This commit is contained in:
2021-10-14 13:47:35 +02:00
commit 6625a8dfaa
4026 changed files with 844291 additions and 0 deletions
@@ -0,0 +1,969 @@
#if defined(TARGET_HAS_ThirdPartyGNEEDaccessAPI)
#include "ovasCConfigurationgNautilusInterface.h"
namespace OpenViBE {
namespace AcquisitionServer {
/*_________________________________________________
Insert callback to specific widget here
Example with a button that launch a calibration of the device:
*/
//Callback connected to a dedicated gtk button (button_select_channels_bipolar_car_noise):
static void ChannelSettingsCB(GtkButton* button, void* data) { static_cast<CConfigurationgNautilusInterface*>(data)->buttonChannelSettingsPressedCB(); }
//Callback connected to a dedicated gtk button (button_select_sensitivity_filters):
static void SensitivityFiltersCB(GtkButton* button, void* data) { static_cast<CConfigurationgNautilusInterface*>(data)->buttonSensitivityFiltersPressedCB(); }
//Callback connected to a dedicated gtk button (button_sensitivity_filters_apply):
static void SensitivityFiltersApplyCB(GtkButton* button, void* data)
{
static_cast<CConfigurationgNautilusInterface*>(data)->buttonSensitivityFiltersApplyPressedCB();
}
//Callback connected to a dedicated gtk button (button_channel_apply):
static void ChannelSettingsApplyCB(GtkButton* button, void* data)
{
static_cast<CConfigurationgNautilusInterface*>(data)->buttonChannelSettingsApplyPressedCB();
}
//Callback actually called:
void CConfigurationgNautilusInterface::buttonChannelSettingsPressedCB()
{
// Connect to the hardware, ask for calibration, verify the return code, etc.
GtkWidget* dialog = GTK_WIDGET(gtk_builder_get_object(m_builder,"dialog_select_channels_bipolar_car_noise"));
gint resp = gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_hide(dialog);
}
//Callback actually called:
void CConfigurationgNautilusInterface::buttonSensitivityFiltersPressedCB()
{
// get bandpass and notch filters for currenty selected sampling rate and set to filter list in corresponding dialog
GtkWidget* dialog = GTK_WIDGET(gtk_builder_get_object(m_builder,"dialog_sensitivity_filters"));
gint resp = gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_hide(dialog);
}
//Callback actually called:
void CConfigurationgNautilusInterface::buttonSensitivityFiltersApplyPressedCB()
{
// get handle to sensitivity and filters dialog and close it
GtkWidget* dialog = GTK_WIDGET(gtk_builder_get_object(m_builder,"dialog_sensitivity_filters"));
gtk_widget_hide(dialog);
}
//Callback actually called:
void CConfigurationgNautilusInterface::buttonChannelSettingsApplyPressedCB()
{
// get handle to channel settings dialog and close it
GtkWidget* dialog = GTK_WIDGET(gtk_builder_get_object(m_builder,"dialog_select_channels_bipolar_car_noise"));
gtk_widget_hide(dialog);
// get number of channels selected and set range as number of channels starting at number of channels
uint16_t nChannels = 0;
char tmp[30];
for (uint32_t i = 0; i < GDS_GNAUTILUS_CHANNELS_MAX; ++i)
{
// set electrode names as channel names in channel selection dialog
sprintf_s(&tmp[0], 30, "checkbutton_channel_%d", (i + 1));
GtkButton* checkButton = GTK_BUTTON(gtk_builder_get_object(m_builder,tmp));
if (checkButton)
{
if ((gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkButton))) && (gtk_widget_get_visible(GTK_WIDGET(checkButton)))) { nChannels += 1; }
}
}
GtkSpinButton* button = GTK_SPIN_BUTTON(gtk_builder_get_object(m_builder,"spinbutton_number_of_channels"));
gtk_spin_button_set_range(button, nChannels, nChannels);
gtk_spin_button_set_value(button, nChannels);
}
// catch combobox sampling rate changed signal and call function which handles event
static void sample_rate_changed_cb(GtkComboBox* comboBox, void* data) { static_cast<CConfigurationgNautilusInterface*>(data)->comboboxSampleRateChangedCB(); }
// Callback actually called
void CConfigurationgNautilusInterface::comboboxSampleRateChangedCB()
{
// get hardware filters according to sampling frequency currently selected
const bool res = getFiltersForNewSamplingRate();
if (!res) { } // error logged in getFiltersForNewSamplingRate
}
// catch noise reduction checkbox toggled signal and call function which handles event
static void noise_reduction_changed_cb(GtkCheckButton* pCheckbutton, void* data)
{
static_cast<CConfigurationgNautilusInterface*>(data)->checkbuttonNoiseReductionChangedCB();
}
// Callback actually called
void CConfigurationgNautilusInterface::checkbuttonNoiseReductionChangedCB()
{
// activate/deactivate noise reduction checkboxes in dialog_select_channels_bipolar_car_noise
GtkCheckButton* buttonNoise = GTK_CHECK_BUTTON(gtk_builder_get_object(m_builder,"checkbutton_noise_reduction"));
const gboolean buttonValue = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(buttonNoise));
char tmp[45];
for (uint16_t i = 0; i < GDS_GNAUTILUS_CHANNELS_MAX; ++i)
{
sprintf_s(&tmp[0], 45, "checkbutton_noise_channel_%d", (i + 1));
GtkCheckButton* buttonNoiseChannel = GTK_CHECK_BUTTON(gtk_builder_get_object(m_builder,tmp));
if (buttonNoiseChannel)
{
if (gtk_widget_get_visible(GTK_WIDGET(buttonNoiseChannel))) { gtk_widget_set_sensitive(GTK_WIDGET(buttonNoiseChannel), buttonValue); }
}
}
}
// catch car checkbox toggled signal and call function which handles event
static void car_changed_cb(GtkCheckButton* /*button*/, void* data) { static_cast<CConfigurationgNautilusInterface*>(data)->checkbuttonCARChangedCB(); }
// Callback actually called
void CConfigurationgNautilusInterface::checkbuttonCARChangedCB()
{
// activate/deactivate car checkboxes in dialog_select_channels_bipolar_car_noise
GtkCheckButton* buttonCAR = GTK_CHECK_BUTTON(gtk_builder_get_object(m_builder,"checkbutton_car"));
const gboolean buttonValue = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(buttonCAR));
char tmp[45];
for (uint16_t i = 0; i < GDS_GNAUTILUS_CHANNELS_MAX; ++i)
{
sprintf_s(&tmp[0], 45, "checkbutton_car_channel_%d", (i + 1));
GtkCheckButton* buttonCarChannel = GTK_CHECK_BUTTON(gtk_builder_get_object(m_builder,tmp));
if (buttonCarChannel)
{
if (gtk_widget_get_visible(GTK_WIDGET(buttonCarChannel))) { gtk_widget_set_sensitive(GTK_WIDGET(buttonCarChannel), buttonValue); }
}
}
}
// get hardware related settings from GDS
bool CConfigurationgNautilusInterface::getHardwareSettings()
{
GtkTreeIter iter;
uint32_t i;
// get network channel and set in dialog and set one as active in dialog
size_t supportedNwChannelsCount;
// get number of supported network channels to allocate memory to hold supported network channels
m_gdsResult = GDS_GNAUTILUS_GetSupportedNetworkChannels(m_deviceHandle, m_deviceNames, nullptr, &supportedNwChannelsCount);
if (m_gdsResult.ErrorCode != GDS_ERROR_SUCCESS)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << m_gdsResult.ErrorMessage << "\n";
return false;
}
uint32_t* supportedNwChannels = new uint32_t[supportedNwChannelsCount];
m_gdsResult = GDS_GNAUTILUS_GetSupportedNetworkChannels(m_deviceHandle, m_deviceNames, supportedNwChannels, &supportedNwChannelsCount);
if (m_gdsResult.ErrorCode != GDS_ERROR_SUCCESS)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << m_gdsResult.ErrorMessage << "\n";
return false;
}
// get network channel currently used between base station and headstage
uint32_t val;
m_gdsResult = GDS_GNAUTILUS_GetNetworkChannel(m_deviceHandle, m_deviceNames, &val);
if (m_gdsResult.ErrorCode != GDS_ERROR_SUCCESS)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << m_gdsResult.ErrorMessage << "\n";
return false;
}
// put network channels to combobox
GtkComboBox* comboBoxNetworkChannel = GTK_COMBO_BOX(gtk_builder_get_object(m_builder, "combobox_network_channel"));
GtkTreeModel* listStoreNetworkChannel = gtk_combo_box_get_model(comboBoxNetworkChannel);
gtk_list_store_clear(GTK_LIST_STORE(listStoreNetworkChannel));
std::stringstream networkChannel;
if (m_comboBoxNetworkChannels.size() > 0) m_comboBoxNetworkChannels.clear();
// fill network channel combobox with available network channels
for (i = 0; i < supportedNwChannelsCount; ++i)
{
networkChannel << supportedNwChannels[i];
gtk_list_store_append(GTK_LIST_STORE(listStoreNetworkChannel), &iter);
gtk_list_store_set(GTK_LIST_STORE(listStoreNetworkChannel), &iter, 0, networkChannel.str().c_str(), -1);
networkChannel.clear();
networkChannel.str("");
m_comboBoxNetworkChannels.push_back(supportedNwChannels[i]);
}
const auto it = find(m_comboBoxNetworkChannels.begin(), m_comboBoxNetworkChannels.end(), val);
const size_t nwChIndex = distance(m_comboBoxNetworkChannels.begin(), it);
gtk_combo_box_set_active(comboBoxNetworkChannel, nwChIndex);
delete [] supportedNwChannels;
// get supported sample rates
size_t nSampling;
// get number of supported sample rates
m_gdsResult = GDS_GNAUTILUS_GetSupportedSamplingRates(m_deviceHandle, m_deviceNames, nullptr, &nSampling);
if (m_gdsResult.ErrorCode != GDS_ERROR_SUCCESS)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << m_gdsResult.ErrorMessage << "\n";
return false;
}
uint32_t* sampling = new uint32_t[nSampling];
// get supported sample rates
m_gdsResult = GDS_GNAUTILUS_GetSupportedSamplingRates(m_deviceHandle, m_deviceNames, sampling, &nSampling);
if (m_gdsResult.ErrorCode != GDS_ERROR_SUCCESS)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << m_gdsResult.ErrorMessage << "\n";
return false;
}
// set sample rates as content of combo box in corresponding dialog
GtkComboBox* comboBoxSamplings = GTK_COMBO_BOX(gtk_builder_get_object(m_builder, "combobox_sampling_frequency"));
GtkTreeModel* listStoreSamplings = gtk_combo_box_get_model(comboBoxSamplings);
gtk_list_store_clear(GTK_LIST_STORE(listStoreSamplings));
for (i = 0; i < nSampling; ++i)
{
std::string str = std::to_string(sampling[i]);
gtk_list_store_append(GTK_LIST_STORE(listStoreSamplings), &iter);
gtk_list_store_set(GTK_LIST_STORE(listStoreSamplings), &iter, 0, str.c_str(), -1);
}
gtk_combo_box_set_active(comboBoxSamplings, 0);
const bool functionReturn = getFiltersForNewSamplingRate();
if (!functionReturn) { return false; }
size_t nSensitivities;
// get number of sensitivities
m_gdsResult = GDS_GNAUTILUS_GetSupportedSensitivities(m_deviceHandle, m_deviceNames, nullptr, &nSensitivities);
if (m_gdsResult.ErrorCode != GDS_ERROR_SUCCESS)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << m_gdsResult.ErrorMessage << "\n";
return false;
}
// get sensitivities
double* sensitivities = new double[nSensitivities];
m_gdsResult = GDS_GNAUTILUS_GetSupportedSensitivities(m_deviceHandle, m_deviceNames, sensitivities, &nSensitivities);
if (m_gdsResult.ErrorCode != GDS_ERROR_SUCCESS)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << m_gdsResult.ErrorMessage << "\n";
return false;
}
// set items in dialog item combobox_select_sensitivity
GtkComboBox* comboBoxSensitivities = GTK_COMBO_BOX(gtk_builder_get_object(m_builder, "combobox_select_sensitivity"));
GtkTreeModel* listStoreSensitivities = gtk_combo_box_get_model(comboBoxSensitivities);
gtk_list_store_clear(GTK_LIST_STORE(listStoreSensitivities));
for (i = 0; i < nSensitivities; ++i)
{
std::string str = std::to_string(sensitivities[i] / 1000);
gtk_list_store_append(GTK_LIST_STORE(listStoreSensitivities), &iter);
gtk_list_store_set(GTK_LIST_STORE(listStoreSensitivities), &iter, 0, str.c_str(), -1);
m_comboBoxSensitivityValues.push_back(sensitivities[i]);
}
gtk_combo_box_set_active(comboBoxSensitivities, 0);
delete [] sensitivities;
size_t nInputSources;
// first get number of supported input sources (call with third parameter set to NULL)
m_gdsResult = GDS_GNAUTILUS_GetSupportedInputSources(m_deviceHandle, m_deviceNames, nullptr, &nInputSources);
if (m_gdsResult.ErrorCode != GDS_ERROR_SUCCESS)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << m_gdsResult.ErrorMessage << "\n";
return false;
}
// allocate memory to hold input sources
GDS_GNAUTILUS_INPUT_SIGNAL* inputSources = new GDS_GNAUTILUS_INPUT_SIGNAL[nInputSources];
// now get input sources
m_gdsResult = GDS_GNAUTILUS_GetSupportedInputSources(m_deviceHandle, m_deviceNames, inputSources, &nInputSources);
if (m_gdsResult.ErrorCode != GDS_ERROR_SUCCESS)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << m_gdsResult.ErrorMessage << "\n";
return false;
}
// set values to combobox_input_source (there are only three allowed at the moment, see code below)
GtkComboBox* comboBoxInputSources = GTK_COMBO_BOX(gtk_builder_get_object(m_builder, "combobox_input_source"));
GtkTreeModel* listStoreInputSources = gtk_combo_box_get_model(comboBoxInputSources);
gtk_list_store_clear(GTK_LIST_STORE(listStoreInputSources));
for (i = 0; i < nInputSources; ++i)
{
if (inputSources[i] == 0)
{
// electrode input
m_comboBoxInputSources.push_back(inputSources[i]);
gtk_list_store_append(GTK_LIST_STORE(listStoreInputSources), &iter);
gtk_list_store_set(GTK_LIST_STORE(listStoreInputSources), &iter, 0, "Electrode", -1);
}
else if (inputSources[i] == 1)
{
// shortcut
m_comboBoxInputSources.push_back(inputSources[i]);
gtk_list_store_append(GTK_LIST_STORE(listStoreInputSources), &iter);
gtk_list_store_set(GTK_LIST_STORE(listStoreInputSources), &iter, 0, "Shortcut", -1);
}
else if (inputSources[i] == 5)
{
// test signal
m_comboBoxInputSources.push_back(inputSources[i]);
gtk_list_store_append(GTK_LIST_STORE(listStoreInputSources), &iter);
gtk_list_store_set(GTK_LIST_STORE(listStoreInputSources), &iter, 0, "Test Signal", -1);
}
}
gtk_combo_box_set_active(comboBoxInputSources, 0);
return true;
}
// get channel names for hardware currently connected (cannot be changed as electrode grid is fixed)
bool CConfigurationgNautilusInterface::getChannelNames()
{
uint32_t nMountedModules;
size_t nElectrodeNames;
char tmp[30];
std::stringstream bipolarEntry;
// get number of mounted modules and electrode names currently available
nMountedModules = 0;
nElectrodeNames = 0;
m_gdsResult = GDS_GNAUTILUS_GetChannelNames(m_deviceHandle, m_deviceNames, &nMountedModules,NULL, &nElectrodeNames);
if (m_gdsResult.ErrorCode != GDS_ERROR_SUCCESS)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << m_gdsResult.ErrorMessage << "\n";
return false;
}
// set array of electrode names according to names currently available
char (*electrodeNames)[GDS_GNAUTILUS_ELECTRODE_NAME_LENGTH_MAX] = new char[nElectrodeNames][GDS_GNAUTILUS_ELECTRODE_NAME_LENGTH_MAX];
// get electrode names
m_gdsResult = GDS_GNAUTILUS_GetChannelNames(m_deviceHandle, m_deviceNames, &nMountedModules, electrodeNames, &nElectrodeNames);
if (m_gdsResult.ErrorCode != GDS_ERROR_SUCCESS)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << m_gdsResult.ErrorMessage << "\n";
return false;
}
GtkComboBox* comboBoxBipolarChannels = GTK_COMBO_BOX(gtk_builder_get_object(m_builder,"combobox_channel_1"));
GtkTreeModel* listStoreBipolarChannels = gtk_combo_box_get_model(comboBoxBipolarChannels);
gtk_list_store_clear(GTK_LIST_STORE(listStoreBipolarChannels));
bipolarEntry << "none";
GtkTreeIter it;
gtk_list_store_append(GTK_LIST_STORE(listStoreBipolarChannels), &it);
gtk_list_store_set(GTK_LIST_STORE(listStoreBipolarChannels), &it, 0, bipolarEntry.str().c_str(), -1);
for (uint16_t i = 0; i < GDS_GNAUTILUS_CHANNELS_MAX; ++i)
{
// set electrode names as channel names in channel selection dialog
sprintf_s(&tmp[0], 30, "checkbutton_channel_%d", (i + 1));
GtkButton* buttonChannel = GTK_BUTTON(gtk_builder_get_object(m_builder,tmp));
if ((buttonChannel) && (i < nElectrodeNames))
{
gtk_button_set_label(buttonChannel, &electrodeNames[i][0]);
gtk_list_store_append(GTK_LIST_STORE(listStoreBipolarChannels), &it);
gtk_list_store_set(GTK_LIST_STORE(listStoreBipolarChannels), &it, 0, &electrodeNames[i][0], -1);
}
else if ((buttonChannel) && (i >= nElectrodeNames))
{
gtk_widget_set_sensitive(GTK_WIDGET(buttonChannel), false);
gtk_button_set_label(buttonChannel, "");
}
}
for (uint16_t i = 0; i < GDS_GNAUTILUS_CHANNELS_MAX; ++i)
{
sprintf_s(&tmp[0], 30, "combobox_channel_%d", (i + 1));
comboBoxBipolarChannels = GTK_COMBO_BOX(gtk_builder_get_object(m_builder,tmp));
if (comboBoxBipolarChannels)
{
gtk_combo_box_set_model(comboBoxBipolarChannels, listStoreBipolarChannels);
gtk_combo_box_set_active(comboBoxBipolarChannels, 0);
}
}
// adapt number of recorded channels in main configuration dialog according to number of actual selected channels
GtkSpinButton* buttonNChannels = GTK_SPIN_BUTTON(gtk_builder_get_object(m_builder,"spinbutton_number_of_channels"));
gtk_spin_button_set_range(buttonNChannels, nElectrodeNames, nElectrodeNames);
gtk_spin_button_set_value(buttonNChannels, nElectrodeNames);
// set electrode names as channel names
m_channelNames.clear();
for (size_t i = 0; i < nElectrodeNames; ++i) { m_channelNames[i] = electrodeNames[i]; }
delete [] electrodeNames;
return true;
}
// get channels currenly available for g.Nautilus used
bool CConfigurationgNautilusInterface::getAvailableChannels()
{
char tmp[30];
// get channels currently available on connected device
BOOL availableChannels[GDS_GNAUTILUS_CHANNELS_MAX];
m_gdsResult = GDS_GNAUTILUS_GetAvailableChannels(m_deviceHandle, m_deviceNames, &availableChannels);
if (m_gdsResult.ErrorCode != GDS_ERROR_SUCCESS)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << m_gdsResult.ErrorMessage << "\n";
return false;
}
m_availableChannels.resize(GDS_GNAUTILUS_CHANNELS_MAX);
for (uint16_t i = 0; i < GDS_GNAUTILUS_CHANNELS_MAX; ++i)
{
sprintf_s(&tmp[0], 30, "checkbutton_channel_%d", (i + 1));
GtkCheckButton* buttonChannel = GTK_CHECK_BUTTON(gtk_builder_get_object(m_builder,tmp));
sprintf_s(&tmp[0], 30, "label_channel_%d", (i + 1));
GtkLabel* labelChannel = GTK_LABEL(gtk_builder_get_object(m_builder,tmp));
sprintf_s(&tmp[0], 30, "combobox_channel_%d", (i + 1));
GtkComboBox* comboBoxChannel = GTK_COMBO_BOX(gtk_builder_get_object(m_builder,tmp));
sprintf_s(&tmp[0], 30, "checkbutton_car_channel_%d", (i + 1));
GtkCheckButton* buttonCARChannel = GTK_CHECK_BUTTON(gtk_builder_get_object(m_builder,tmp));
sprintf_s(&tmp[0], 30, "checkbutton_noise_channel_%d", (i + 1));
GtkCheckButton* buttonNoiseChannel = GTK_CHECK_BUTTON(gtk_builder_get_object(m_builder,tmp));
if (availableChannels[i] == 1)
{
if (buttonChannel)
{
gtk_widget_set_visible(GTK_WIDGET(buttonChannel), true);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(buttonChannel), true);
gtk_widget_set_visible(GTK_WIDGET(labelChannel), true);
gtk_widget_set_visible(GTK_WIDGET(comboBoxChannel), true);
gtk_widget_set_visible(GTK_WIDGET(buttonCARChannel), true);
gtk_widget_set_visible(GTK_WIDGET(buttonNoiseChannel), true);
}
m_availableChannels[i] = true;
}
else
{
if (buttonChannel)
{
gtk_widget_set_visible(GTK_WIDGET(buttonChannel), false);
gtk_widget_set_visible(GTK_WIDGET(labelChannel), false);
gtk_widget_set_visible(GTK_WIDGET(comboBoxChannel), false);
gtk_widget_set_visible(GTK_WIDGET(buttonCARChannel), false);
gtk_widget_set_visible(GTK_WIDGET(buttonNoiseChannel), false);
}
m_availableChannels[i] = false;
}
}
return true;
}
// if sampling rate changed filters in filter settings dialog have to be updated according to new sampling rate
bool CConfigurationgNautilusInterface::getFiltersForNewSamplingRate()
{
GtkTreeIter iter;
// get current sample rate
GtkComboBox* comboBoxSampling = GTK_COMBO_BOX(gtk_builder_get_object(m_builder, "combobox_sampling_frequency"));
const char* sSampling = gtk_combo_box_get_active_text(comboBoxSampling);
double sampling = atof(sSampling);
size_t nBandPassFilters, nNotchFilters;
std::stringstream filterDesc;
filterDesc << "no bandpass filter";
// get number of bandpass filters and allocate filter array correspondingly
m_gdsResult = GDS_GNAUTILUS_GetBandpassFilters(m_deviceHandle, m_deviceNames, nullptr, &nBandPassFilters);
if (m_gdsResult.ErrorCode != GDS_ERROR_SUCCESS)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << m_gdsResult.ErrorMessage << "\n";
return false;
}
GDS_FILTER_INFO* bandPassFilters = new GDS_FILTER_INFO[nBandPassFilters];
// get bandpass filters
m_gdsResult = GDS_GNAUTILUS_GetBandpassFilters(m_deviceHandle, m_deviceNames, bandPassFilters, &nBandPassFilters);
if (m_gdsResult.ErrorCode != GDS_ERROR_SUCCESS)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << m_gdsResult.ErrorMessage;
return false;
}
// get number of notch filters and allocate filter array correspondingly
m_gdsResult = GDS_GNAUTILUS_GetNotchFilters(m_deviceHandle, m_deviceNames, nullptr, &nNotchFilters);
if (m_gdsResult.ErrorCode != GDS_ERROR_SUCCESS)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << m_gdsResult.ErrorMessage << "\n";
return false;
}
GDS_FILTER_INFO* notchFilters = new GDS_FILTER_INFO[nNotchFilters];
// get notch filters
m_gdsResult = GDS_GNAUTILUS_GetNotchFilters(m_deviceHandle, m_deviceNames, notchFilters, &nNotchFilters);
if (m_gdsResult.ErrorCode != GDS_ERROR_SUCCESS)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << m_gdsResult.ErrorMessage << "\n";
return false;
}
// set filters as combobox entries depending on the current sample rate selected
GtkComboBox* comboBoxBandPass = GTK_COMBO_BOX(gtk_builder_get_object(m_builder,"combobox_select_bandpass_filter"));
GtkTreeModel* listStoreBandPass = gtk_combo_box_get_model(comboBoxBandPass);
gtk_list_store_clear(GTK_LIST_STORE(listStoreBandPass));
GtkComboBox* comboBoxNotch = GTK_COMBO_BOX(gtk_builder_get_object(m_builder,"combobox_select_notch_filter"));
GtkTreeModel* listStoreNotch = gtk_combo_box_get_model(comboBoxNotch);
gtk_list_store_clear(GTK_LIST_STORE(listStoreNotch));
if (m_comboBoxBandpassFilterIdx.size() > 0) m_comboBoxBandpassFilterIdx.clear();
if (m_comboBoxNotchFilterIdx.size() > 0) m_comboBoxNotchFilterIdx.clear();
if (m_comboBoxSensitivityValues.size() > 0) m_comboBoxSensitivityValues.clear();
// fill bandpass filter combobox with available filters
gtk_list_store_append(GTK_LIST_STORE(listStoreBandPass), &iter);
gtk_list_store_set(GTK_LIST_STORE(listStoreBandPass), &iter, 0, filterDesc.str().c_str(), -1);
filterDesc.clear();
filterDesc.str("");
m_comboBoxBandpassFilterIdx.push_back(-1);
for (size_t i = 0; i < nBandPassFilters; ++i)
{
if (sampling == bandPassFilters[i].SamplingRate)
{
if (bandPassFilters[i].TypeId == 1) filterDesc << "Butterworth - ";
if (bandPassFilters[i].TypeId == 2) filterDesc << "Chebyshev - ";
filterDesc << bandPassFilters[i].Order << " - [";
filterDesc << bandPassFilters[i].LowerCutoffFrequency << "; ";
filterDesc << bandPassFilters[i].UpperCutoffFrequency << "] - ";
filterDesc << bandPassFilters[i].SamplingRate;
gtk_list_store_append(GTK_LIST_STORE(listStoreBandPass), &iter);
gtk_list_store_set(GTK_LIST_STORE(listStoreBandPass), &iter, 0, filterDesc.str().c_str(), -1);
m_comboBoxBandpassFilterIdx.push_back(i);
}
filterDesc.clear();
filterDesc.str("");
}
gtk_combo_box_set_active(comboBoxBandPass, m_bandpassFilterIdx + 1); // +1 because -1 is for "no filter".
// fill notch filter combobox with available fliters
filterDesc << "no notch filter";
gtk_list_store_append(GTK_LIST_STORE(listStoreNotch), &iter);
gtk_list_store_set(GTK_LIST_STORE(listStoreNotch), &iter, 0, filterDesc.str().c_str(), -1);
filterDesc.clear();
filterDesc.str("");
m_comboBoxNotchFilterIdx.push_back(-1);
for (size_t i = 0; i < nNotchFilters; ++i)
{
if (sampling == notchFilters[i].SamplingRate)
{
if (notchFilters[i].TypeId == 1) filterDesc << "Butterworth - ";
if (notchFilters[i].TypeId == 2) filterDesc << "Chebyshev - ";
filterDesc << notchFilters[i].Order << " - [";
filterDesc << notchFilters[i].LowerCutoffFrequency << "; ";
filterDesc << notchFilters[i].UpperCutoffFrequency << "] - ";
filterDesc << notchFilters[i].SamplingRate;
gtk_list_store_append(GTK_LIST_STORE(listStoreNotch), &iter);
gtk_list_store_set(GTK_LIST_STORE(listStoreNotch), &iter, 0, filterDesc.str().c_str(), -1);
m_comboBoxNotchFilterIdx.push_back(i);
}
filterDesc.clear();
filterDesc.str("");
}
gtk_combo_box_set_active(comboBoxNotch, m_notchFilterIdx + 1); // +1 because -1 is for "no filter".
delete [] bandPassFilters;
delete [] notchFilters;
return true;
}
// If you added more reference attribute, initialize them here
CConfigurationgNautilusInterface::CConfigurationgNautilusInterface(IDriverContext& ctx, const char* gtkBuilderFilename, std::string& deviceSerial,
int& inputSource, uint32_t& networkChannel, int& bandpassFilterIdx, int& notchFilterIdx,
double& sensitivity, bool& digitalInputEnabled, bool& noiseReductionEnabled,
bool& carEnabled, bool& accelerationDataEnabled, bool& counterEnabled,
bool& linkQualityEnabled, bool& batteryLevelEnabled, bool& validationIndicatorEnabled,
std::vector<uint16_t>& selectedChannels, std::vector<int>& bipolarChannels,
std::vector<bool>& cars, std::vector<bool>& noiseReduction)
: CConfigurationBuilder(gtkBuilderFilename), m_driverCtx(ctx), m_deviceSerial(deviceSerial), m_inputSource(inputSource), m_networkChannel(networkChannel),
m_bandpassFilterIdx(bandpassFilterIdx), m_notchFilterIdx(notchFilterIdx), m_sensitivity(sensitivity), m_digitalInputEnabled(digitalInputEnabled),
m_noiseReductionEnabled(noiseReductionEnabled), m_carEnabled(carEnabled), m_accelerationDataEnabled(accelerationDataEnabled),
m_counterEnabled(counterEnabled), m_linkQualityEnabled(linkQualityEnabled), m_batteryLevelEnabled(batteryLevelEnabled),
m_validationIndicatorEnabled(validationIndicatorEnabled), m_selectedChannels(selectedChannels), m_bipolarChannels(bipolarChannels), m_cars(cars),
m_noiseReduction(noiseReduction) { m_connectionOpen = false; }
bool CConfigurationgNautilusInterface::preConfigure()
{
if (! CConfigurationBuilder::preConfigure()) { return false; }
// Connect here all callbacks
// Example:
// g_signal_connect(gtk_builder_get_object(m_builder, "button_calibrate"), "pressed", G_CALLBACK(button_calibrate_pressed_cb), this);
// Insert here the pre-configure code.
// For example, you may want to check if a device is currently connected
// and if more than one are connected. Then you can list in a dedicated combo-box
// the device currently connected so the user can choose which one he wants to acquire from.
bool functionReturn;
// open connection to device if not done yet before reading filters, channel names etc.
if (!m_connectionOpen)
{
// open device handle and get connected device
functionReturn = openDevice();
if (!functionReturn) { return false; } // error logged in openDevice;
}
// get settings for connected hardware
functionReturn = getHardwareSettings();
if (!functionReturn) { return false; }
// error logged in getHardwareSettings
// get available channels
functionReturn = getAvailableChannels();
if (!functionReturn) { return false; } // error logged in getAvailableChannels
functionReturn = getChannelNames();
if (!functionReturn) { return false; } // error logged in getChannelNames
// activate checkboxes in g.Nautilus Configuration dialog
GtkCheckButton* buttonEventChannel = GTK_CHECK_BUTTON(gtk_builder_get_object(m_builder, "checkbutton_event_channel"));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(buttonEventChannel), m_digitalInputEnabled);
GtkCheckButton* buttonNoiseReduction = GTK_CHECK_BUTTON(gtk_builder_get_object(m_builder, "checkbutton_noise_reduction"));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(buttonNoiseReduction), m_noiseReductionEnabled);
GtkCheckButton* buttonCAR = GTK_CHECK_BUTTON(gtk_builder_get_object(m_builder, "checkbutton_car"));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(buttonCAR), m_carEnabled);
// activate/deactivate channel, noise reduction and CAR checkboxes in dialog_select_channels_bipolar_car_noise
// as well as bipolar combo boxes according to available channels
const gboolean noiseReduction = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(buttonNoiseReduction));
const gboolean car = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(buttonCAR));
char tmp[45];
for (uint16_t i = 0; i < GDS_GNAUTILUS_CHANNELS_MAX; ++i)
{
sprintf_s(&tmp[0], 45, "checkbutton_channel_%d", (i + 1));
GtkCheckButton* button = GTK_CHECK_BUTTON(gtk_builder_get_object(m_builder,tmp));
if ((button) && (m_availableChannels[i])) gtk_widget_set_sensitive(GTK_WIDGET(button), true);
else if (button) gtk_widget_set_sensitive(GTK_WIDGET(button), false);
sprintf_s(&tmp[0], 45, "checkbutton_noise_channel_%d", (i + 1));
button = GTK_CHECK_BUTTON(gtk_builder_get_object(m_builder,tmp));
if ((button) && (m_availableChannels[i])) gtk_widget_set_sensitive(GTK_WIDGET(button), noiseReduction);
else if (button) gtk_widget_set_sensitive(GTK_WIDGET(button), false);
sprintf_s(&tmp[0], 45, "checkbutton_car_channel_%d", (i + 1));
button = GTK_CHECK_BUTTON(gtk_builder_get_object(m_builder,tmp));
if ((button) && (m_availableChannels[i])) gtk_widget_set_sensitive(GTK_WIDGET(button), car);
else if (button) gtk_widget_set_sensitive(GTK_WIDGET(button), false);
sprintf_s(&tmp[0], 45, "combobox_channel_%d", (i + 1));
GtkComboBox* comboBox = GTK_COMBO_BOX(gtk_builder_get_object(m_builder,tmp));
if ((comboBox) && (m_availableChannels[i])) gtk_widget_set_sensitive(GTK_WIDGET(comboBox), true);
else if (comboBox) gtk_widget_set_sensitive(GTK_WIDGET(comboBox), false);
}
GtkCheckButton* accelerationData = GTK_CHECK_BUTTON(gtk_builder_get_object(m_builder, "checkbutton_acceleration_data"));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(accelerationData), m_accelerationDataEnabled);
GtkCheckButton* counter = GTK_CHECK_BUTTON(gtk_builder_get_object(m_builder, "checkbutton_counter"));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(counter), m_counterEnabled);
GtkCheckButton* linkQuality = GTK_CHECK_BUTTON(gtk_builder_get_object(m_builder, "checkbutton_link_quality"));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linkQuality), m_linkQualityEnabled);
GtkCheckButton* batteryLevel = GTK_CHECK_BUTTON(gtk_builder_get_object(m_builder, "checkbutton_battery_level"));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(batteryLevel), m_batteryLevelEnabled);
GtkCheckButton* validationIndicator = GTK_CHECK_BUTTON(
gtk_builder_get_object(m_builder, "checkbutton_validation_indicator"));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(validationIndicator), m_validationIndicatorEnabled);
g_signal_connect(gtk_builder_get_object(m_builder,"button_select_channels_bipolar_car_noise"), "pressed", G_CALLBACK(ChannelSettingsCB), this);
g_signal_connect(gtk_builder_get_object(m_builder,"button_select_sensitivity_filters"), "pressed", G_CALLBACK(SensitivityFiltersCB), this);
g_signal_connect(gtk_builder_get_object(m_builder,"button_select_sensitivity_filters_apply"), "pressed", G_CALLBACK(SensitivityFiltersApplyCB), this);
g_signal_connect(gtk_builder_get_object(m_builder,"button_channel_apply"), "pressed", G_CALLBACK(ChannelSettingsApplyCB), this);
// set device serial in device serial text entry in g.Nautilus Configuration dialog
GtkEntry* deviceSerial = GTK_ENTRY(gtk_builder_get_object(m_builder, "entry_device_serial"));
gtk_entry_set_text(deviceSerial, m_deviceSerial.c_str());
gtk_entry_set_editable(deviceSerial, false);
// deactivate buttons if no device is detected
if (gtk_entry_get_text_length(deviceSerial) < 13)
{
GtkWidget* button = GTK_WIDGET(gtk_builder_get_object(m_builder,"button_select_channels_bipolar_car_noise"));
gtk_widget_set_sensitive(button, false);
button = GTK_WIDGET(gtk_builder_get_object(m_builder,"button_select_sensitivity_filters"));
gtk_widget_set_sensitive(button, false);
}
// catch event when sample rate is changed to adjust available filters
g_signal_connect(gtk_builder_get_object(m_builder, "combobox_sampling_frequency"), "changed", G_CALLBACK(sample_rate_changed_cb), this);
// catch events when car and noise reduction checkboxes are toggled in main config dialog to enable/disable corresponding checkboxes in related dialog
g_signal_connect(gtk_builder_get_object(m_builder, "checkbutton_noise_reduction"), "toggled", G_CALLBACK(noise_reduction_changed_cb), this);
g_signal_connect(gtk_builder_get_object(m_builder, "checkbutton_car"), "toggled", G_CALLBACK(car_changed_cb), this);
return true;
}
bool CConfigurationgNautilusInterface::postConfigure()
{
if (m_applyConfig)
{
// If the user pressed the "apply" button, you need to save the changes made in the configuration.
// For example, you can save the connection ID of the selected device:
// m_connectionID = <value-from-gtk-widget>
GtkCheckButton* checkButton;
uint16_t i;
gboolean buttonValue = false;
gdouble nChannels = 0;
// get serial number from configuration dialog
GtkEntry* entrySerial = GTK_ENTRY(gtk_builder_get_object(m_builder, "entry_device_serial"));
m_deviceSerial = gtk_entry_get_text(entrySerial);
// get selected input source from dialog
GtkComboBox* inputSources = GTK_COMBO_BOX(gtk_builder_get_object(m_builder, "combobox_input_source"));
size_t idx = gtk_combo_box_get_active(inputSources);
m_inputSource = m_comboBoxInputSources[idx];
// get selected channels
char tmp[45];
m_selectedChannels.clear();
for (i = 0; i < GDS_GNAUTILUS_CHANNELS_MAX; ++i)
{
sprintf_s(&tmp[0], 45, "checkbutton_channel_%d", (i + 1));
checkButton = GTK_CHECK_BUTTON(gtk_builder_get_object(m_builder,tmp));
if (checkButton)
{
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkButton)))
{
m_selectedChannels.push_back(i + 1);
nChannels += 1;
}
else
{
m_selectedChannels.push_back(0);
m_channelNames.erase(i);
}
}
}
// get bipolar channels
m_bipolarChannels.clear();
for (i = 0; i < GDS_GNAUTILUS_CHANNELS_MAX; ++i)
{
sprintf_s(&tmp[0], 45, "combobox_channel_%d", (i + 1));
GtkComboBox* bipolarChannels = GTK_COMBO_BOX(gtk_builder_get_object(m_builder,tmp));
if (bipolarChannels)
{
// bipolar is 0 based for the channels, -1 indicates no bipolar derivation
m_bipolarChannels.push_back(gtk_combo_box_get_active(bipolarChannels) - 1);
}
}
// set bandpass and notch filter indices to correponding variables
GtkComboBox* bandpassFilters = GTK_COMBO_BOX(gtk_builder_get_object(m_builder,"combobox_select_bandpass_filter"));
idx = gtk_combo_box_get_active(bandpassFilters);
m_bandpassFilterIdx = m_comboBoxBandpassFilterIdx.at(idx);
GtkComboBox* notchFilters = GTK_COMBO_BOX(gtk_builder_get_object(m_builder,"combobox_select_notch_filter"));
idx = gtk_combo_box_get_active(notchFilters);
m_notchFilterIdx = m_comboBoxNotchFilterIdx.at(idx);
// sensitivity
GtkComboBox* sensitivities = GTK_COMBO_BOX(gtk_builder_get_object(m_builder,"combobox_select_sensitivity"));
idx = gtk_combo_box_get_active(sensitivities);
m_sensitivity = m_comboBoxSensitivityValues.at(idx);
// digital inputs
checkButton = GTK_CHECK_BUTTON(gtk_builder_get_object(m_builder,"checkbutton_event_channel"));
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkButton)) == 1) { m_digitalInputEnabled = true; }
else { m_digitalInputEnabled = false; }
// noise reduction
checkButton = GTK_CHECK_BUTTON(gtk_builder_get_object(m_builder,"checkbutton_noise_reduction"));
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkButton)) == 1) { m_noiseReductionEnabled = true; }
else { m_noiseReductionEnabled = false; }
// if noise reduction is active, check for which channels noise reduction is enabled
m_noiseReduction.clear();
for (i = 0; i < GDS_GNAUTILUS_CHANNELS_MAX; ++i)
{
sprintf_s(&tmp[0], 45, "checkbutton_noise_channel_%d", (i + 1));
checkButton = GTK_CHECK_BUTTON(gtk_builder_get_object(m_builder,tmp));
if (checkButton)
{
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkButton)) == 1) { m_noiseReduction.push_back(true); }
else { m_noiseReduction.push_back(false); }
}
}
// CAR
checkButton = GTK_CHECK_BUTTON(gtk_builder_get_object(m_builder,"checkbutton_car"));
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkButton)) == 1) m_carEnabled = true;
else m_carEnabled = false;
// if CAR is active, check for which channels CAR is enabled
m_cars.clear();
for (i = 0; i < GDS_GNAUTILUS_CHANNELS_MAX; ++i)
{
sprintf_s(&tmp[0], 45, "checkbutton_car_channel_%d", (i + 1));
checkButton = GTK_CHECK_BUTTON(gtk_builder_get_object(m_builder,tmp));
if (checkButton)
{
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkButton)) == 1) m_cars.push_back(true);
else m_cars.push_back(false);
}
}
// acceleration data
checkButton = GTK_CHECK_BUTTON(gtk_builder_get_object(m_builder,"checkbutton_acceleration_data"));
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkButton)) == 1) { m_accelerationDataEnabled = true; }
else { m_accelerationDataEnabled = false; }
// counter
checkButton = GTK_CHECK_BUTTON(gtk_builder_get_object(m_builder,"checkbutton_counter"));
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkButton)) == 1) { m_counterEnabled = true; }
else { m_counterEnabled = false; }
// link quality
checkButton = GTK_CHECK_BUTTON(gtk_builder_get_object(m_builder,"checkbutton_link_quality"));
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkButton)) == 1) { m_linkQualityEnabled = true; }
else { m_linkQualityEnabled = false; }
// battery level
checkButton = GTK_CHECK_BUTTON(gtk_builder_get_object(m_builder,"checkbutton_battery_level"));
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkButton)) == 1) { m_batteryLevelEnabled = true; }
else { m_batteryLevelEnabled = false; }
// validation indicator
checkButton = GTK_CHECK_BUTTON(gtk_builder_get_object(m_builder,"checkbutton_validation_indicator"));
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkButton)) == 1) { m_validationIndicatorEnabled = true; }
else { m_validationIndicatorEnabled = false; }
// network channel
GtkComboBox* comboBoxNetworkChannel = GTK_COMBO_BOX(gtk_builder_get_object(m_builder,"combobox_network_channel"));
const char* networkChannel = gtk_combo_box_get_active_text(comboBoxNetworkChannel);
m_networkChannel = uint32_t(atoi(networkChannel));
// set number of channels in main configuration dialog (spinbutton still remains disabled, user cannot change value there)
GtkSpinButton* buttonChannels = GTK_SPIN_BUTTON(gtk_builder_get_object(m_builder, "spinbutton_number_of_channels"));
gtk_spin_button_set_value(buttonChannels, nChannels);
gtk_spin_button_set_range(buttonChannels, nChannels, nChannels);
}
if (m_connectionOpen)
{
// close connection handle
const bool functionReturn = closeDevice();
if (!functionReturn)
{
// error logged in closeDevice
return false;
}
}
if (! CConfigurationBuilder::postConfigure()
) { return false; } // normal header is filled (Subject ID, Age, Gender, channels, sampling frequency), ressources are realesed
return true;
}
bool CConfigurationgNautilusInterface::openDevice()
{
GDS_ENDPOINT hostEp, localEp;
GDS_DEVICE_CONNECTION_INFO* connectedDevicesInfo;
size_t nDevices;
std::string deviceSerial;
BOOL openExclusively = true;
BOOL isCreator;
m_deviceNames = new char[1][DEVICE_NAME_LENGTH_MAX];
uint8_t byteIP[4];
byteIP[0] = 1;
byteIP[1] = 0;
byteIP[2] = 0;
byteIP[3] = 127;
char tmpIP[16];
_snprintf_s(tmpIP, IP_ADDRESS_LENGTH_MAX, "%d.%d.%d.%d", byteIP[3], byteIP[2], byteIP[1], byteIP[0]);
for (size_t i = 0; i < IP_ADDRESS_LENGTH_MAX; ++i)
{
hostEp.IpAddress[i] = tmpIP[i];
localEp.IpAddress[i] = tmpIP[i];
}
hostEp.Port = 50223;
localEp.Port = 50224;
// get connected device
m_gdsResult = GDS_GetConnectedDevices(hostEp, localEp, &connectedDevicesInfo, &nDevices);
if (m_gdsResult.ErrorCode != GDS_ERROR_SUCCESS)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << m_gdsResult.ErrorMessage << "\n";
return false;
}
for (size_t i = 0; i < nDevices; ++i)
{
// if devices are in use they cannot be used for a new acquisition
if ((connectedDevicesInfo[i].InUse) && (i < nDevices)) continue;
// only one device can be used for data acquisition, as g.Nautilus cannot be synchronized
if ((connectedDevicesInfo[i].InUse) && (connectedDevicesInfo[i].ConnectedDevicesLength > 1)) continue;
GDS_DEVICE_INFO* deviceInfo = connectedDevicesInfo[i].ConnectedDevices;
if (deviceInfo[0].DeviceType == GDS_DEVICE_TYPE_GNAUTILUS)
{
deviceSerial = deviceInfo[0].Name;
nDevices = 1;
break;
}
}
if (nDevices == 0)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << "No g.Nautilus connected\n";
return false;
}
strncpy_s(m_deviceNames[0], deviceSerial.c_str(), DEVICE_NAME_LENGTH_MAX);
m_deviceSerial = deviceSerial;
// connect to device
m_gdsResult = GDS_Connect(hostEp, localEp, m_deviceNames, nDevices, openExclusively, &m_deviceHandle, &isCreator);
if (m_gdsResult.ErrorCode != GDS_ERROR_SUCCESS)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << m_gdsResult.ErrorMessage << "\n";
return false;
}
// free connected devices list allocated by GDS_GetConnectedDevices
m_gdsResult = GDS_FreeConnectedDevicesList(&connectedDevicesInfo, nDevices);
if (m_gdsResult.ErrorCode != GDS_ERROR_SUCCESS)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << m_gdsResult.ErrorMessage << "\n";
return false;
}
m_connectionOpen = true;
return true;
}
bool CConfigurationgNautilusInterface::closeDevice()
{
// disconnect device
m_gdsResult = GDS_Disconnect(&m_deviceHandle);
if (m_gdsResult.ErrorCode != GDS_ERROR_SUCCESS)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << m_gdsResult.ErrorMessage << "\n";
return false;
}
m_connectionOpen = false;
delete [] m_deviceNames;
return true;
}
} // namespace AcquisitionServer
} // namespace OpenViBE
#endif // TARGET_HAS_ThirdPartyGNEEDaccessAPI
@@ -0,0 +1,102 @@
#pragma once
#if defined(TARGET_HAS_ThirdPartyGNEEDaccessAPI)
#include "../ovasCConfigurationBuilder.h"
#include "ovasIDriver.h"
#include <gtk/gtk.h>
#include <GDSClientAPI.h>
#include <GDSClientAPI_gNautilus.h>
#include <sstream>
#include <algorithm>
namespace OpenViBE {
namespace AcquisitionServer {
/**
* \class CConfigurationgNautilusInterface
* \author g.tec medical engineering GmbH (g.tec medical engineering GmbH)
* \date Wed Aug 12 16:37:18 2015
* \brief The CConfigurationgNautilusInterface handles the configuration dialog specific to the g.NEEDaccess device.
*
* TODO: details
*
* \sa CDrivergNautilusInterface
*/
class CConfigurationgNautilusInterface final : public CConfigurationBuilder
{
public:
// you may have to add to your constructor some reference parameters
// for example, a connection ID:
//CConfigurationgNautilusInterface(IDriverContext& ctx, const char* gtkBuilderFilename, uint32_t& rConnectionId);
CConfigurationgNautilusInterface(IDriverContext& ctx, const char* gtkBuilderFilename, std::string& deviceSerial, int& inputSource, uint32_t& networkChannel,
int& bandpassFilterIdx, int& notchFilterIdx, double& sensitivity, bool& digitalInputEnabled, bool& noiseReductionEnabled,
bool& carEnabled, bool& accelerationDataEnabled, bool& counterEnabled, bool& linkQualityEnabled, bool& batteryLevelEnabled,
bool& validationIndicatorEnabled, std::vector<uint16_t>& selectedChannels, std::vector<int>& bipolarChannels,
std::vector<bool>& cars, std::vector<bool>& noiseReduction);
bool preConfigure() override;
bool postConfigure() override;
//button callback functions
void buttonChannelSettingsPressedCB();
void buttonChannelSettingsApplyPressedCB();
void buttonSensitivityFiltersPressedCB();
void buttonSensitivityFiltersApplyPressedCB();
bool getHardwareSettings();
bool getChannelNames();
bool getAvailableChannels();
bool getFiltersForNewSamplingRate();
void comboboxSampleRateChangedCB();
void checkbuttonNoiseReductionChangedCB();
void checkbuttonCARChangedCB();
protected:
IDriverContext& m_driverCtx;
std::string& m_deviceSerial;
int& m_inputSource;
uint32_t& m_networkChannel;
int& m_bandpassFilterIdx;
int& m_notchFilterIdx;
double& m_sensitivity;
bool& m_digitalInputEnabled;
bool& m_noiseReductionEnabled;
bool& m_carEnabled;
bool& m_accelerationDataEnabled;
bool& m_counterEnabled;
bool& m_linkQualityEnabled;
bool& m_batteryLevelEnabled;
bool& m_validationIndicatorEnabled;
std::vector<uint16_t>& m_selectedChannels;
std::vector<int>& m_bipolarChannels;
std::vector<bool>& m_cars;
std::vector<bool>& m_noiseReduction;
std::vector<int> m_comboBoxBandpassFilterIdx;
std::vector<int> m_comboBoxNotchFilterIdx;
std::vector<double> m_comboBoxSensitivityValues;
std::vector<int> m_comboBoxInputSources;
std::vector<size_t> m_comboBoxNetworkChannels;
private:
/*
* Insert here all specific attributes, such as a connection ID.
* use references to directly modify the corresponding attribute of the driver
* Example:
*/
// uint32_t& m_connectionID;
bool openDevice();
bool closeDevice();
GDS_HANDLE m_deviceHandle;
GDS_RESULT m_gdsResult;
std::vector<bool> m_availableChannels;
char (*m_deviceNames)[DEVICE_NAME_LENGTH_MAX];
bool m_connectionOpen = false;
};
} // namespace AcquisitionServer
} // namespace OpenViBE
#endif // TARGET_HAS_ThirdPartyGNEEDaccessAPI
@@ -0,0 +1,462 @@
#if defined(TARGET_HAS_ThirdPartyGNEEDaccessAPI)
#include "ovasCDrivergNautilusInterface.h"
#include "ovasCConfigurationgNautilusInterface.h"
#include <toolkit/ovtk_all.h>
namespace OpenViBE {
namespace AcquisitionServer {
// global functions, event handles and variables
void OnDataReadyEventHandler(GDS_HANDLE handle, void* data);
HANDLE dataReadyEventHandle;
CDrivergNautilusInterface::CDrivergNautilusInterface(IDriverContext& ctx)
: IDriver(ctx), m_settings("AcquisitionServer_Driver_gNautilusInterface", m_driverCtx.getConfigurationManager()), m_Device(NULL)
{
m_header.setSamplingFrequency(250);
m_header.setChannelCount(32);
// The following class allows saving and loading driver settings from the acquisition server .conf file
m_settings.add("Header", &m_header);
// To save your custom driver settings, register each variable to the SettingsHelper
//m_settings.add("SettingName", &variable);
m_settings.add("DeviceIndex", &m_deviceIdx);
m_settings.add("InputSource", &m_inputSource);
m_settings.add("NetworkChannel", &m_networkChannel);
m_settings.add("Sensitivity", &m_sensitivity);
m_settings.add("NotchFilterIndex", &m_notchFilterIdx);
m_settings.add("BandPassFilterIndex", &m_bandPassFilterIdx);
m_settings.add("DigitalInputEnabled", &m_digitalInputEnabled);
m_settings.add("NoiseReductionEnabled", &m_noiseReductionEnabled);
m_settings.add("CAREnabled", &m_carEnabled);
m_settings.add("AccelerationEnabled", &m_accelerationDataEnabled);
m_settings.add("CounterEnabled", &m_counterEnabled);
m_settings.add("LinqQualityEnabled", &m_linkQualityEnabled);
m_settings.add("BatteryLevelEnabled", &m_batteryLevelEnabled);
m_settings.add("ValidationIndicatorEnabled", &m_validationIndicatorEnabled);
m_settings.load();
}
//___________________________________________________________________//
// //
bool CDrivergNautilusInterface::initialize(const uint32_t nSamplePerSentBlock, IDriverCallback& callback)
{
if (m_driverCtx.isConnected() || !m_header.isChannelCountSet() || !m_header.isSamplingFrequencySet()) { return false; }
if (nSamplePerSentBlock > 250)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << "Sample count per sent block cannot be higher than 250 samples for g.Nautilus\n";
return false;
}
// initialize basic GDS functions before the first GDS function itself is called
GDS_Initialize();
// get number of channels actually acquired
m_nAcquiredChannel = 0;
for (size_t i = 0; i < GDS_GNAUTILUS_CHANNELS_MAX; ++i)
{
if (find(m_selectedChannels.begin(), m_selectedChannels.end(), (i + 1)) != m_selectedChannels.end())
{
m_header.setChannelUnits(m_nAcquiredChannel, OVTK_UNIT_Volts, OVTK_FACTOR_Micro);
m_nAcquiredChannel += 1;
}
}
m_header.setChannelCount(m_nAcquiredChannel);
// g.Nautilus provides some extra channel, add them to the channels count
// and provide corresponding names
uint32_t nAcquiredChannel = m_nAcquiredChannel;
if (m_accelerationDataEnabled)
{
m_header.setChannelCount(nAcquiredChannel + 3);
m_header.setChannelName(nAcquiredChannel, "CH_Accel_x");
m_header.setChannelName(nAcquiredChannel + 1, "CH_Accel_y");
m_header.setChannelName(nAcquiredChannel + 2, "CH_Accel_z");
m_header.setChannelUnits(nAcquiredChannel, OVTK_UNIT_Meter_Per_Second_Squared, OVTK_FACTOR_Base);
m_header.setChannelUnits(nAcquiredChannel + 1, OVTK_UNIT_Meter_Per_Second_Squared, OVTK_FACTOR_Base);
m_header.setChannelUnits(nAcquiredChannel + 2, OVTK_UNIT_Meter_Per_Second_Squared, OVTK_FACTOR_Base);
nAcquiredChannel = m_header.getChannelCount();
}
if (m_counterEnabled)
{
m_header.setChannelCount(nAcquiredChannel + 1);
m_header.setChannelName(nAcquiredChannel, "CH_Counter");
m_header.setChannelUnits(nAcquiredChannel,OVTK_UNIT_Dimensionless,OVTK_FACTOR_Base);
nAcquiredChannel = m_header.getChannelCount();
}
if (m_linkQualityEnabled)
{
m_header.setChannelCount(nAcquiredChannel + 1);
m_header.setChannelName(nAcquiredChannel, "CH_LQ");
m_header.setChannelUnits(nAcquiredChannel,OVTK_UNIT_10_2_Percent,OVTK_FACTOR_Base);
nAcquiredChannel = m_header.getChannelCount();
}
if (m_batteryLevelEnabled)
{
m_header.setChannelCount(nAcquiredChannel + 1);
m_header.setChannelName(nAcquiredChannel, "CH_Battery");
m_header.setChannelUnits(nAcquiredChannel,OVTK_UNIT_10_2_Percent,OVTK_FACTOR_Base);
nAcquiredChannel = m_header.getChannelCount();
}
if (m_digitalInputEnabled)
{
m_header.setChannelCount(nAcquiredChannel + 1);
m_header.setChannelName(nAcquiredChannel, "CH_Event");
m_header.setChannelUnits(nAcquiredChannel,OVTK_UNIT_Dimensionless,OVTK_FACTOR_Base);
nAcquiredChannel = m_header.getChannelCount();
}
if (m_validationIndicatorEnabled)
{
m_header.setChannelCount(nAcquiredChannel + 1);
m_header.setChannelName(nAcquiredChannel, "CH_Valid");
m_header.setChannelUnits(nAcquiredChannel,OVTK_UNIT_Dimensionless,OVTK_FACTOR_Base);
nAcquiredChannel = m_header.getChannelCount();
}
// initialize connection and open connection handle and get serial of connected g.Nautilus
GDS_DEVICE_CONNECTION_INFO* devicesInfo;
size_t nDevices = 0;
GDS_ENDPOINT hostEp;
GDS_ENDPOINT localEp;
uint8_t byteIP[4];
char tempIP[16];
byteIP[0] = 1;
byteIP[1] = 0;
byteIP[2] = 0;
byteIP[3] = 127;
_snprintf_s(tempIP, IP_ADDRESS_LENGTH_MAX, "%d.%d.%d.%d", byteIP[3], byteIP[2], byteIP[1], byteIP[0]);
for (size_t i = 0; i < IP_ADDRESS_LENGTH_MAX; ++i)
{
hostEp.IpAddress[i] = tempIP[i];
localEp.IpAddress[i] = tempIP[i];
}
hostEp.Port = 50223;
localEp.Port = 50224;
bool found = false;
m_gdsResult = GDS_GetConnectedDevices(hostEp, localEp, &devicesInfo, &nDevices);
if (m_gdsResult.ErrorCode != GDS_ERROR_SUCCESS)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << m_gdsResult.ErrorMessage << "\n";
return false;
}
for (size_t i = 0; i < nDevices; ++i)
{
// if devices are in use they cannot be used for a new acquisition
if ((devicesInfo[i].InUse) && (i < nDevices)) { continue; }
// only one device can be used for data acquisition, as g.Nautilus cannot be synchronized
if ((devicesInfo[i].InUse) && (devicesInfo[i].ConnectedDevicesLength > 1)) { continue; }
GDS_DEVICE_INFO* info = devicesInfo[i].ConnectedDevices;
if (info[0].DeviceType == GDS_DEVICE_TYPE_GNAUTILUS)
{
// check if device used for configuration is still available
if (!strcmp(info[0].Name, m_deviceSerial.c_str()))
{
m_nDevice = 1;
found = true;
break;
}
}
}
if (found == false)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << "No g.Nautilus device found\n";
return false;
}
char (*names)[DEVICE_NAME_LENGTH_MAX] = new char[1][DEVICE_NAME_LENGTH_MAX];
bool openExclusively = true;
BOOL isCreator;
strncpy_s(names[0], m_deviceSerial.c_str(), DEVICE_NAME_LENGTH_MAX);
// connect to device
m_gdsResult = GDS_Connect(hostEp, localEp, names, m_nDevice, openExclusively, &m_Device, &isCreator);
if (m_gdsResult.ErrorCode != GDS_ERROR_SUCCESS)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << m_gdsResult.ErrorMessage << "\n";
return false;
}
m_driverCtx.getLogManager() << Kernel::LogLevel_Info << "Connected to device : " << m_deviceSerial << "\n";
m_deviceCfg.SamplingRate = m_header.getSamplingFrequency();
m_deviceCfg.NumberOfScans = nSamplePerSentBlock;
m_deviceCfg.NetworkChannel = m_networkChannel;
m_deviceCfg.AccelerationData = m_accelerationDataEnabled;
m_deviceCfg.BatteryLevel = m_batteryLevelEnabled;
m_deviceCfg.CAR = m_carEnabled;
m_deviceCfg.Counter = m_counterEnabled;
m_deviceCfg.DigitalIOs = m_digitalInputEnabled;
m_deviceCfg.LinkQualityInformation = m_linkQualityEnabled;
m_deviceCfg.NoiseReduction = m_noiseReductionEnabled;
m_deviceCfg.Slave = 0;
m_deviceCfg.ValidationIndicator = m_validationIndicatorEnabled;
m_deviceCfg.InputSignal = GDS_GNAUTILUS_INPUT_SIGNAL(m_inputSource);
for (size_t i = 0; i < GDS_GNAUTILUS_CHANNELS_MAX; ++i)
{
if (find(m_selectedChannels.begin(), m_selectedChannels.end(), (i + 1)) != m_selectedChannels.end()) { m_deviceCfg.Channels[i].Enabled = true; }
else { m_deviceCfg.Channels[i].Enabled = false; }
m_deviceCfg.Channels[i].Sensitivity = m_sensitivity;
if (i < m_cars.size()) { m_deviceCfg.Channels[i].UsedForCar = m_cars[i]; }
else { m_deviceCfg.Channels[i].UsedForCar = false; }
if (i < m_noiseReduction.size()) { m_deviceCfg.Channels[i].UsedForNoiseReduction = m_noiseReduction[i]; }
else { m_deviceCfg.Channels[i].UsedForNoiseReduction = false; }
m_deviceCfg.Channels[i].BandpassFilterIndex = m_bandPassFilterIdx;
m_deviceCfg.Channels[i].NotchFilterIndex = m_notchFilterIdx;
if (i < m_bipolarChannels.size()) { m_deviceCfg.Channels[i].BipolarChannel = m_bipolarChannels[i]; }
else { m_deviceCfg.Channels[i].BipolarChannel = false; }
}
// Free memory allocated for list of connected devices by GDS_GetConnectedDevices
m_gdsResult = GDS_FreeConnectedDevicesList(&devicesInfo, nDevices);
if (m_gdsResult.ErrorCode != GDS_ERROR_SUCCESS)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << m_gdsResult.ErrorMessage << "\n";
return false;
}
// Builds up a buffer to store acquired samples. This buffer
// will be sent to the acquisition server later...
m_sample = new float[nAcquiredChannel * m_deviceCfg.NumberOfScans];
if (!m_sample)
{
delete [] m_sample;
m_sample = nullptr;
return false;
}
// set up data buffer for gds getdata function
m_Buffer = new float[nAcquiredChannel * m_deviceCfg.NumberOfScans];
if (!m_Buffer)
{
delete [] m_Buffer;
m_Buffer = nullptr;
return false;
}
m_bufferSize = nAcquiredChannel * m_deviceCfg.NumberOfScans;
// Saves parameters
m_callback = &callback;
m_nSamplePerSentBlock = nSamplePerSentBlock;
return true;
}
bool CDrivergNautilusInterface::start()
{
if (!m_driverCtx.isConnected() || m_driverCtx.isStarted()) { return false; }
// if no device was found return
if (m_nDevice != 1) { return false; }
GDS_CONFIGURATION_BASE* config = new GDS_CONFIGURATION_BASE[m_nDevice];
config[0].Configuration = &m_deviceCfg;
config[0].DeviceInfo.DeviceType = GDS_DEVICE_TYPE_GNAUTILUS;
strcpy_s(config[0].DeviceInfo.Name, m_deviceSerial.c_str());
size_t nScan = 0;
size_t channelsPerDevice = 0;
size_t bufferSizeInSamples = 0;
// set device configuration
m_gdsResult = GDS_SetConfiguration(m_Device, config, m_nDevice);
if (m_gdsResult.ErrorCode != GDS_ERROR_SUCCESS)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << m_gdsResult.ErrorMessage << "\n";
return false;
}
// initialize data ready event and set data ready event handle
dataReadyEventHandle = nullptr;
dataReadyEventHandle = CreateEvent(nullptr, false, false, nullptr);
m_gdsResult = GDS_SetDataReadyCallback(m_Device, (GDS_Callback)OnDataReadyEventHandler, m_deviceCfg.NumberOfScans,NULL);
if (m_gdsResult.ErrorCode != GDS_ERROR_SUCCESS)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << m_gdsResult.ErrorMessage << "\n";
return false;
}
// set number of scans getdata function will return
m_availableScans = m_deviceCfg.NumberOfScans;
// ...
// request hardware to start
// sending data
// ...
// start acquisition
m_gdsResult = GDS_StartAcquisition(m_Device);
if (m_gdsResult.ErrorCode != GDS_ERROR_SUCCESS)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << m_gdsResult.ErrorMessage << "\n";
return false;
}
// start data stream from server
m_gdsResult = GDS_StartStreaming(m_Device);
if (m_gdsResult.ErrorCode != GDS_ERROR_SUCCESS)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << m_gdsResult.ErrorMessage << "\n";
return false;
}
m_gdsResult = GDS_GetDataInfo(m_Device, &nScan, nullptr, &channelsPerDevice, &bufferSizeInSamples);
if (m_gdsResult.ErrorCode != GDS_ERROR_SUCCESS)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << m_gdsResult.ErrorMessage << "\n";
return false;
}
return true;
}
bool CDrivergNautilusInterface::loop()
{
if (!m_driverCtx.isConnected() || !m_driverCtx.isStarted()) { return true; }
const CStimulationSet stimSet;
if (m_driverCtx.isStarted())
{
const DWORD ret = WaitForSingleObject(dataReadyEventHandle, 5000);
if (ret == WAIT_TIMEOUT)
{
// if data ready event is not triggered in 5000ms add a timeout handler
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << "No data received in 5 seconds\n";
return false;
}
// when data is ready call get data function with amount of scans to return
m_gdsResult = GDS_GetData(m_Device, &m_availableScans, m_Buffer, m_bufferSize);
if (m_gdsResult.ErrorCode != GDS_ERROR_SUCCESS)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << m_gdsResult.ErrorMessage << "\n";
return false;
}
// put data from receiving buffer to application buffer
for (size_t i = 0; i < m_header.getChannelCount(); ++i)
{
for (size_t j = 0; j < m_nSamplePerSentBlock; ++j) { m_sample[i * m_nSamplePerSentBlock + j] = m_Buffer[j * (m_header.getChannelCount()) + i]; }
}
}
// ...
// receive samples from hardware
// put them the correct way in the sample array
// whether the buffer is full, send it to the acquisition server
//...
m_callback->setSamples(m_sample);
// When your sample buffer is fully loaded,
// it is advised to ask the acquisition server
// to correct any drift in the acquisition automatically.
m_driverCtx.correctDriftSampleCount(m_driverCtx.getSuggestedDriftCorrectionSampleCount());
// ...
// receive events from hardware
// and put them the correct way in a CStimulationSet object
//...
m_callback->setStimulationSet(stimSet);
return true;
}
bool CDrivergNautilusInterface::stop()
{
if (!m_driverCtx.isConnected()) return false;
if (!m_driverCtx.isStarted()) return false;
// ...
// request the hardware to stop
// sending data
// ...
// stop streaming
m_gdsResult = GDS_StopStreaming(m_Device);
if (m_gdsResult.ErrorCode != GDS_ERROR_SUCCESS)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << m_gdsResult.ErrorMessage << "\n";
return false;
}
// stop data acquisiton
m_gdsResult = GDS_StopAcquisition(m_Device);
if (m_gdsResult.ErrorCode != GDS_ERROR_SUCCESS)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << m_gdsResult.ErrorMessage << "\n";
return false;
}
return true;
}
bool CDrivergNautilusInterface::uninitialize()
{
if (!m_driverCtx.isConnected() || m_driverCtx.isStarted()) { return false; }
// ...
// uninitialize hardware here
// ...
m_gdsResult = GDS_Disconnect(&m_Device);
if (m_gdsResult.ErrorCode != GDS_ERROR_SUCCESS)
{
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << m_gdsResult.ErrorMessage << "\n";
return false;
}
delete [] m_sample;
m_sample = nullptr;
m_callback = nullptr;
// uninitialize basic GDS functions after last GDS function is called
GDS_Uninitialize();
m_driverCtx.getLogManager() << Kernel::LogLevel_Info << "Disconnected from device : " << m_deviceSerial << "\n";
return true;
}
//___________________________________________________________________//
// //
bool CDrivergNautilusInterface::isConfigurable()
{
return true; // change to false if your device is not configurable
}
bool CDrivergNautilusInterface::configure()
{
// Change this line if you need to specify some references to your driver attribute that need configuration, e.g. the connection ID.
CConfigurationgNautilusInterface config(m_driverCtx, Directories::getDataDir() + "/applications/acquisition-server/interface-gNautilusInterface.ui",
m_deviceSerial, m_inputSource, m_networkChannel, m_bandPassFilterIdx, m_notchFilterIdx, m_sensitivity,
m_digitalInputEnabled, m_noiseReductionEnabled, m_carEnabled, m_accelerationDataEnabled, m_counterEnabled,
m_linkQualityEnabled, m_batteryLevelEnabled, m_validationIndicatorEnabled, m_selectedChannels, m_bipolarChannels,
m_cars, m_noiseReduction);
if (!config.configure(m_header)) { return false; }
m_settings.save();
return true;
}
void OnDataReadyEventHandler(GDS_HANDLE handle, void* data)
{
// signals data is ready on GDS acquisition buffer
if (!SetEvent(dataReadyEventHandle))
{
// insert error handling if necessary
}
}
} // namespace AcquisitionServer
} // namespace OpenViBE
#endif // TARGET_HAS_ThirdPartyGNEEDaccessAPI
@@ -0,0 +1,98 @@
#pragma once
#if defined(TARGET_HAS_ThirdPartyGNEEDaccessAPI)
#include "ovasIDriver.h"
#include "../ovasCHeader.h"
#include <openvibe/ov_all.h>
#include "../ovasCSettingsHelper.h"
#include "../ovasCSettingsHelperOperators.h"
#include <GDSClientAPI.h>
#include <GDSClientAPI_gNautilus.h>
#include <vector>
#include <string>
#include <algorithm>
#include <Windows.h>
namespace OpenViBE {
namespace AcquisitionServer {
/**
* \class CDrivergNautilusInterface
* \author g.tec medical engineering GmbH (g.tec medical engineering GmbH)
* \date Wed Aug 12 16:37:18 2015
* \brief The CDrivergNautilusInterface allows the acquisition server to acquire data from a g.NEEDaccess device.
*
* TODO: details
*
* \sa CConfigurationgNautilusInterface
*/
class CDrivergNautilusInterface final : public IDriver
{
public:
explicit CDrivergNautilusInterface(IDriverContext& ctx);
~CDrivergNautilusInterface() override { }
const char* getName() override { return "g.tec g.Nautilus using g.NEEDaccess"; }
bool initialize(const uint32_t nSamplePerSentBlock, IDriverCallback& callback) override;
bool uninitialize() override;
bool start() override;
bool stop() override;
bool loop() override;
bool isConfigurable() override;
bool configure() override;
const IHeader* getHeader() override { return &m_header; }
bool isFlagSet(const EDriverFlag flag) const override { return flag == EDriverFlag::IsUnstable; }
protected:
SettingsHelper m_settings;
IDriverCallback* m_callback = nullptr;
// Replace this generic Header with any specific header you might have written
CHeader m_header;
uint32_t m_nSamplePerSentBlock = 4;
float* m_sample = nullptr;
uint32_t m_deviceIdx = uint32_t(-1);
uint32_t m_actualDeviceIdx = 0;
uint32_t m_bufferSize = 0;
size_t m_availableScans = 0;
float* m_Buffer = nullptr;
int m_notchFilterIdx = -1;
int m_bandPassFilterIdx = -1;
double m_sensitivity = 0;
int m_inputSource = 0;
uint32_t m_networkChannel = 11;
bool m_digitalInputEnabled = true;
bool m_noiseReductionEnabled = false;
bool m_carEnabled = false;
bool m_accelerationDataEnabled = true;
bool m_counterEnabled = true;
bool m_linkQualityEnabled = true;
bool m_batteryLevelEnabled = true;
bool m_validationIndicatorEnabled = true;
std::vector<uint16_t> m_selectedChannels;
std::vector<int> m_bipolarChannels;
std::vector<bool> m_noiseReduction;
std::vector<bool> m_cars;
uint32_t m_nAcquiredChannel = 32;
GDS_HANDLE m_Device;
GDS_RESULT m_gdsResult;
GDS_GNAUTILUS_CONFIGURATION m_deviceCfg;
std::string m_deviceSerial;
uint32_t m_nDevice = 0;
};
} // namespace AcquisitionServer
} // namespace OpenViBE
#endif // TARGET_HAS_ThirdPartyGNEEDaccessAPI