From 2b07b765022083b084ba1c36994ad30b1a306a58 Mon Sep 17 00:00:00 2001 From: Tobias Baumann Date: Thu, 10 Feb 2022 17:55:12 +0000 Subject: [PATCH] =?UTF-8?q?=E2=80=9EovpCBoxAlgorithmP300TactileVisualizati?= =?UTF-8?q?on.cpp=E2=80=9C=20l=C3=B6schen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ovpCBoxAlgorithmP300TactileVisualization.cpp | 764 ------------------- 1 file changed, 764 deletions(-) delete mode 100644 ovpCBoxAlgorithmP300TactileVisualization.cpp diff --git a/ovpCBoxAlgorithmP300TactileVisualization.cpp b/ovpCBoxAlgorithmP300TactileVisualization.cpp deleted file mode 100644 index 1ae6ee1..0000000 --- a/ovpCBoxAlgorithmP300TactileVisualization.cpp +++ /dev/null @@ -1,764 +0,0 @@ -///------------------------------------------------------------------------------------------------- -/// -/// \file ovpCBoxAlgorithmP300TactileVisualization.cpp -/// \brief Functions of the Class P300TactileVisualization. !!This is a modification of the P300 Speller Visualization Box!! -/// \author Tobias Baumann (TH Nuernberg). -/// \version 1.0. -/// \date Mon Feb 04 12:43:53 2022. -/// \copyright GNU Affero General Public License v3.0 -/// -///------------------------------------------------------------------------------------------------- - -//includes -#include "ovpCBoxAlgorithmP300TactileVisualization.h" -#include - -#include -#include -#include -#include - -namespace OpenViBE { -namespace Plugins { -namespace Tactilebci { - -static void ToggleButtonShowHideCB(GtkToggleToolButton* button, gpointer data) -{ - if (gtk_toggle_tool_button_get_active(button)) { gtk_widget_show(GTK_WIDGET(data)); } - else { gtk_widget_hide(GTK_WIDGET(data)); } -} - -// This callback flushes all accumulated stimulations to the TCP Tagging -// after the rendering has completed. -static gboolean FlushCB(gpointer data) -{ - (static_cast(data))->flushQueue(); - - return false; // Only run once -} - -bool CBoxAlgorithmP300TactileVisualization::initialize() -{ - const Kernel::IBox& boxContext = this->getStaticBoxContext(); - - m_mainWidgetInterface = nullptr; - m_toolbarWidgetInterface = nullptr; - m_flashFontDesc = nullptr; - m_noFlashFontDesc = nullptr; - m_targetFontDesc = nullptr; - m_selectedFontDesc = nullptr; - - // ---------------------------------------------------------------------------------------------------------------------------------------------------------- - - m_interfaceFilename = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 0); - m_rowStimulationBase = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 1); - m_columnStimulationBase = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 2); - - m_flashBgColor = CGdkcolorAutoCast(boxContext, this->getConfigurationManager(), 3); - m_flashFgColor = CGdkcolorAutoCast(boxContext, this->getConfigurationManager(), 4); - m_flashFontSize = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 5); - m_noFlashBgColor = CGdkcolorAutoCast(boxContext, this->getConfigurationManager(), 6); - m_noFlashFgColor = CGdkcolorAutoCast(boxContext, this->getConfigurationManager(), 7); - m_noFlashFontSize = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 8); - m_targetBgColor = CGdkcolorAutoCast(boxContext, this->getConfigurationManager(), 9); - m_targetFgColor = CGdkcolorAutoCast(boxContext, this->getConfigurationManager(), 10); - m_targetFontSize = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 11); - m_selectedBgColor = CGdkcolorAutoCast(boxContext, this->getConfigurationManager(), 12); - m_selectedFgColor = CGdkcolorAutoCast(boxContext, this->getConfigurationManager(), 13); - m_selectedFontSize = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 14); - - // ---------------------------------------------------------------------------------------------------------------------------------------------------------- - - m_sequenceStimulationDecoder = &this->getAlgorithmManager().getAlgorithm( - this->getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_StimulationDecoder)); - m_sequenceStimulationDecoder->initialize(); - - m_targetStimulationDecoder = &this->getAlgorithmManager().getAlgorithm( - this->getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_StimulationDecoder)); - m_targetStimulationDecoder->initialize(); - - m_targetFlaggingStimulationEncoder = &this->getAlgorithmManager().getAlgorithm( - this->getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_StimulationEncoder)); - m_targetFlaggingStimulationEncoder->initialize(); - - m_rowSelectionStimulationDecoder = &this->getAlgorithmManager().getAlgorithm( - this->getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_StimulationDecoder)); - m_rowSelectionStimulationDecoder->initialize(); - - m_columnSelectionStimulationDecoder = &this->getAlgorithmManager().getAlgorithm( - this->getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_StimulationDecoder)); - m_columnSelectionStimulationDecoder->initialize(); - - m_sequenceMemoryBuffer.initialize( - m_sequenceStimulationDecoder->getInputParameter(OVP_GD_Algorithm_StimulationDecoder_InputParameterId_MemoryBufferToDecode)); - m_sequenceStimulationSet.initialize( - m_sequenceStimulationDecoder->getOutputParameter(OVP_GD_Algorithm_StimulationDecoder_OutputParameterId_StimulationSet)); - - m_targetMemoryBuffer.initialize( - m_targetStimulationDecoder->getInputParameter(OVP_GD_Algorithm_StimulationDecoder_InputParameterId_MemoryBufferToDecode)); - m_targetStimulationSet.initialize( - m_targetStimulationDecoder->getOutputParameter(OVP_GD_Algorithm_StimulationDecoder_OutputParameterId_StimulationSet)); - - m_targetFlaggingStimulationSet.initialize( - m_targetFlaggingStimulationEncoder->getInputParameter(OVP_GD_Algorithm_StimulationEncoder_InputParameterId_StimulationSet)); - m_targetFlaggingMemoryBuffer.initialize( - m_targetFlaggingStimulationEncoder->getOutputParameter(OVP_GD_Algorithm_StimulationEncoder_OutputParameterId_EncodedMemoryBuffer)); - - m_lastTime = 0; - - m_stimulusSender = nullptr; - - m_idleFuncTag = 0; - m_stimuliQueue.clear(); - - m_mainWidgetInterface = gtk_builder_new(); // glade_xml_new(m_interfaceFilename.toASCIIString(), "p300-speller-main", nullptr); - if (!gtk_builder_add_from_file(m_mainWidgetInterface, m_interfaceFilename.toASCIIString(), nullptr)) - { - this->getLogManager() << Kernel::LogLevel_ImportantWarning << "Could not load interface file [" << m_interfaceFilename << "]\n"; - this->getLogManager() << Kernel::LogLevel_ImportantWarning << - "The file may be missing. However, the interface files now use gtk-builder instead of glade. Did you update your files ?\n"; - return false; - } - - m_toolbarWidgetInterface = gtk_builder_new(); // glade_xml_new(m_interfaceFilename.toASCIIString(), "p300-speller-toolbar", nullptr); - gtk_builder_add_from_file(m_toolbarWidgetInterface, m_interfaceFilename.toASCIIString(), nullptr); - - m_mainWindow = GTK_WIDGET(gtk_builder_get_object(m_mainWidgetInterface, "p300-speller-main")); - m_toolbarWidget = GTK_WIDGET(gtk_builder_get_object(m_toolbarWidgetInterface, "p300-speller-toolbar")); - m_table = GTK_TABLE(gtk_builder_get_object(m_mainWidgetInterface, "p300-speller-table")); - m_result = GTK_LABEL(gtk_builder_get_object(m_mainWidgetInterface, "label-result")); - m_target = GTK_LABEL(gtk_builder_get_object(m_mainWidgetInterface, "label-target")); - - //TactileMenu initialization - TactileMenu CBoxAlgorithmP300TactileVisualization::m_MainMenu("Ja", "Nein", "Pflege", "Hilfe", "Geräte", "Optionen", m_mainWidgetInterface); - TactileMenu CBoxAlgorithmP300TactileVisualization::m_CareMenu("Ja", "Nein", "Hunger", "Lage", "Müdigkeit", "Hauptmenü", m_mainWidgetInterface); - TactileMenu CBoxAlgorithmP300TactileVisualization::m_HelpMenu("Ja", "Nein", "Schmerzen", "Atemnot", "Anderes", "Hauptmenü", m_mainWidgetInterface); - TactileMenu CBoxAlgorithmP300TactileVisualization::m_DevicesMenu("Ja", "Nein", "Atemgerät", "Rollstuhl", "Computer", "Hauptmenü", m_mainWidgetInterface); - TactileMenu CBoxAlgorithmP300TactileVisualization::m_FunctionsMenu("Ja", "Nein", "befehl1", "befehl2", "befehl3", "Hauptmenü", m_mainWidgetInterface); - - - - m_CurrentMenu = &m_MainMenu; - m_CurrentMenu->reloadui(); -//Grenze------------------------------------------------------------------------------------- - gtk_builder_connect_signals(m_mainWidgetInterface, nullptr); - gtk_builder_connect_signals(m_toolbarWidgetInterface, nullptr); - - g_signal_connect(gtk_builder_get_object(m_toolbarWidgetInterface, "toolbutton-show_target_text"), "toggled", G_CALLBACK(ToggleButtonShowHideCB), - gtk_builder_get_object(m_mainWidgetInterface, "label-target")); - g_signal_connect(gtk_builder_get_object(m_toolbarWidgetInterface, "toolbutton-show_target_text"), "toggled", G_CALLBACK(ToggleButtonShowHideCB), - gtk_builder_get_object(m_mainWidgetInterface, "label-target-title")); - g_signal_connect(gtk_builder_get_object(m_toolbarWidgetInterface, "toolbutton-show_result_text"), "toggled", G_CALLBACK(ToggleButtonShowHideCB), - gtk_builder_get_object(m_mainWidgetInterface, "label-result")); - g_signal_connect(gtk_builder_get_object(m_toolbarWidgetInterface, "toolbutton-show_result_text"), "toggled", G_CALLBACK(ToggleButtonShowHideCB), - gtk_builder_get_object(m_mainWidgetInterface, "label-result-title")); - - m_visualizationCtx = dynamic_cast(this->createPluginObject( - OVP_ClassId_Plugin_VisualizationCtx)); - m_visualizationCtx->setWidget(*this, m_mainWindow); - m_visualizationCtx->setToolbar(*this, m_toolbarWidget); - - guint nRow = 0, nCol = 0; - g_object_get(m_table, "n-rows", &nRow, nullptr); - g_object_get(m_table, "n-columns", &nCol, nullptr); - - m_nRow = nRow; - m_nCol = nCol; - - PangoFontDescription* maxFontDesc = pango_font_description_copy(pango_context_get_font_description(gtk_widget_get_pango_context(m_mainWindow))); - m_flashFontDesc = pango_font_description_copy(pango_context_get_font_description(gtk_widget_get_pango_context(m_mainWindow))); - m_noFlashFontDesc = pango_font_description_copy(pango_context_get_font_description(gtk_widget_get_pango_context(m_mainWindow))); - m_targetFontDesc = pango_font_description_copy(pango_context_get_font_description(gtk_widget_get_pango_context(m_mainWindow))); - m_selectedFontDesc = pango_font_description_copy(pango_context_get_font_description(gtk_widget_get_pango_context(m_mainWindow))); - - uint64_t maxSize = 0; - maxSize = std::max(maxSize, m_flashFontSize); - maxSize = std::max(maxSize, m_noFlashFontSize); - maxSize = std::max(maxSize, m_targetFontSize); - maxSize = std::max(maxSize, m_selectedFontSize); - - pango_font_description_set_size(maxFontDesc, gint(maxSize * PANGO_SCALE)); - pango_font_description_set_size(m_flashFontDesc, gint(m_flashFontSize * PANGO_SCALE)); - pango_font_description_set_size(m_noFlashFontDesc, gint(m_noFlashFontSize * PANGO_SCALE)); - pango_font_description_set_size(m_targetFontDesc, gint(m_targetFontSize * PANGO_SCALE)); - pango_font_description_set_size(m_selectedFontDesc, gint(m_selectedFontSize * PANGO_SCALE)); - - this->cacheBuildFromTable(m_table); - this->cacheForEach(&CBoxAlgorithmP300TactileVisualization::cacheChangeBackgroundCB, &m_noFlashBgColor); - this->cacheForEach(&CBoxAlgorithmP300TactileVisualization::cacheChangeForegroundCB, &m_noFlashFgColor); - this->cacheForEach(&CBoxAlgorithmP300TactileVisualization::cacheChangeFontCB, maxFontDesc); - - pango_font_description_free(maxFontDesc); - - m_lastTargetRow = -1; - m_lastTargetCol = -1; - m_targetRow = -1; - m_targetCol = -1; - m_selectedRow = -1; - m_selectedCol = -1; - - m_stimulusSender = TCPTagging::CreateStimulusSender(); - - if (!m_stimulusSender->connect("localhost", "15361")) - { - this->getLogManager() << Kernel::LogLevel_Warning << "Unable to connect to AS TCP Tagging, stimuli wont be forwarded.\n"; - } - - m_tableInitialized = false; - - return true; -} - -bool CBoxAlgorithmP300TactileVisualization::uninitialize() -{ - if (m_idleFuncTag) - { - m_stimuliQueue.clear(); - g_source_remove(m_idleFuncTag); - m_idleFuncTag = 0; - } - - if (m_stimulusSender) - { - delete m_stimulusSender; - m_stimulusSender = nullptr; - } - - if (m_selectedFontDesc) - { - pango_font_description_free(m_selectedFontDesc); - m_selectedFontDesc = nullptr; - } - - if (m_targetFontDesc) - { - pango_font_description_free(m_targetFontDesc); - m_targetFontDesc = nullptr; - } - - if (m_noFlashFontDesc) - { - pango_font_description_free(m_noFlashFontDesc); - m_noFlashFontDesc = nullptr; - } - - if (m_flashFontDesc) - { - pango_font_description_free(m_flashFontDesc); - m_flashFontDesc = nullptr; - } - - if (m_toolbarWidgetInterface) - { - g_object_unref(m_toolbarWidgetInterface); - m_toolbarWidgetInterface = nullptr; - } - - if (m_mainWidgetInterface) - { - g_object_unref(m_mainWidgetInterface); - m_mainWidgetInterface = nullptr; - } - - m_targetFlaggingStimulationSet.uninitialize(); - m_targetFlaggingMemoryBuffer.uninitialize(); - - m_targetStimulationSet.uninitialize(); - m_targetMemoryBuffer.uninitialize(); - - m_sequenceStimulationSet.uninitialize(); - m_sequenceMemoryBuffer.uninitialize(); - - if (m_columnSelectionStimulationDecoder) - { - m_columnSelectionStimulationDecoder->uninitialize(); - this->getAlgorithmManager().releaseAlgorithm(*m_columnSelectionStimulationDecoder); - m_columnSelectionStimulationDecoder = nullptr; - } - - if (m_rowSelectionStimulationDecoder) - { - m_rowSelectionStimulationDecoder->uninitialize(); - this->getAlgorithmManager().releaseAlgorithm(*m_rowSelectionStimulationDecoder); - m_rowSelectionStimulationDecoder = nullptr; - } - - if (m_targetFlaggingStimulationEncoder) - { - m_targetFlaggingStimulationEncoder->uninitialize(); - this->getAlgorithmManager().releaseAlgorithm(*m_targetFlaggingStimulationEncoder); - m_targetFlaggingStimulationEncoder = nullptr; - } - - if (m_targetStimulationDecoder) - { - m_targetStimulationDecoder->uninitialize(); - this->getAlgorithmManager().releaseAlgorithm(*m_targetStimulationDecoder); - m_targetStimulationDecoder = nullptr; - } - - if (m_sequenceStimulationDecoder) - { - m_sequenceStimulationDecoder->uninitialize(); - this->getAlgorithmManager().releaseAlgorithm(*m_sequenceStimulationDecoder); - m_sequenceStimulationDecoder = nullptr; - } - - if (m_visualizationCtx) - { - this->releasePluginObject(m_visualizationCtx); - m_sequenceStimulationDecoder = nullptr; - } - - return true; -} - -bool CBoxAlgorithmP300TactileVisualization::processInput(const size_t /*index*/) -{ - this->getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess(); - - if (!m_tableInitialized) - { - this->cacheForEach(&CBoxAlgorithmP300TactileVisualization::cacheChangeBackgroundCB, &m_noFlashBgColor); - this->cacheForEach(&CBoxAlgorithmP300TactileVisualization::cacheChangeForegroundCB, &m_noFlashFgColor); - this->cacheForEach(&CBoxAlgorithmP300TactileVisualization::cacheChangeFontCB, m_noFlashFontDesc); - m_tableInitialized = true; - } - - return true; -} - -bool CBoxAlgorithmP300TactileVisualization::process() -{ - Kernel::IBoxIO& boxContext = this->getDynamicBoxContext(); - - // --- Sequence stimulations - - for (size_t i = 0; i < boxContext.getInputChunkCount(0); ++i) - { - CStimulationSet flaggingStimulationSet; - - m_sequenceMemoryBuffer = boxContext.getInputChunk(0, i); - m_targetFlaggingStimulationSet = &flaggingStimulationSet; - m_targetFlaggingMemoryBuffer = boxContext.getOutputChunk(0); - - m_sequenceStimulationDecoder->process(); - - m_lastTime = boxContext.getInputChunkEndTime(0, i); - - if (m_sequenceStimulationDecoder->isOutputTriggerActive(OVP_GD_Algorithm_StimulationDecoder_OutputTriggerId_ReceivedHeader)) - { - m_targetFlaggingStimulationEncoder->process(OVP_GD_Algorithm_StimulationEncoder_InputTriggerId_EncodeHeader); - } - - if (m_sequenceStimulationDecoder->isOutputTriggerActive(OVP_GD_Algorithm_StimulationDecoder_OutputTriggerId_ReceivedBuffer)) - { - IStimulationSet* stimulationSet = m_sequenceStimulationSet; - for (size_t j = 0; j < stimulationSet->getStimulationCount(); ++j) - { - uint64_t id = stimulationSet->getStimulationIdentifier(j); - bool flash = false; - int row = -1; - int col = -1; - bool isTarget = false; - - if (id >= m_rowStimulationBase && id < m_rowStimulationBase + m_nRow) - { - row = int(id - m_rowStimulationBase); - flash = true; - isTarget = (row == m_lastTargetRow); - } - if (id >= m_columnStimulationBase && id < m_columnStimulationBase + m_nCol) - { - col = int(id - m_columnStimulationBase); - flash = true; - isTarget = (col == m_lastTargetCol); - } - if (id == OVTK_StimulationId_VisualStimulationStop) - { - this->getLogManager() << Kernel::LogLevel_Debug << "Received OVTK_StimulationId_VisualStimulationStop - resets grid\n"; - this->cacheForEach(&CBoxAlgorithmP300TactileVisualization::cacheChangeBackgroundCB, &m_noFlashBgColor); - this->cacheForEach(&CBoxAlgorithmP300TactileVisualization::cacheChangeForegroundCB, &m_noFlashFgColor); - this->cacheForEach(&CBoxAlgorithmP300TactileVisualization::cacheChangeFontCB, m_noFlashFontDesc); - } - if (id == OVTK_StimulationId_Reset) - { - gtk_label_set_text(m_target, ""); - gtk_label_set_text(m_result, ""); - } - - if (flash) - { - this->cacheForEachIf(row, col, &CBoxAlgorithmP300TactileVisualization::cacheChangeBackgroundCB, - &CBoxAlgorithmP300TactileVisualization::cacheChangeBackgroundCB, &m_flashBgColor, &m_noFlashBgColor); - this->cacheForEachIf(row, col, &CBoxAlgorithmP300TactileVisualization::cacheChangeForegroundCB, - &CBoxAlgorithmP300TactileVisualization::cacheChangeForegroundCB, &m_flashFgColor, &m_noFlashFgColor); - this->cacheForEachIf(row, col, &CBoxAlgorithmP300TactileVisualization::cacheChangeFontCB, - &CBoxAlgorithmP300TactileVisualization::cacheChangeFontCB, m_flashFontDesc, m_noFlashFontDesc); - - // We now know if this flash corresponds to the current target or not, merge this to the outgoing stimulation stream - if (isTarget) - { - m_stimuliQueue.push_back(OVTK_StimulationId_Target); - flaggingStimulationSet.appendStimulation(OVTK_StimulationId_Target, stimulationSet->getStimulationDate(j), 0); - } - else - { - m_stimuliQueue.push_back(OVTK_StimulationId_NonTarget); - flaggingStimulationSet.appendStimulation(OVTK_StimulationId_NonTarget, stimulationSet->getStimulationDate(j), 0); - } - } - - // Pass the stimulation to the server also as-is. If its a flash, it can be differentiated from a 'target' spec because - // its NOT between OVTK_StimulationId_RestStart and OVTK_StimulationId_RestStop stimuli in the generated P300 timeline. - m_stimuliQueue.push_back(id); - } - m_targetFlaggingStimulationEncoder->process(OVP_GD_Algorithm_StimulationEncoder_InputTriggerId_EncodeBuffer); - } - - if (m_sequenceStimulationDecoder->isOutputTriggerActive(OVP_GD_Algorithm_StimulationDecoder_OutputTriggerId_ReceivedEnd)) - { - m_targetFlaggingStimulationEncoder->process(OVP_GD_Algorithm_StimulationEncoder_InputTriggerId_EncodeEnd); - } - - boxContext.markInputAsDeprecated(0, i); - boxContext.markOutputAsReadyToSend(0, boxContext.getInputChunkStartTime(0, i), boxContext.getInputChunkEndTime(0, i)); - } - - // --- Target stimulations - - for (size_t i = 0; i < boxContext.getInputChunkCount(1); ++i) - { - if (m_lastTime >= boxContext.getInputChunkStartTime(1, i)) - { - m_targetMemoryBuffer = boxContext.getInputChunk(1, i); - m_targetStimulationDecoder->process(); - - if (m_targetStimulationDecoder->isOutputTriggerActive(OVP_GD_Algorithm_StimulationDecoder_OutputTriggerId_ReceivedHeader)) { } - - if (m_targetStimulationDecoder->isOutputTriggerActive(OVP_GD_Algorithm_StimulationDecoder_OutputTriggerId_ReceivedBuffer)) - { - IStimulationSet* stimulationSet = m_targetStimulationSet; - for (size_t j = 0; j < stimulationSet->getStimulationCount(); ++j) - { - uint64_t id = stimulationSet->getStimulationIdentifier(j); - bool target = false; - if (id >= m_rowStimulationBase && id < m_rowStimulationBase + m_nRow) - { - this->getLogManager() << Kernel::LogLevel_Debug << "Received Target Row " << id << "\n"; - m_targetRow = int(id - m_rowStimulationBase); - target = true; - } - if (id >= m_columnStimulationBase && id < m_columnStimulationBase + m_nCol) - { - this->getLogManager() << Kernel::LogLevel_Debug << "Received Target Column " << id << "\n"; - m_targetCol = int(id - m_columnStimulationBase); - target = true; - } - - if (target && m_targetRow != -1 && m_targetCol != -1) - { - this->getLogManager() << Kernel::LogLevel_Debug << "Displays Target Cell\n"; - this->cacheForEachIf(m_targetRow, m_targetCol, &CBoxAlgorithmP300TactileVisualization::cacheChangeBackgroundCB, - &CBoxAlgorithmP300TactileVisualization::cacheChangeNullCB, &m_targetBgColor, nullptr); - this->cacheForEachIf(m_targetRow, m_targetCol, &CBoxAlgorithmP300TactileVisualization::cacheChangeForegroundCB, - &CBoxAlgorithmP300TactileVisualization::cacheChangeNullCB, &m_targetFgColor, nullptr); - this->cacheForEachIf(m_targetRow, m_targetCol, &CBoxAlgorithmP300TactileVisualization::cacheChangeFontCB, - &CBoxAlgorithmP300TactileVisualization::cacheChangeNullCB, m_targetFontDesc, nullptr); - - std::vector widgets; - this->cacheForEachIf(m_targetRow, m_targetCol, &CBoxAlgorithmP300TactileVisualization::cacheCollectChildWidgetCB, - &CBoxAlgorithmP300TactileVisualization::cacheCollectChildWidgetCB, &widgets, nullptr); - - // Merge the current target into the stimulation stream. It can be differentiated - // from a 'flash' spec because it IS between OVTK_StimulationId_RestStart and - // OVTK_StimulationId_RestStop stimulations in the P300 timeline. - { - m_stimuliQueue.push_back(m_targetRow + m_rowStimulationBase); - m_stimuliQueue.push_back(m_targetCol + m_columnStimulationBase); - } - - if (widgets.size() == 1) - { - if (GTK_IS_LABEL(widgets[0])) - { - std::string label; - label = gtk_label_get_text(m_target); - label += gtk_label_get_text(GTK_LABEL(widgets[0])); - gtk_label_set_text(m_target, label.c_str()); - } - else - { - this->getLogManager() << Kernel::LogLevel_Warning << "Expected label class widget... could not find a valid text to append\n"; - } - } - else - { - this->getLogManager() << Kernel::LogLevel_Warning << "Did not find a unique widget at row:" << size_t(m_targetRow) << " column:" << - size_t(m_targetCol) << "\n"; - } - - m_targetHistory.emplace_back(m_targetRow, m_targetCol); - m_lastTargetRow = m_targetRow; - m_lastTargetCol = m_targetCol; - m_targetRow = -1; - m_targetCol = -1; - } - } - } - - if (m_targetStimulationDecoder->isOutputTriggerActive(OVP_GD_Algorithm_StimulationDecoder_OutputTriggerId_ReceivedEnd)) { } - - boxContext.markInputAsDeprecated(1, i); - } - } - - // --- Selection stimulations - - for (size_t k = 2; k < 4; ++k) - { - Kernel::IAlgorithmProxy* decoder = (k == 2 ? m_rowSelectionStimulationDecoder : m_columnSelectionStimulationDecoder); - Kernel::TParameterHandler selectionMemoryBuffer( - decoder->getInputParameter(OVP_GD_Algorithm_StimulationDecoder_InputParameterId_MemoryBufferToDecode)); - Kernel::TParameterHandler selectionStimulationSet( - decoder->getOutputParameter(OVP_GD_Algorithm_StimulationDecoder_OutputParameterId_StimulationSet)); - - for (size_t i = 0; i < boxContext.getInputChunkCount(k); ++i) - { - if (m_lastTime >= boxContext.getInputChunkStartTime(k, i)) - { - selectionMemoryBuffer = boxContext.getInputChunk(k, i); - decoder->process(); - - if (decoder->isOutputTriggerActive(OVP_GD_Algorithm_StimulationDecoder_OutputTriggerId_ReceivedHeader)) { } - - if (decoder->isOutputTriggerActive(OVP_GD_Algorithm_StimulationDecoder_OutputTriggerId_ReceivedBuffer)) - { - IStimulationSet* stimulationSet = selectionStimulationSet; - for (size_t j = 0; j < stimulationSet->getStimulationCount(); ++j) - { - uint64_t id = stimulationSet->getStimulationIdentifier(j); - bool selected = false; - if (id >= m_rowStimulationBase && id < m_rowStimulationBase + m_nRow) - { - this->getLogManager() << Kernel::LogLevel_Debug << "Received Selected Row " << id << "\n"; - m_selectedRow = int(id - m_rowStimulationBase); - selected = true; - } - if (id >= m_columnStimulationBase && id < m_columnStimulationBase + m_nRow) - { - this->getLogManager() << Kernel::LogLevel_Debug << "Received Selected Column " << id << "\n"; - m_selectedCol = int(id - m_columnStimulationBase); - selected = true; - } - if (id == OVTK_StimulationId_Label_00) - { - if (k == 2) { m_selectedRow = -2; } - if (k == 3) { m_selectedCol = -2; } - selected = true; - } - if (selected && m_selectedRow != -1 && m_selectedCol != -1) - { - if (m_selectedRow >= 0 && m_selectedCol >= 0) - { - this->getLogManager() << Kernel::LogLevel_Debug << "Displays Selected Cell\n"; - this->cacheForEachIf(m_selectedRow, m_selectedCol, &CBoxAlgorithmP300TactileVisualization::cacheChangeBackgroundCB, - &CBoxAlgorithmP300TactileVisualization::cacheChangeNullCB, &m_selectedBgColor, nullptr); - this->cacheForEachIf(m_selectedRow, m_selectedCol, &CBoxAlgorithmP300TactileVisualization::cacheChangeForegroundCB, - &CBoxAlgorithmP300TactileVisualization::cacheChangeNullCB, &m_selectedFgColor, nullptr); - this->cacheForEachIf(m_selectedRow, m_selectedCol, &CBoxAlgorithmP300TactileVisualization::cacheChangeFontCB, - &CBoxAlgorithmP300TactileVisualization::cacheChangeNullCB, m_selectedFontDesc, nullptr); - - std::vector widgets; - this->cacheForEachIf(m_selectedRow, m_selectedCol, &CBoxAlgorithmP300TactileVisualization::cacheCollectChildWidgetCB, - &CBoxAlgorithmP300TactileVisualization::cacheCollectChildWidgetCB, &widgets, nullptr); - - if (widgets.size() == 1) - { - if (GTK_IS_LABEL(widgets[0])) - { - std::string label; - label = gtk_label_get_text(GTK_LABEL(widgets[0])); - if (!m_targetHistory.empty()) - { - auto it = m_targetHistory.begin(); - bool correct = (it->first == m_selectedRow && it->second == m_selectedCol); - bool halfCorrect = (it->first == m_selectedRow || it->second == m_selectedCol); - m_targetHistory.pop_front(); - std::string tmp; - if (correct) { tmp = ""; } - else if (halfCorrect) { tmp = ""; } - else { tmp = ""; } - label = tmp.append(label).append(""); - } - label = std::string(gtk_label_get_label(m_result)).append(label); - gtk_label_set_markup(m_result, label.c_str()); - } - else - { - this->getLogManager() << Kernel::LogLevel_Warning << - "Expected label class widget... could not find a valid text to append\n"; - } - } - else - { - this->getLogManager() << Kernel::LogLevel_Warning << "Did not find a unique widget at row : " << size_t(m_selectedRow) << - " column : " << size_t(m_selectedCol) << "\n"; - } - } - else - { - this->getLogManager() << Kernel::LogLevel_Trace << "Selection Rejected !\n"; - std::string label; - label = gtk_label_get_text(m_result); - label += "*"; - gtk_label_set_text(m_result, label.c_str()); - } - - m_selectedRow = -1; - m_selectedCol = -1; - } - //Load new menuentries - uint64_t label_id = id - m_rowStimulationBase; - if(main) - { - set_labeltext(label_id); - main = false; - } - else if(label_id == 5) - { - set_labeltext(6); - main = true; - } - } - } - - if (decoder->isOutputTriggerActive(OVP_GD_Algorithm_StimulationDecoder_OutputTriggerId_ReceivedEnd)) { } - boxContext.markInputAsDeprecated(k, i); - } - } - } - - // After any possible rendering, we flush the accumulated stimuli. The default idle func is low priority, so it should be run after rendering by gtk. - if (m_idleFuncTag == 0) { m_idleFuncTag = g_idle_add(FlushCB, this); } - - return true; -} - -// _________________________________________________________________________________________________________________________________________________________ -// - -void CBoxAlgorithmP300TactileVisualization::cacheBuildFromTable(GtkTable* table) -{ - if (table) - { - const GdkColor white = InitGDKColor(65535, 65535, 65535, 65535); - - for (GList* list = table->children; list; list = list->next) - { - GtkTableChild* child = static_cast(list->data); - - for (size_t i = child->top_attach; i < child->bottom_attach; ++i) - { - for (size_t j = child->left_attach; j < child->right_attach; ++j) - { - widget_style_t& style = m_cache[i][j]; - style.widget = child->widget; - style.childWidget = gtk_bin_get_child(GTK_BIN(child->widget)); - style.bgColor = white; - style.fgColor = white; - style.fontDesc = nullptr; - } - } - } - } -} - -void CBoxAlgorithmP300TactileVisualization::cacheForEach(const cache_callback callback, void* data) -{ - for (auto i = m_cache.begin(); i != m_cache.end(); ++i) - { - for (auto j = i->second.begin(); j != i->second.end(); ++j) { (this->*callback)(j->second, data); } - } -} - -void CBoxAlgorithmP300TactileVisualization::cacheForEachIf(const int iLine, const int iColumn, const cache_callback ifCB, const cache_callback elseCB, - void* ifUserData, void* elseUserData) -{ - for (auto i = m_cache.begin(); i != m_cache.end(); ++i) - { - for (auto j = i->second.begin(); j != i->second.end(); ++j) - { - const bool line = (iLine != -1); - const bool column = (iColumn != -1); - bool inLine = false; - bool inCol = false; - bool first; - - if (line && size_t(iLine) == i->first) { inLine = true; } - if (column && size_t(iColumn) == j->first) { inCol = true; } - - if (line && column) { first = inLine && inCol; } - else { first = inLine || inCol; } - - if (first) { (this->*ifCB)(j->second, ifUserData); } - else { (this->*elseCB)(j->second, elseUserData); } - } - } -} - -void CBoxAlgorithmP300TactileVisualization::cacheChangeNullCB(widget_style_t& /*rWidgetStyle*/, void* /*data*/) { } - -void CBoxAlgorithmP300TactileVisualization::cacheChangeBackgroundCB(widget_style_t& style, void* data) -{ - GdkColor oColor = *static_cast(data); - if (memcmp(&style.bgColor, &oColor, sizeof(GdkColor)) != 0) - { - gtk_widget_modify_bg(style.widget, GTK_STATE_NORMAL, &oColor); - style.bgColor = oColor; - } -} - -void CBoxAlgorithmP300TactileVisualization::cacheChangeForegroundCB(widget_style_t& style, void* data) -{ - GdkColor oColor = *static_cast(data); - if (memcmp(&style.fgColor, &oColor, sizeof(GdkColor)) != 0) - { - gtk_widget_modify_fg(style.childWidget, GTK_STATE_NORMAL, &oColor); - style.fgColor = oColor; - } -} - -void CBoxAlgorithmP300TactileVisualization::cacheChangeFontCB(widget_style_t& style, void* data) -{ - auto* pFontDescription = static_cast(data); - if (style.fontDesc != pFontDescription) - { - gtk_widget_modify_font(style.childWidget, pFontDescription); - style.fontDesc = pFontDescription; - } -} - -void CBoxAlgorithmP300TactileVisualization::cacheCollectWidgetCB(widget_style_t& style, void* data) -{ - if (data) { (static_cast*>(data))->push_back(style.widget); } -} - -void CBoxAlgorithmP300TactileVisualization::cacheCollectChildWidgetCB(widget_style_t& style, void* data) -{ - if (data) { (static_cast*>(data))->push_back(style.childWidget); } -} - -// Note that we don't need concurrency control here as gtk callbacks run in the main thread -void CBoxAlgorithmP300TactileVisualization::flushQueue() -{ - for (const auto& stimulation : m_stimuliQueue) { m_stimulusSender->sendStimulation(stimulation); } - m_stimuliQueue.clear(); - - // This function will be automatically removed after completion, so set to 0 - m_idleFuncTag = 0; -} - -} // namespace Tactilebci -} // namespace Plugins -} // namespace OpenViBE