Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a538a0bbe6 | ||
|
|
44c73e4a59 | ||
|
|
7fb9ca1d2b | ||
|
|
ba49972b50 |
-10
@@ -1,10 +0,0 @@
|
||||
#!/usr/bin/env xdg-open
|
||||
[Desktop Entry]
|
||||
Version=1.0
|
||||
Type=Application
|
||||
Terminal=false
|
||||
Icon[C]=/home/ubuntu/Downloads/icon.ico
|
||||
Name[C]=BCI
|
||||
Exec=/home/ubuntu/Desktop/BCIProjekt/start.sh
|
||||
Name=BCI
|
||||
Icon=/home/ubuntu/Downloads/icon.ico
|
||||
@@ -0,0 +1,65 @@
|
||||
-->TODO: -Interface Box erstellen(UDP,Serial,(BT),...)
|
||||
-Offline Test
|
||||
-Online Test
|
||||
|
||||
06.05.2022:
|
||||
-->ui files für unterschiedliche Anzahl von Tactilos erstellt (p300-tactile-2.ui, p300-tactile-3.ui, ...)
|
||||
-->Lua files der szenarios angepasst, um die Variation der Tactiloanzahl zu ermöglichen
|
||||
-->arduino Firmware auf zehn mögliche Tactilos erweitert
|
||||
-->arduino Firmware ports angepasst (nutzung der PWM-fähigen ports)
|
||||
|
||||
02.05.2022:
|
||||
-->FindThirdPartyBoost_System aus Cmakelist.txt entfernt (entfaellt mit OpenViBE3.3)
|
||||
-->Szenarios angepasst (einige Boxen wurden mit OpenViBE3.3 ueberarbeitet)
|
||||
-->UDPSender, TactileVisualization und TactiloStimulator Boxen erweitert um die Möglichkeit die Anzahl der Tactilos des Systems einzustellen
|
||||
|
||||
28.02.2022:
|
||||
-->Box für die Ansteuerung der Tactilos über die Lattepanda GPIOs hinzugefügt
|
||||
|
||||
11.02.2022:
|
||||
Änderungen am TactileBCI SourceCode:
|
||||
-->neue Box P300 Tactile Visualization für die Organisation von Menüs/Submenüs des Tactilen BCIs erstellt(Basierend auf der P300 Speller Visualization)
|
||||
|
||||
-->Das LogLevel der Nachrichten in der UDPStimCodeSender Box auf Debug gesetzt um nicht standardmäßig die große Menge an Nachrichten anzuzeigen
|
||||
|
||||
Änderungen an den Szenarios:
|
||||
-->In 1-Acquisition und 4-Online P300 Speller Visualization durch die neue Box P300 Tactile Visualization ersetzt
|
||||
|
||||
Änderungen in OV_TACTILE.conf:
|
||||
-->Schriftgröße von Target, Flash und Selected angepasst
|
||||
|
||||
|
||||
|
||||
05.02.2022:
|
||||
-->die verschiedenen repositories zu einem zusammengefasst
|
||||
|
||||
|
||||
|
||||
29.01.2022:
|
||||
Änderungen an den Szenarios:
|
||||
1.Szenario Acquisition:
|
||||
-->Die Filterung des Signals erfolgt jetzt hier, statt in den Szenarien für die filterkonfiguration
|
||||
-->In der UI des Szenarios gibt es jetzt einen zweiten reiter zur anzeige des EEG-Signals
|
||||
|
||||
2.Szenario Train xDAWN:
|
||||
-->Das aufgezeichnete signal ist jetzt bereits gefiltert, dementsprechend entfällt die filterung hier
|
||||
|
||||
3.Szenario Train p300-classifier:
|
||||
-->Das aufgezeichnete signal ist jetzt bereits gefiltert, dementsprechend entfällt die filterung hier
|
||||
|
||||
4.Szenario Online:
|
||||
-->Analog zu acquisition wird auch hier das gefilterte signal aufgezeichnet und nicht mehr das ungefilterte
|
||||
-->Auch hier lässt sich jetzt in einem zusätzlichen Reiter das EEG Signal anzeigen
|
||||
|
||||
Änderungen an Scripts:
|
||||
p300-tactile-stimulator.lua:
|
||||
-->Da die Box derzeit keinen Input hat, wurde eine Zeile entfernt, welche die letzten erhaltenen daten löscht
|
||||
|
||||
Änderungen an der UDPSender Box:
|
||||
-->Die weitergabe der Daten am boxoutput wurde verändert, um ein timingproblem zu beheben
|
||||
|
||||
Änderungen im OpenVibe Sourcecode:
|
||||
\meta\sdk\plugins\processing\signal-processing\src\box-algorithms\ovpCBoxAlgorithmXDAWNTrainer.cpp:
|
||||
-->Z.338-339 geändert, damit die cfg mit gültigen werten gefüllt wird: fprintf(file, "\t<SettingValue>%u</SettingValue>\n", (unsigned int)m_filterDim);
|
||||
fprintf(file, "\t<SettingValue>%u</SettingValue>\n", (unsigned int)nChannel);
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
if(OV_DISABLE_GTK)
|
||||
message(STATUS "Skipping Plugins: Simple Visualization, no GTK")
|
||||
return()
|
||||
endif(OV_DISABLE_GTK)
|
||||
|
||||
project(openvibe-plugins-tactile-bci VERSION ${OPENVIBE_MAJOR_VERSION}.${OPENVIBE_MINOR_VERSION}.${OPENVIBE_PATCH_VERSION})
|
||||
|
||||
file(GLOB_RECURSE SRC_FILES src/*.cpp src/*.h src/*.inl)
|
||||
|
||||
add_library(${PROJECT_NAME} SHARED ${SRC_FILES})
|
||||
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
openvibe
|
||||
openvibe-common
|
||||
openvibe-toolkit
|
||||
openvibe-module-ebml
|
||||
openvibe-module-system
|
||||
openvibe-visualization-toolkit
|
||||
)
|
||||
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES
|
||||
VERSION ${PROJECT_VERSION}
|
||||
SOVERSION ${PROJECT_VERSION_MAJOR}
|
||||
FOLDER ${PLUGINS_FOLDER}
|
||||
COMPILE_FLAGS "-DOVP_Exports -DOVP_Shared")
|
||||
|
||||
add_definitions(-DTARGET_HAS_ThirdPartyOpenViBEPluginsGlobalDefines)
|
||||
add_definitions(-DBOOST_DATE_TIME_NO_LIB)
|
||||
if(WIN32)
|
||||
add_definitions(-D_WIN32_WINNT=0x0501)
|
||||
endif(WIN32)
|
||||
|
||||
include("FindOpenViBEModuleTCPTagging")
|
||||
include("FindThirdPartyGTK")
|
||||
# need boost for UDPStimcodeSender and TactileStimulation
|
||||
include("FindThirdPartyBoost")
|
||||
|
||||
# -----------------------------
|
||||
# Install files
|
||||
# -----------------------------
|
||||
install(TARGETS ${PROJECT_NAME}
|
||||
RUNTIME DESTINATION ${DIST_BINDIR}
|
||||
LIBRARY DESTINATION ${DIST_LIBDIR}
|
||||
ARCHIVE DESTINATION ${DIST_LIBDIR})
|
||||
|
||||
install(DIRECTORY scenarios/ DESTINATION ${DIST_DATADIR}/openvibe/thn_bci/scenarios)
|
||||
@@ -1,358 +0,0 @@
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
Im Controller wird in der Init eine View erstellt und gestartet. Zudem wird der Acquisitionserver
|
||||
gestartet, die shared Librarz geladen, die Konstanten Initialtisiert.
|
||||
Mittels der Funktion Action Performed wird die jeweilige Reaktion auf die Benutyeraktion ausgeloest.
|
||||
Hierfuer stehen die verschiedenen eigenen Funktionen die die Reaktion in der richtigen reihenfolge
|
||||
an ein neu instanizieertes Modell weitergibt.
|
||||
Zudem stehen einige Funktionen zur Informationsuebergabe an die View oder das Modell zur Verfuegung
|
||||
'''
|
||||
|
||||
|
||||
from UIModellVisuell import *
|
||||
from UIModellTaktil import *
|
||||
from UIModell import *
|
||||
import UIViewTKinter as viewTkinter
|
||||
from shutil import copyfile
|
||||
import ctypes
|
||||
import os
|
||||
|
||||
|
||||
|
||||
class Controller():
|
||||
|
||||
def __init__(self):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
In der Init wird die shared Library geladen, die View erstellt und geoeffnet und die verschiedenen
|
||||
Konstanten gesetzt
|
||||
'''
|
||||
|
||||
self.getSharedLibrary()
|
||||
|
||||
self.view = viewTkinter.View(self, self.dll.getDefaultPath_visuell())
|
||||
self.modi = "visuellesBCI"
|
||||
self.pathOVFile = self.dll.getPathOVFile_visuell()
|
||||
self.pathSpatialCfg = self.dll.getSpatialCFGFile_visuell()
|
||||
self.pathClassifierCfg = self.dll.getClassifierCFGFile_visuell()
|
||||
self.infotext = ""
|
||||
|
||||
self.commands = {
|
||||
"copySpelling": self.commandoCopySpelling,
|
||||
"stop": self.commandStop,
|
||||
"freeSpelling": self.commandFreeSpelling,
|
||||
"test": self.test,
|
||||
"wechsel": self.wechsel,
|
||||
"speicherort": self.setDataset
|
||||
}
|
||||
|
||||
self.nexts = {
|
||||
"filterXdawn" : self.filterXdawn,
|
||||
"filterClassic": self.filterClassic,
|
||||
"save": self.speichern
|
||||
}
|
||||
|
||||
self.pagesTaktil = {
|
||||
"stop": "StartPage",
|
||||
"copySpelling": "WorkingPageTaktil",
|
||||
"freeSpelling": "WorkingPageTaktil",
|
||||
"test": "WorkingPageTaktil"
|
||||
}
|
||||
self.pagesVisuell = {
|
||||
"stop": "StartPage",
|
||||
"copySpelling": "WorkingPageVisuell",
|
||||
"freeSpelling": "WorkingPageVisuell",
|
||||
"test": "WorkingPageVisuell"
|
||||
}
|
||||
self.acquisitionServer = Modell(self, self.dll)
|
||||
self.acquisitionServer.start()
|
||||
|
||||
self.model = None
|
||||
self.view.mainloop()
|
||||
|
||||
def getSharedLibrary(self):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
Laedt die shared Library (diese muss sich im gleichen Ordner wie die ausfuehrunde Datei befinden)
|
||||
und setzt die Eingabe und Rueckgabewerte.
|
||||
'''
|
||||
|
||||
path = os.path.abspath(".")
|
||||
path = path + "/dll.so"
|
||||
self.dll = ctypes.CDLL(path)
|
||||
|
||||
self.dll.getCommandFreespellingTaktil.argtypes = []
|
||||
self.dll.getCommandFreespellingTaktil.restype = ctypes.c_char_p
|
||||
|
||||
self.dll.getCommandFreespellingVisuell.argtypes = []
|
||||
self.dll.getCommandFreespellingVisuell.restype = ctypes.c_char_p
|
||||
|
||||
self.dll.getCommandCopyspellingTaktil.argtypes = []
|
||||
self.dll.getCommandCopyspellingTaktil.restype = ctypes.c_char_p
|
||||
|
||||
self.dll.getCommandCopyspellingVisuell.argtypes = []
|
||||
self.dll.getCommandCopyspellingVisuell.restype = ctypes.c_char_p
|
||||
|
||||
self.dll.getCommandXDawn_taktil.argtypes = []
|
||||
self.dll.getCommandXDawn_taktil.restype = ctypes.c_char_p
|
||||
|
||||
self.dll.getCommandXDawn_visuell.argtypes = []
|
||||
self.dll.getCommandXDawn_visuell.restype = ctypes.c_char_p
|
||||
|
||||
self.dll.getCommandClassifier_visuell.argtypes = []
|
||||
self.dll.getCommandClassifier_visuell.restype = ctypes.c_char_p
|
||||
|
||||
self.dll.getCommandClassifier_taktil.argtypes = []
|
||||
self.dll.getCommandClassifier_taktil.restype = ctypes.c_char_p
|
||||
|
||||
self.dll.getDefaultPath_visuell.argtypes = []
|
||||
self.dll.getDefaultPath_visuell.restype = ctypes.c_char_p
|
||||
|
||||
self.dll.getDefaultPath_taktil.argtypes = []
|
||||
self.dll.getDefaultPath_taktil.restype = ctypes.c_char_p
|
||||
|
||||
self.dll.getPathOVFile_visuell.argtypes = []
|
||||
self.dll.getPathOVFile_visuell.restype = ctypes.c_char_p
|
||||
|
||||
self.dll.getSpatialCFGFile_visuell.argtypes = []
|
||||
self.dll.getSpatialCFGFile_visuell.restype = ctypes.c_char_p
|
||||
|
||||
self.dll.getClassifierCFGFile_visuell.argtypes = []
|
||||
self.dll.getClassifierCFGFile_visuell.restype = ctypes.c_char_p
|
||||
|
||||
self.dll.getPathOVFile_taktil.argtypes = []
|
||||
self.dll.getPathOVFile_taktil.restype = ctypes.c_char_p
|
||||
|
||||
self.dll.getSpatialCFGFile_taktil.argtypes = []
|
||||
self.dll.getSpatialCFGFile_taktil.restype = ctypes.c_char_p
|
||||
|
||||
self.dll.getClassifierCFGFile_taktil.argtypes = []
|
||||
self.dll.getClassifierCFGFile_taktil.restype = ctypes.c_char_p
|
||||
|
||||
self.dll.getCommandStartAquisitionServer.argtypes = []
|
||||
self.dll.getCommandStartAquisitionServer.restype = ctypes.c_char_p
|
||||
|
||||
def actionPerformed(self, action):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
Wird aufgerufen wenn ein Button in der Init gedrueckt wird zuerst wird kontrolliert ob die Seite
|
||||
gewechselt werden muss, dann nach dem Buttonnamen die Funktion zugeordnert. Der Funktion zum
|
||||
Buttomnamen wird in der Init festgelegt
|
||||
'''
|
||||
|
||||
self.changePage(action)
|
||||
func = self.commands.get(action)
|
||||
if(func is not None):
|
||||
func()
|
||||
else:
|
||||
print("Kommado existiert nicht")
|
||||
|
||||
|
||||
def changePage(self,action):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
Change Page ruft je nach Aktion und Modi die jeweilige Seite auf
|
||||
'''
|
||||
|
||||
if(self.modi == "taktilesBCI"):
|
||||
page = self.pagesTaktil.get(action)
|
||||
elif(self.modi == "visuellesBCI"):
|
||||
page = self.pagesVisuell.get(action)
|
||||
if(page is not None):
|
||||
self.view.changeFrame(page)
|
||||
|
||||
def wechsel(self):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
Wechsel aendert den Modi. Dafuer wird zuerst der aktuelle Modi ueberprueft und dann auf den anderen
|
||||
Modi gesetzt.
|
||||
'''
|
||||
|
||||
self.resetInfo()
|
||||
self.addInfoText("")
|
||||
if(self.modi == "taktilesBCI"):
|
||||
self.view.setChangeBtnText("Wechsel zu taktilen BCI")
|
||||
self.view.setTitleText("visuelles BCI")
|
||||
self.view.setDefaultPath(self.dll.getDefaultPath_visuell())
|
||||
self.pathOVFile = self.dll.getPathOVFile_visuell()
|
||||
self.pathSpatialCfg = self.dll.getSpatialCFGFile_visuell()
|
||||
self.pathClassifierCfg = self.dll.getClassifierCFGFile_visuell()
|
||||
self.modi = "visuellesBCI"
|
||||
elif(self.modi == "visuellesBCI"):
|
||||
self.setTitle("taktiles BCI")
|
||||
self.view.setChangeBtnText("Wechsel zu visuellen BCI")
|
||||
self.view.setDefaultPath(self.dll.getDefaultPath_taktil())
|
||||
self.pathOVFile = self.dll.getPathOVFile_taktil()
|
||||
self.pathSpatialCfg = self.dll.getSpatialCFGFile_taktil()
|
||||
self.pathClassifierCfg = self.dll.getClassifierCFGFile_taktil()
|
||||
self.modi = "taktilesBCI"
|
||||
|
||||
def speichern(self):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
wird nach dem Classifier Training aufgerufen und speichert die erstellte .ov Datei und die
|
||||
spatial.cfg, classifier.cgf-Dateine unter dem ausgewaehlten Ordnername.
|
||||
(Ordnername wird zu Beginn des CopySpellings festgelegt)
|
||||
'''
|
||||
print("saveFile")
|
||||
print(self.file)
|
||||
if not os.path.exists(self.file):
|
||||
os.mkdir(self.file)
|
||||
copyfile(self.pathOVFile, (self.file + "/p300-xdawn-train.ov"))
|
||||
copyfile(self.pathClassifierCfg, (self.file + "/p300-classifier.cfg"))
|
||||
copyfile(self.pathSpatialCfg, (self.file + "/p300-spatial-filter.cfg"))
|
||||
|
||||
self.changeScreen("StartPage")
|
||||
|
||||
#copyfile(self.pathOVFile, self.file)
|
||||
|
||||
def setDataset(self):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
Legt fest welches Datenset fuer das Freestelling genutzt wird
|
||||
'''
|
||||
|
||||
file = self.view.openfiledialog()
|
||||
print(file)
|
||||
if not file:
|
||||
print("nichts ausgewaehlt")
|
||||
else:
|
||||
if os.path.exists((file + "/p300-classifier.cfg")):
|
||||
print("classifier kopiert")
|
||||
copyfile((file + "/p300-classifier.cfg"), self.pathClassifierCfg)
|
||||
if os.path.exists((file + "/p300-spatial-filter.cfg")):
|
||||
print("spatialfilter kopiert")
|
||||
copyfile((file + "/p300-spatial-filter.cfg"), self.pathSpatialCfg)
|
||||
if os.path.exists((file + "/p300-xdawn-train.ov")):
|
||||
print(".ov kopiert")
|
||||
copyfile((file + "/p300-xdawn-train.ov"), self.pathOVFile)
|
||||
|
||||
|
||||
|
||||
def test(self):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
Funktion zum testen von xDawn und ClassifierTraining
|
||||
'''
|
||||
self.file = self.view.savefiledialog()
|
||||
if(self.modi == "taktilesBCI"):
|
||||
self.model = ModellTaktil(self, dll=self.dll)
|
||||
elif(self.modi == "visuellesBCI"):
|
||||
self.model = ModellVisuell(self, dll=self.dll)
|
||||
self.model.setFunktion(self.model.trainXDawn)
|
||||
self.model.start()
|
||||
|
||||
def commandoCopySpelling(self):
|
||||
self.view.savefiledialog()
|
||||
|
||||
|
||||
def copyspelling(self, path):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
Speichert den gewuenschte Pfad und erstellt anschliessend ein Model (als Thread) und fuehrt die
|
||||
Funktion CopySpelling aus.
|
||||
'''
|
||||
self.file = path
|
||||
print(path)
|
||||
if self.file == "-1":
|
||||
print("kein gueltiger Pfad")
|
||||
self.view.changeFrame("StartPage")
|
||||
else:
|
||||
if(self.modi == "taktilesBCI"):
|
||||
self.model = ModellTaktil(self, dll=self.dll)
|
||||
elif(self.modi == "visuellesBCI"):
|
||||
self.model = ModellVisuell(self, dll=self.dll)
|
||||
self.model.setFunktion(self.model.startCopySpelling)
|
||||
self.model.start()
|
||||
|
||||
def filterXdawn(self):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
wird nach dem CopySpelling gestartet. Die Funktion erstellt ein Model (als Thread) und fuehrt die
|
||||
Funktion trainXDawn aus.
|
||||
'''
|
||||
print("filterXDawn-Controller -Modi: " + self.modi)
|
||||
if(self.modi == "taktilesBCI"):
|
||||
self.model = ModellTaktil(self, dll=self.dll)
|
||||
elif(self.modi == "visuellesBCI"):
|
||||
self.model = ModellVisuell(self, dll=self.dll)
|
||||
self.model.setFunktion(self.model.trainXDawn)
|
||||
self.model.start()
|
||||
|
||||
def filterClassic(self):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
wird nach dem xDawn-Training gestartet. Die Funktion erstellt ein Model (als Thread) und fuehrt die
|
||||
Funktion trainClassifier aus.
|
||||
'''
|
||||
|
||||
if(self.modi == "taktilesBCI"):
|
||||
self.model = ModellTaktil(self, dll=self.dll)
|
||||
elif(self.modi == "visuellesBCI"):
|
||||
self.model = ModellVisuell(self, dll=self.dll)
|
||||
self.model.setFunktion(self.model.trainClassifier)
|
||||
self.model.start()
|
||||
|
||||
def commandFreeSpelling(self):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
startet nach Benutzeraktion das Freespelling: ie Funktion erstellt ein Model (als Thread) und fuehrt die
|
||||
Funktion freespelling aus.
|
||||
'''
|
||||
print("freespelling")
|
||||
if(self.modi == "taktilesBCI"):
|
||||
self.model = ModellTaktil(self, dll=self.dll)
|
||||
elif(self.modi == "visuellesBCI"):
|
||||
self.model = ModellVisuell(self, dll=self.dll)
|
||||
self.model.setFunktion(self.model.freeSpelling)
|
||||
self.model.start()
|
||||
|
||||
|
||||
def commandStop(self):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
Wird nach Benutzeraktion aufgerufen und stopt, falls vorhanden, den ablaufenden Thread und schliesst
|
||||
Openvibe
|
||||
'''
|
||||
if(self.model is not None):
|
||||
self.addInfoText("Aktion: STOP-Befehl\n")
|
||||
self.model.stop()
|
||||
self.model.join()
|
||||
self.model.killProzess()
|
||||
self.mode = None
|
||||
|
||||
def stopAcquisitionServer(self):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
Wird nur beim schliessen der GUI aufgerufen und stopt und schliesst den Acquisitionserver
|
||||
'''
|
||||
self.acquisitionServer.stop()
|
||||
self.acquisitionServer.join()
|
||||
self.acquisitionServer.killAcquisitionServer()
|
||||
self.acquisitionServer = None
|
||||
|
||||
def stop(self, next=None):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
Wird aus dem Modell nach Ablauf oder bei Fehler aufgerufen und stopt den aktuellen Thread.
|
||||
Anschliessend wird je nach Prozess die naechste Funktion (XDawn-Training oder Classifier) aufgerufen
|
||||
'''
|
||||
print("Stop aus Modell")
|
||||
self.model.stop()
|
||||
self.model.join()
|
||||
self.model.killProzess()
|
||||
self.mode = None
|
||||
if(next is not None):
|
||||
func = self.nexts.get(next)
|
||||
func()
|
||||
|
||||
|
||||
def addInfoText(self,text):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
Fuegt dem Infotext den Text hinzu und schreibt es in die Ausgabe
|
||||
'''
|
||||
self.infotext = self.infotext + text
|
||||
self.view.setInfoText(self.infotext)
|
||||
|
||||
def resetInfo(self):
|
||||
self.infotext = ""
|
||||
|
||||
def setTitle(self,text):
|
||||
self.view.setTitleText(text)
|
||||
|
||||
def changeScreen(self, pageName):
|
||||
self.view.changeFrame(pageName=pageName)
|
||||
|
||||
def getModi(self):
|
||||
return self.modi
|
||||
|
||||
def getWindowSize(self):
|
||||
return self.view.getWindowSize()
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,180 +0,0 @@
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
Das Model steuert stellt die Modi unabhaengigen Funktionen bereit
|
||||
'''
|
||||
|
||||
from subprocess import *
|
||||
from threading import Thread
|
||||
import time
|
||||
|
||||
class Modell(Thread):
|
||||
|
||||
def __init__(self,c, dll):
|
||||
Thread.__init__(self)
|
||||
self.controller = c
|
||||
self.dll = dll
|
||||
self.aktiv= True
|
||||
|
||||
def setFunktion(self, func, args=None, kwargs=None):
|
||||
pass
|
||||
|
||||
def startCopySpelling(self):
|
||||
pass
|
||||
|
||||
def trainXDawn(self):
|
||||
pass
|
||||
|
||||
def trainClassifier(self):
|
||||
pass
|
||||
|
||||
def freeSpelling(self):
|
||||
pass
|
||||
|
||||
def stop(self):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
Die Funktion stop stopt den ablaufenden Thread
|
||||
'''
|
||||
print("stop thread")
|
||||
self.aktiv = False
|
||||
|
||||
def run(self):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
Wird bei Thread.start() aus dem Controller aufgerufen und laeuft ab sobald der Thread destartet wurde
|
||||
'''
|
||||
print("start thread")
|
||||
#self.aktiv = True
|
||||
t = Thread(target=self.startAquisitionServer)
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
|
||||
while self.aktiv:
|
||||
time.sleep(0.1)
|
||||
|
||||
def killProzessParent(self):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
schliesst OpenVibe-Designer
|
||||
'''
|
||||
print('Parent start killing')
|
||||
pidOV = 0
|
||||
items = []
|
||||
|
||||
prozesse = Popen(["ps", "-e"], stdout=PIPE).communicate()[0].strip()
|
||||
zeilen = prozesse.split('\n')
|
||||
for z in zeilen:
|
||||
if(z.find("openvibe-design") != -1):
|
||||
z = z.strip()
|
||||
items = z.split(' ')
|
||||
pidOV = items[0]
|
||||
print(pidOV)
|
||||
if pidOV is not 0:
|
||||
#kill -TERM veranlasst dem Prozess sich selbst zu beenden (nicht erzwungen)
|
||||
try:
|
||||
Popen(["kill", "-TERM", str(pidOV)], stdout=PIPE).communicate()
|
||||
except:
|
||||
print("kein killing")
|
||||
|
||||
|
||||
print("killed openvibe-designer")
|
||||
|
||||
def killAcquisitionServer(self):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
schliesst den Acquisitionserver
|
||||
'''
|
||||
|
||||
print('start killing AS')
|
||||
pid = 0
|
||||
items = []
|
||||
|
||||
prozesse = Popen(["ps", "-e"], stdout=PIPE).communicate()[0].strip()
|
||||
zeilen = prozesse.split('\n')
|
||||
for z in zeilen:
|
||||
if(z.find("openvibe-acquis") != -1):
|
||||
z = z.strip()
|
||||
items = z.split(' ')
|
||||
pid = items[0]
|
||||
if pid is not 0:
|
||||
#kill -TERM veranlasst dem Prozess sich selbst zu beenden (nicht erzwungen)
|
||||
Popen(["kill", "-TERM", str(pid)], stdout=PIPE).communicate()
|
||||
|
||||
|
||||
print("killed openvibe-acquisitionserver")
|
||||
|
||||
|
||||
|
||||
def startAquisitionServer(self):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
startet den Acquisitionserver und steuert die Benutzerausgabe
|
||||
'''
|
||||
|
||||
print("start Aquisitionserver")
|
||||
self.controller.resetInfo()
|
||||
self.controller.addInfoText('Aquisitionserver -- Bitte starten sie den Server\n')
|
||||
|
||||
command = self.dll.getCommandStartAquisitionServer().split(" ")
|
||||
process = Popen(command, stdout=PIPE, universal_newlines=True)
|
||||
|
||||
self.openVibeAktiv = True
|
||||
while True:
|
||||
output = process.stdout.readline()
|
||||
print(output.strip())
|
||||
x1 = output.find("Connection succeeded")
|
||||
x2 = output.find("Now acquiring")
|
||||
x3 = output.find("Stopping the acquisition")
|
||||
x4 = output.find("Disconnecting")
|
||||
init = output.find("Loading plugin: Fiddler")
|
||||
y = output.find("Error")
|
||||
if(x1 != -1):
|
||||
self.controller.addInfoText('Aquisitionserver ist verbunden -- Bitte starten Sie den Server\n')
|
||||
elif(x2 != -1 ):
|
||||
self.controller.resetInfo()
|
||||
self.controller.addInfoText("Aquisitionserver gestartet\n")
|
||||
self.minimizeWindow("server")
|
||||
elif(x3 != -1 ):
|
||||
self.controller.addInfoText("AquisitionServer gestoppt -- Bitte starten Sie den Server\n")
|
||||
self.positionWindow("server")
|
||||
elif(x4 != -1 ):
|
||||
self.controller.addInfoText("Verbindung vom Aquisitionserver getrennt!\n")
|
||||
self.positionWindow("server")
|
||||
elif(init != -1 ):
|
||||
time.sleep(1)
|
||||
self.positionWindow("server")
|
||||
elif(y != -1 ):
|
||||
self.controller.addInfoText("Fehler beim Auisitionserver aufgetaucht\n")
|
||||
if not self.aktiv:
|
||||
print("stop")
|
||||
break
|
||||
|
||||
def positionWindow(self, name):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
positioniert das Fenster auf der GUI
|
||||
'''
|
||||
print("calls positionWindow")
|
||||
parameter = self.controller.getWindowSize()
|
||||
positionX = int(parameter[0]+ int(parameter[3] * 0.05))
|
||||
positionY = int(parameter[1]) + int(parameter[2]*0.08)
|
||||
height = int(parameter[2])*0.55
|
||||
width = int(parameter[3])*0.9
|
||||
windowID = Popen(["xdotool", "search", "--onlyvisible", "--name", name], stdout=PIPE).communicate()[0].strip()
|
||||
try:
|
||||
print(int(windowID))
|
||||
Popen(["xdotool", "windowsize", windowID, str(width), str(height)], stdout=PIPE).communicate()
|
||||
Popen(["xdotool", "windowmove", windowID, str(positionX), str(positionY)], stdout=PIPE).communicate()
|
||||
Popen(["xdotool", "windowactivate", windowID], stdout=PIPE).communicate()[0].strip()
|
||||
except:
|
||||
print("no window")
|
||||
print(windowID)
|
||||
self.controller.addInfoText("Fehler: kein Fenster gefunden!")
|
||||
|
||||
def minimizeWindow(self, name):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
minimiert das Fenster
|
||||
'''
|
||||
windowID = Popen(["xdotool", "search", "--onlyvisible", "--name", name], stdout=PIPE).communicate()[0].strip()
|
||||
try:
|
||||
print(int(windowID))
|
||||
Popen(["xdotool", "windowminimize", windowID], stdout=PIPE).communicate()
|
||||
except:
|
||||
print("no window")
|
||||
print(windowID)
|
||||
self.controller.addInfoText("Fehler: kein Fenster gefunden!")
|
||||
|
||||
|
||||
@@ -1,228 +0,0 @@
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
Das taktile Model steuert den Ablauf der aufrufe der Openvibe Funktionen fuer das taktile BCI
|
||||
noch nicht implementiert da noch kein Programm dafuer
|
||||
'''
|
||||
|
||||
from subprocess import *
|
||||
from threading import Thread
|
||||
import time
|
||||
from UIModell import *
|
||||
import re
|
||||
|
||||
class ModellTaktil(Modell):
|
||||
|
||||
def __init__(self,c, dll):
|
||||
Thread.__init__(self)
|
||||
Modell.__init__(self, c, dll)
|
||||
#self.dll = dll
|
||||
self.aktiv= True
|
||||
self.openVibeAktiv = False
|
||||
|
||||
def stop(self):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
Die Funktion stop stopt den ablaufenden Thread
|
||||
'''
|
||||
print("stop thread")
|
||||
self.aktiv = False
|
||||
|
||||
def setFunktion(self, func, args=None, kwargs=None):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
Mittels dieser Funktion kann die im Thread ablaufende Funktion und deren Argumente eingestellt werden
|
||||
'''
|
||||
self.func = func
|
||||
self.args = args or []
|
||||
self.kwargs = kwargs or {}
|
||||
|
||||
def run(self):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
Wird bei Thread.start() aus dem Controller aufgerufen und laeuft ab sobald der Thread destartet wurde
|
||||
'''
|
||||
print("start thread")
|
||||
#self.aktiv = True
|
||||
t = Thread(target=self.func, args=self.args, kwargs=self.kwargs)
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
|
||||
while self.aktiv:
|
||||
time.sleep(0.1)
|
||||
|
||||
|
||||
def startCopySpelling(self):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
Holt aus der shared Librarz die Befehle und startet das Copyspelling. Reagiert auf Error oder
|
||||
beenden. Bei Beenden startet es das XDawnTraining, bei Error wird der Vorgang gestoppt.
|
||||
'''
|
||||
print("start copySpelling")
|
||||
self.controller.resetInfo()
|
||||
self.controller.addInfoText('Starten des gefuerten Buchstabierens -- ')
|
||||
|
||||
command = self.dll.getCommandCopyspellingTaktil().split(" ")
|
||||
process = Popen(command, stdout=PIPE, universal_newlines=True)
|
||||
|
||||
self.openVibeAktiv = True
|
||||
while True:
|
||||
output = process.stdout.readline()
|
||||
print(output.strip())
|
||||
x = output.find("Application terminated")
|
||||
y = output.find("Error")
|
||||
if(x != -1):
|
||||
print("Training finished")
|
||||
process.terminate()
|
||||
self.controller.addInfoText('Buchstabieren beendet\n')
|
||||
self.controller.stop("filterXdawn")
|
||||
break
|
||||
elif(y != -1 ):
|
||||
print("Error occured")
|
||||
self.controller.changeScreen("StartPage")
|
||||
self.controller.addInfoText("Fehler beim Buchstabieren aufgetaucht\n")
|
||||
process.terminate()
|
||||
self.controller.stop()
|
||||
break
|
||||
if not self.aktiv:
|
||||
print("stop")
|
||||
break
|
||||
|
||||
|
||||
#self.controller.stop()
|
||||
|
||||
def trainXDawn(self):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
Holt aus der shared Library die Befehle und startet das XDawnTraining. Reagiert auf Error oder
|
||||
die Ausgabe das das Training beendet wurde. Bei Beenden startet es das ClassifierTraining, bei Error wird der Vorgang gestoppt.
|
||||
'''
|
||||
print("Start training Xdawn")
|
||||
self.controller.addInfoText('Starten des xDawn-Trainings -- ')
|
||||
command = self.dll.getCommandXDawn_taktil() #.split(" ")
|
||||
print("Command: " + command)
|
||||
command = command.split(" ")
|
||||
process = Popen(command, stdout=PIPE, universal_newlines=True)
|
||||
|
||||
self.openVibeAktiv = True
|
||||
while self.aktiv:
|
||||
output = process.stdout.readline()
|
||||
print(output.strip())
|
||||
x = output.find("Training finished and saved")
|
||||
y = output.find("Error")
|
||||
if(x != -1):
|
||||
print("Training finished")
|
||||
process.terminate()
|
||||
self.controller.addInfoText('Training beendet\n')
|
||||
self.controller.stop("filterClassic")
|
||||
break
|
||||
elif(y != -1 ):
|
||||
print("Error occured")
|
||||
self.controller.changeScreen("StartPage")
|
||||
self.controller.addInfoText("Fehler beim XDawn Training aufgetaucht\n")
|
||||
self.controller.stop()
|
||||
process.terminate()
|
||||
break
|
||||
if not self.aktiv:
|
||||
print("stop")
|
||||
break
|
||||
|
||||
#self.controller.stop()
|
||||
|
||||
#self.controller.filterClassic()
|
||||
|
||||
|
||||
def trainClassifier(self):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
Holt aus der shared Library die Befehle und startet das ClassifierTraining. Reagiert auf Error oder
|
||||
die Ausgabe das das Training beendet wurde. Bei Beenden startet es das speichern der Daten, bei Error wird der Vorgang gestoppt.
|
||||
'''
|
||||
print("start training Classifier")
|
||||
self.controller.addInfoText("Starten des Classifier-Trainings -- ")
|
||||
|
||||
command = self.dll.getCommandClassifier_taktil().split(" ")
|
||||
process = Popen(command, stdout=PIPE, universal_newlines=True)
|
||||
|
||||
self.openVibeAktiv = True
|
||||
counter = 0
|
||||
acc = 0
|
||||
while True:
|
||||
output = process.stdout.readline()
|
||||
print(output.strip())
|
||||
x = output.find("aka Classifier trainer")
|
||||
accuracy = output.find("Cross-validation test accuracy is ")
|
||||
y = output.find("Error")
|
||||
if(x != -1):
|
||||
counter = counter +1
|
||||
#counter = 18
|
||||
if(counter >= 17):
|
||||
print("Training finished")
|
||||
self.controller.addInfoText('Training beendet (' + acc + ')\n')
|
||||
process.terminate()
|
||||
self.controller.stop("save")
|
||||
break
|
||||
elif(y != -1 ):
|
||||
print("Error occured")
|
||||
self.controller.changeScreen("StartPage")
|
||||
self.controller.addInfoText("Fehler beim Classifier Training aufgetaucht\n")
|
||||
process.terminate()
|
||||
break
|
||||
if(accuracy != -1):
|
||||
#print("Output:")
|
||||
#print(output)
|
||||
ansi_escape = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])')
|
||||
test = output.encode("windows-1252").decode("utf-8")
|
||||
i = len("Cross-validation test")
|
||||
#print(output[accuracy:accuracy+i+12])
|
||||
#print(test[accuracy+i+12:accuracy+i+40].strip())
|
||||
acc_s = test[accuracy+i:accuracy+i+41].strip()
|
||||
acc = ansi_escape.sub('', acc_s)
|
||||
print(acc)
|
||||
|
||||
if not self.aktiv:
|
||||
print("stop")
|
||||
break
|
||||
|
||||
self.controller.changeScreen("StartPage")
|
||||
self.controller.stop()
|
||||
|
||||
def freeSpelling(self):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
Holt aus der shared Library die Befehle und startet das Freespelling. Reagiert auf Error oder
|
||||
beenden. Daraufhin wird der Vorgang gestoppt.
|
||||
'''
|
||||
print("start freeSpelling")
|
||||
self.controller.resetInfo()
|
||||
self.controller.addInfoText('Starten des freien Buchstabierens -- ')
|
||||
command = self.dll.getCommandFreespellingTaktil().split(" ")
|
||||
process = Popen(command, stdout=PIPE, universal_newlines=True)
|
||||
self.openVibeAktiv = True
|
||||
while True:
|
||||
output = process.stdout.readline()
|
||||
print(output.strip())
|
||||
y = output.find("Error")
|
||||
x = output.find("Application terminated")
|
||||
if(x != -1):
|
||||
print("End Spelling")
|
||||
process.terminate()
|
||||
self.controller.addInfoText('Buchstabieren beendet\n')
|
||||
self.controller.changeScreen("StartPage")
|
||||
self.controller.stop()
|
||||
break
|
||||
elif(y != -1 ):
|
||||
print("Error occured")
|
||||
self.controller.changeScreen("StartPage")
|
||||
self.controller.addInfoText("Fehler beim Buchstabieren aufgetaucht\n")
|
||||
process.terminate()
|
||||
self.controller.stop()
|
||||
break
|
||||
if not self.aktiv:
|
||||
print("stop")
|
||||
break
|
||||
|
||||
self.controller.changeScreen("StartPage")
|
||||
self.controller.stop()
|
||||
|
||||
def killProzess(self):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
Ruft den Parent auf, dass Openvibe falls es noch laeuft geschlossen wird
|
||||
'''
|
||||
if(self.openVibeAktiv):
|
||||
self.openVibeAktiv = False
|
||||
self.killProzessParent()
|
||||
|
||||
|
||||
|
||||
@@ -1,230 +0,0 @@
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
Das Visuelle Model steuert den Ablauf der aufrufe der Openvibe Funktionen fuer das visuelle BCI
|
||||
'''
|
||||
|
||||
from subprocess import *
|
||||
from threading import Thread
|
||||
import time
|
||||
import re
|
||||
|
||||
from UIModell import Modell
|
||||
|
||||
class ModellVisuell(Modell):
|
||||
|
||||
def __init__(self,c, dll):
|
||||
Thread.__init__(self)
|
||||
Modell.__init__(self, c, dll)
|
||||
self.aktiv= True
|
||||
self.openVibeAktiv = False
|
||||
|
||||
def stop(self):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
Die Funktion stop stopt den ablaufenden Thread
|
||||
'''
|
||||
print("stop thread")
|
||||
self.aktiv = False
|
||||
|
||||
def setFunktion(self, func, args=None, kwargs=None):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
Mittels dieser Funktion kann die im Thread ablaufende Funktion und deren Argumente eingestellt werden
|
||||
'''
|
||||
self.func = func
|
||||
self.args = args or []
|
||||
self.kwargs = kwargs or {}
|
||||
|
||||
def run(self):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
Wird bei Thread.start() aus dem Controller aufgerufen und laeuft ab sobald der Thread destartet wurde
|
||||
'''
|
||||
print("start thread")
|
||||
#self.aktiv = True
|
||||
t = Thread(target=self.func, args=self.args, kwargs=self.kwargs)
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
|
||||
while self.aktiv:
|
||||
time.sleep(0.1)
|
||||
|
||||
|
||||
def startCopySpelling(self):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
Holt aus der shared Librarz die Befehle und startet das Copyspelling. Reagiert auf Error oder
|
||||
beenden. Bei Beenden startet es das XDawnTraining, bei Error wird der Vorgang gestoppt.
|
||||
Positioniert die visuelle Matrix.
|
||||
'''
|
||||
print("start copySpelling")
|
||||
self.controller.resetInfo()
|
||||
self.controller.addInfoText('Starten des gefuerhten Buchstabierens -- ')
|
||||
command = self.dll.getCommandCopyspellingVisuell().split(" ")
|
||||
process = Popen(command, stdout=PIPE, universal_newlines=True)
|
||||
|
||||
self.openVibeAktiv = True
|
||||
while True:
|
||||
output = process.stdout.readline()
|
||||
print(output.strip())
|
||||
x = output.find("Application terminated")
|
||||
y = output.find("Error")
|
||||
z = output.find("Initialization")
|
||||
if(x != -1):
|
||||
print("Training finished")
|
||||
process.terminate()
|
||||
self.controller.addInfoText('Buchstabieren beendet\n')
|
||||
self.controller.stop("filterXdawn")
|
||||
break
|
||||
elif(y != -1 ):
|
||||
print("Error occured")
|
||||
self.controller.changeScreen("StartPage")
|
||||
self.controller.addInfoText("Fehler beim Buchstabieren aufgetaucht\n")
|
||||
process.terminate()
|
||||
self.controller.stop()
|
||||
break
|
||||
elif(z != -1):
|
||||
print("Initiation finisched")
|
||||
time.sleep(2)
|
||||
self.positionWindow("p300")
|
||||
if not self.aktiv:
|
||||
print("stop")
|
||||
break
|
||||
#self.controller.stop()
|
||||
|
||||
def trainXDawn(self):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
Holt aus der shared Library die Befehle und startet das XDawnTraining. Reagiert auf Error oder
|
||||
die Ausgabe das das Training beendet wurde. Bei Beenden startet es das ClassifierTraining, bei Error wird der Vorgang gestoppt.
|
||||
'''
|
||||
print("start training Xdawn")
|
||||
self.controller.addInfoText('Starten des XDawn/Trainings -- ')
|
||||
command = self.dll.getCommandXDawn_visuell().split(" ")
|
||||
process = Popen(command, stdout=PIPE, universal_newlines=True)
|
||||
|
||||
self.openVibeAktiv = True
|
||||
while self.aktiv:
|
||||
output = process.stdout.readline()
|
||||
print(output.strip())
|
||||
x = output.find("Training finished and saved")
|
||||
y = output.find("Error")
|
||||
if(x != -1):
|
||||
print("Training finished")
|
||||
process.terminate()
|
||||
self.controller.addInfoText('Beenden des Trainings\n')
|
||||
self.controller.stop("filterClassic")
|
||||
break
|
||||
elif(y != -1 ):
|
||||
print("Error occured")
|
||||
self.controller.changeScreen("StartPage")
|
||||
self.controller.addInfoText("Fehler beim XDawn Training aufgetaucht\n")
|
||||
self.controller.stop()
|
||||
process.terminate()
|
||||
break
|
||||
if not self.aktiv:
|
||||
print("stop")
|
||||
break
|
||||
|
||||
#self.controller.stop()
|
||||
|
||||
def trainClassifier(self):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
Holt aus der shared Library die Befehle und startet das ClassifierTraining. Reagiert auf Error oder
|
||||
die Ausgabe das das Training beendet wurde. Bei Beenden startet es das speichern der Daten, bei Error wird der Vorgang gestoppt.
|
||||
'''
|
||||
print("start training Classifier")
|
||||
self.controller.addInfoText("Starten Classifier-Trainings -- ")
|
||||
command = self.dll.getCommandClassifier_visuell().split(" ")
|
||||
process = Popen(command, stdout=PIPE, universal_newlines=True)
|
||||
|
||||
self.openVibeAktiv = True
|
||||
counter = 0
|
||||
acc = 0
|
||||
while True:
|
||||
output = process.stdout.readline()
|
||||
print(output.strip())
|
||||
x = output.find("aka Classifier trainer")
|
||||
accuracy = output.find("Cross-validation test accuracy is ")
|
||||
y = output.find("Error")
|
||||
if(x != -1):
|
||||
counter = counter +1
|
||||
#counter = 18
|
||||
if(counter >= 17):
|
||||
print("Training finished")
|
||||
self.controller.addInfoText('Beenden des Training (' + acc + ')\n')
|
||||
process.terminate()
|
||||
self.controller.stop("save")
|
||||
break
|
||||
elif(y != -1 ):
|
||||
print("Error occured")
|
||||
self.controller.changeScreen("StartPage")
|
||||
self.controller.addInfoText("Fehler beim Classifier Training aufgetaucht\n")
|
||||
process.terminate()
|
||||
break
|
||||
if(accuracy != -1):
|
||||
ansi_escape = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])')
|
||||
test = output.encode("windows-1252").decode("utf-8")
|
||||
i = len("Cross-validation test")
|
||||
acc_s = test[accuracy+i:accuracy+i+41].strip()
|
||||
acc = ansi_escape.sub('', acc_s)
|
||||
print(acc)
|
||||
if not self.aktiv:
|
||||
print("stop")
|
||||
break
|
||||
|
||||
self.controller.changeScreen("StartPage")
|
||||
self.controller.stop()
|
||||
|
||||
def freeSpelling(self):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
Holt aus der shared Library die Befehle und startet das Freespelling. Reagiert auf Error oder
|
||||
beenden. Daraufhin wird der Vorgang gestoppt. Positioniert die visuelle Matrix.
|
||||
'''
|
||||
print("start freeSpelling")
|
||||
self.controller.resetInfo()
|
||||
self.controller.addInfoText('Starten des freien Buchstabierens -- ')
|
||||
|
||||
command = self.dll.getCommandFreespellingVisuell().split(" ")
|
||||
process = Popen(command, stdout=PIPE, universal_newlines=True)
|
||||
|
||||
self.openVibeAktiv = True
|
||||
while True:
|
||||
output = process.stdout.readline()
|
||||
print(output.strip())
|
||||
y = output.find("Error")
|
||||
x = output.find("Schlagwort")
|
||||
z = output.find("Initialization")
|
||||
if(x != -1):
|
||||
print("End Spelling")
|
||||
process.terminate()
|
||||
self.controller.addInfoText('Buchstabieren beendet\n')
|
||||
self.controller.changeScreen("StartPage")
|
||||
self.controller.stop()
|
||||
break
|
||||
elif(y != -1 ):
|
||||
print("Error occured")
|
||||
self.controller.changeScreen("StartPage")
|
||||
self.controller.addInfoText("Fehler beim Buchstabieren aufgetaucht\n")
|
||||
process.terminate()
|
||||
self.controller.stop()
|
||||
break
|
||||
elif(z != -1):
|
||||
print("Initiation finisched")
|
||||
time.sleep(2)
|
||||
self.positionWindow("p300")
|
||||
if not self.aktiv:
|
||||
print("stop")
|
||||
break
|
||||
|
||||
self.controller.changeScreen("StartPage")
|
||||
self.controller.stop()
|
||||
|
||||
def killProzess(self):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
Ruft den Parent auf, dass Openvibe falls es noch laeuft geschlossen wird
|
||||
'''
|
||||
if(self.openVibeAktiv):
|
||||
self.openVibeAktiv = False
|
||||
self.killProzessParent()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,284 +0,0 @@
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
Die View bildet die Oberflaeche ab.
|
||||
Sie ist in 3 Sektoren Top, Main und ButtonFrame unterteilt. Der TopFrame beihnahltet die Taskleiste,
|
||||
der Button Frame gibt Informationen raus. Im Main Frame sind die Buttons yu starten und stoppen der
|
||||
Buchstabierungen. HIerfuer sind extra Seiten erstellt, die beliebig, je nach Situation ausgetauscht
|
||||
werden koennen
|
||||
'''
|
||||
|
||||
try:
|
||||
from Tkinter import * #Fuer Python 2.7
|
||||
import tkFileDialog as fd
|
||||
print("python2.7")
|
||||
except ImportError: #Fuer Python >3
|
||||
from tkinter import *
|
||||
from tkinter import filedialog as fd
|
||||
print("python >3")
|
||||
|
||||
from UIController import *
|
||||
|
||||
|
||||
|
||||
class View(Tk):
|
||||
def __init__(self, c, path_default, *args, **kwargs):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
In der Init wird das Lazout gesetyt und die Funktionen yur erstellung der Frames aufgerufen,
|
||||
zudem wird dem schliesen des Fensters sowie den anpassen der Groesse andere Funktionen hinterlegt
|
||||
'''
|
||||
Tk.__init__(self, *args, **kwargs)
|
||||
img = PhotoImage(file='icon.png')
|
||||
self.tk.call('wm', 'iconphoto', self._w, img)
|
||||
self.controller = c
|
||||
self.PATH_DEFAULT = path_default
|
||||
self.title("Visuelles Buchstabieren")
|
||||
self.h = self.winfo_screenheight()
|
||||
self.w = self.winfo_screenwidth()
|
||||
self.geometry('{}x{}'.format(self.w,self.h))
|
||||
self.faktor = [(0.073),(0.727), (0.2)]
|
||||
#self.resizable(height=False, width= False)
|
||||
self.layout = {
|
||||
"background": "#00001E",
|
||||
"backgroundBtn": "#1C86EE",
|
||||
"fontColor": "#FFFFFF",
|
||||
"backgroundBar": "#00002E",
|
||||
"font": ('Calibri', 20, 'bold'),
|
||||
"fontSmall": ('Calibri', 14, 'bold'),
|
||||
"fontInfo": ('Calibri', 25)
|
||||
}
|
||||
|
||||
self.createTopFrame()
|
||||
self.createMainFrame()
|
||||
self.createBottomFrame()
|
||||
|
||||
self.bind("<Configure>", self.adjustSize)
|
||||
self.protocol("WM_DELETE_WINDOW", self.onClosing)
|
||||
|
||||
|
||||
def changeFrame(self, pageName):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
Setzt dem Frame passend zum pageName in den Vordergrund
|
||||
'''
|
||||
frame = self.frames[pageName]
|
||||
frame.tkraise()
|
||||
|
||||
def adjustSize(self, event):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
passt nach Faktoren die einyelnen Seitenteile der jeweiligen Frame Groesse an
|
||||
'''
|
||||
if(str(event.widget) =="."):
|
||||
self.h = event.height
|
||||
self.w = event.width
|
||||
self.topFrame.configure(height=(self.h*self.faktor[0]), width=self.w)
|
||||
self.mainFrame.configure(height=(self.h*self.faktor[1]), width=self.w)
|
||||
self.bottomFrame.configure(height=(self.h*self.faktor[2]), width=self.w)
|
||||
self.container.configure(height=(self.h*self.faktor[1]), width=self.w)
|
||||
for f in self.frames:
|
||||
self.frames[f].configure(height=(self.h*self.faktor[1]), width=self.w)
|
||||
self.frames[f].adjustSize(height=(self.h*self.faktor[1]), width=self.w)
|
||||
|
||||
|
||||
def onClosing(self):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
Stoppt alle laufenden Threads und schliesst OpenVibe und den Aquisitionserver bevor sich das Fenster
|
||||
schliesst
|
||||
'''
|
||||
try:
|
||||
print("closing")
|
||||
self.controller.commandStop()
|
||||
self.controller.stopAcquisitionServer()
|
||||
print("destroy")
|
||||
self.dialog.destroy()
|
||||
except:
|
||||
pass
|
||||
self.destroy()
|
||||
|
||||
|
||||
def createTopFrame(self):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
Erstellt die Buttons und Textfelder fuer die Taskleiste und positionier diese im Frame
|
||||
'''
|
||||
self.topFrame = Frame(self, bg=self.layout["backgroundBar"], height=50, width=500)
|
||||
self.changeBtn = Button(self.topFrame, text="Wechsel zu taktilen BCI", command=lambda: self.controller.actionPerformed("wechsel"), height=3, width = 30, font=self.layout["fontSmall"], bg=self.layout["backgroundBtn"], fg=self.layout["fontColor"])
|
||||
self.saveBtn = Button(self.topFrame, text="Auswaehlen der Datei", command=lambda: self.controller.actionPerformed("speicherort"), height=3, width = 30, font=self.layout["fontSmall"], bg=self.layout["backgroundBtn"], fg=self.layout["fontColor"])
|
||||
#self.setBtn = Button(self.topFrame, text="Auswaehlen der Datei", command=lambda: self.controller.actionPerformed("setFile"), height=2, width = 25, font=self.layout["fontSmall"], bg=self.layout["backgroundBtn"], fg=self.layout["fontColor"])
|
||||
self.toplabel = Label(self.topFrame, text="visuelles BCI", font=self.layout["font"], bg=self.layout["backgroundBar"], fg=self.layout["fontColor"], )
|
||||
|
||||
self.topFrame.grid(column=0, row=0)
|
||||
self.topFrame.grid_propagate(0)
|
||||
self.topFrame.pack_propagate(0)
|
||||
|
||||
self.changeBtn.grid(column=0, row=0, padx=10,pady=5)
|
||||
self.saveBtn.grid(column=1, row=0, padx=10, pady=5)
|
||||
#self.setBtn.grid(column=2, row=0, padx=10, pady=5)
|
||||
self.toplabel.grid(column=2, row=0, padx=100, pady=2)
|
||||
|
||||
def createMainFrame(self):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
Erstellt und postioniert einen Container als Platzhalter fuer die verschiedenen Seiten. Anscliessend
|
||||
erstellt es die verschiedenen Seiten und speicher diese in eine Liste
|
||||
'''
|
||||
self.mainFrame = Frame(self, bg=self.layout["background"], height=250, width=500)
|
||||
self.mainFrame.grid(column=0, row=1)
|
||||
self.mainFrame.pack_propagate(0)
|
||||
|
||||
self.container = Frame(self.mainFrame, bg=self.layout["background"], height=250, width=500)
|
||||
self.container.pack(side="top", fill="both", expand = True)
|
||||
self.container.pack_propagate(0)
|
||||
self.container.grid_propagate(0)
|
||||
|
||||
self.frames = {}
|
||||
for F in (StartPage, WorkingPageTaktil, WorkingPageVisuell):
|
||||
page_name = F.__name__
|
||||
frame = F(parent=self.container, controller=self.controller, layout=self.layout)
|
||||
self.frames[page_name] = frame
|
||||
frame.grid(row=0, column=0, sticky="nsew")
|
||||
|
||||
self.changeFrame("StartPage")
|
||||
|
||||
def createBottomFrame(self):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
Erstellt und positioniert ein Label fuer die ganzen Informationen
|
||||
'''
|
||||
self.bottomFrame = Frame(self, bg=self.layout["backgroundBar"], height=100, width=500)
|
||||
self.bottomlabel = Label(self.bottomFrame, text="Hier stehen Infos\nGanz viele", justify='left', font=self.layout["fontInfo"], bg=self.layout["backgroundBar"], fg=self.layout["fontColor"])
|
||||
|
||||
self.bottomFrame.grid(column=0, row=2)
|
||||
self.bottomFrame.pack_propagate(0)
|
||||
self.bottomFrame.grid_propagate(0)
|
||||
|
||||
self.bottomlabel.grid(padx=5,pady=5)
|
||||
|
||||
def setInfoText(self, text):
|
||||
self.bottomlabel['text'] = text
|
||||
|
||||
def setTitleText(self,text):
|
||||
self.title(text)
|
||||
self.toplabel["text"] = text
|
||||
|
||||
def setChangeBtnText(self,text):
|
||||
self.changeBtn["text"] = text
|
||||
|
||||
def setDefaultPath(self, path):
|
||||
self.PATH_DEFAULT = path
|
||||
|
||||
def openfiledialog(self):
|
||||
path = self.PATH_DEFAULT
|
||||
#file = fd.askopenfilename(initialdir=path)
|
||||
file = fd.askdirectory(initialdir=path)
|
||||
return file
|
||||
|
||||
def savefiledialog(self):
|
||||
self.dialog = Tk()
|
||||
|
||||
self.dialog.title("Visuelles Buchstabieren")
|
||||
h = 100
|
||||
w = 400
|
||||
self.dialog.geometry('{}x{}'.format(w,h))
|
||||
self.dialog.geometry("+{}+{}".format(100,200))
|
||||
l = Label(self.dialog, text="Bitte geben Sie einen Speichernamen ein:")
|
||||
eingabefeld = Entry(self.dialog)
|
||||
okBtn = Button(self.dialog, text="OK", command=lambda:self.okBtn(eingabefeld.get()))
|
||||
l.pack()
|
||||
eingabefeld.pack()
|
||||
okBtn.pack()
|
||||
|
||||
self.dialog.protocol("WM_DELETE_WINDOW", self.closeDialog)
|
||||
self.dialog.mainloop()
|
||||
|
||||
def okBtn(self, text):
|
||||
path = self.PATH_DEFAULT + "/" + text
|
||||
print(path)
|
||||
self.controller.copyspelling(path)
|
||||
self.dialog.destroy()
|
||||
|
||||
def closeDialog(self):
|
||||
self.controller.copyspelling("-1")
|
||||
self.dialog.destroy()
|
||||
|
||||
def getWindowSize(self):
|
||||
return [self.winfo_x(), self.winfo_y(), self.winfo_height(), self.winfo_width()]
|
||||
|
||||
|
||||
class StartPage(Frame):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
Bildet die Seite in der die Aktionen ausgesucht werden koennen. Beihaltet 2 Buttons einen zum starten
|
||||
des freien Buchstabierens und einen yum starten des gefuerten Buchstabierens
|
||||
'''
|
||||
def __init__(self, parent, controller, layout):
|
||||
self.layout = layout
|
||||
|
||||
Frame.__init__(self, parent, height=250, width=500, bg=self.layout["background"])
|
||||
self.grid_propagate(0)
|
||||
self.pack_propagate(0)
|
||||
self.controller = controller
|
||||
|
||||
self.container = Frame(self, bg=self.layout["background"], height=250, width=500)
|
||||
self.btnFrame = Frame(self.container, bg=self.layout["background"], height=250, width=250)
|
||||
|
||||
self.container.columnconfigure(0, weight=1) # Set weight to row and
|
||||
self.container.rowconfigure(0, weight=1) # column where the widget is
|
||||
self.container.grid_propagate(0)
|
||||
self.container.pack_propagate(0)
|
||||
|
||||
self.container.pack()
|
||||
self.btnFrame.grid()
|
||||
|
||||
testBtn = Button(self.btnFrame, text="gefuehrtes Buchstabieren", command=lambda: self.controller.actionPerformed("copySpelling"), height=6, width = 20, font=self.layout["font"], bg=self.layout["backgroundBtn"], fg=self.layout["fontColor"])
|
||||
#testBtn = Button(self.btnFrame, text="copySpelling", command=lambda: self.controller.actionPerformed("test"), height=6, width = 20, font=self.layout["font"], bg=self.layout["backgroundBtn"], fg=self.layout["fontColor"])
|
||||
testBtn.grid(row=0,column=0, padx=25,pady=25)
|
||||
|
||||
freeSpellingBtn = Button(self.btnFrame, text="freies Buchstabieren", command=lambda: self.controller.actionPerformed("freeSpelling"), height=6, width = 20, font=self.layout["font"], bg=self.layout["backgroundBtn"], fg=self.layout["fontColor"])
|
||||
freeSpellingBtn.grid(row=0, column=1, padx=25,pady=25)
|
||||
|
||||
def adjustSize(self, height, width):
|
||||
self.container.configure(height=height, width= width)
|
||||
self.btnFrame.configure(height=(height*4)/5, width= width/2)
|
||||
|
||||
class WorkingPageTaktil(Frame):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
Bildet die Seite nach Auswahl einer Aktion. Beihaltet einen mittig plazierten Buttons zum stoppen
|
||||
des ablaufenden Vorgang
|
||||
'''
|
||||
def __init__(self, parent, controller, layout):
|
||||
self.layout = layout
|
||||
|
||||
Frame.__init__(self, parent, height=250, width=500, bg=self.layout["background"])
|
||||
self.controller = controller
|
||||
|
||||
|
||||
self.columnconfigure(0, weight=1) # Set weight to row and
|
||||
self.rowconfigure(0, weight=1) # column where the widget is
|
||||
|
||||
stopBtn = Button(self, text="stop", command=lambda: self.controller.actionPerformed("stop"), height=4, width = 15, font=self.layout["font"], bg=self.layout["backgroundBtn"], fg=self.layout["fontColor"])
|
||||
stopBtn.grid()
|
||||
|
||||
def adjustSize(self, height, width):
|
||||
pass
|
||||
|
||||
class WorkingPageVisuell(Frame):
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
Bildet die Seite nach Auswahl einer Aktion. Beihaltet einen mittig unten plazierten Buttons zum
|
||||
stoppen des ablaufenden Vorgang
|
||||
'''
|
||||
def __init__(self, parent, controller, layout):
|
||||
self.layout = layout
|
||||
|
||||
Frame.__init__(self, parent, height=250, width=500, bg=self.layout["background"])
|
||||
self.controller = controller
|
||||
self.grid_propagate(0)
|
||||
self.pack_propagate(0)
|
||||
|
||||
self.windowFrame = Frame(self, height=200, width=500, bg=self.layout["background"])
|
||||
self.windowFrame.grid(column=0, row=0)
|
||||
|
||||
self.buttonFrame = Frame(self, height=50, width=500, bg=self.layout["background"])
|
||||
self.buttonFrame.grid(column=0, row=1)
|
||||
self.buttonFrame.columnconfigure(0, weight=1) # Set weight to row and
|
||||
self.buttonFrame.rowconfigure(0, weight=1) # column where the widget is
|
||||
|
||||
stopBtn = Button(self.buttonFrame, text="stop", command=lambda: self.controller.actionPerformed("stop"), height=1, width = 15, font=self.layout["font"], bg=self.layout["backgroundBtn"], fg=self.layout["fontColor"])
|
||||
stopBtn.grid()
|
||||
|
||||
def adjustSize(self, height, width):
|
||||
self.windowFrame.configure(height=(height*9)/10, width= width)
|
||||
self.buttonFrame.configure(height=(height)/10, width= width)
|
||||
-227
@@ -1,227 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
using namespace std;
|
||||
|
||||
extern "C"{
|
||||
|
||||
//allgemein
|
||||
//-------------------------------------------------------------------------------------------------------------------------------------
|
||||
string PATH_OV = "meta/dist/Release/openvibe-designer.sh";
|
||||
string PATH_AquisitionServer = "meta/dist/Release/openvibe-acquisition-server.sh";
|
||||
|
||||
|
||||
|
||||
//visuell
|
||||
//-------------------------------------------------------------------------------------------------------------------------------------
|
||||
string PATH_FILES_Visual = "Projekte/OpenVibe_THN-p300-bci-main/p300-visual/";
|
||||
string pathOVFile_visuell = "Projekte/OpenVibe_THN-p300-bci-main/p300-visual/signals/p300-xdawn-train.ov";
|
||||
string pathClassifierCFG_visuell = "Projekte/OpenVibe_THN-p300-bci-main/p300-visual/cfg/p300-classifier.cfg";
|
||||
string pathSpatialCFG_visuell = "Projekte/OpenVibe_THN-p300-bci-main/p300-visual/cfg/p300-spatial-filter.cfg";
|
||||
string PATH_DEFAULT_visuell = "Projekte/OpenVibe_THN-p300-bci-main/p300-visual/datasets";
|
||||
|
||||
string fileCopySpellingVisuell = "p300-xdawn-1-acquisition.xml";
|
||||
string filefreeSpellingVisuell = "p300-xdawn-4-online.xml";
|
||||
string fileXDawnTrainingVisuell = "p300-xdawn-2-train-xDAWN.xml";
|
||||
string fileClassifierTrainingVisuell = "p300-xdawn-3-train-classifier.xml";
|
||||
|
||||
//taktil
|
||||
//------------------------------------------------------------------------------------------------------------------------------------
|
||||
string fileCopySpellingTaktil = "p300-tactile-1-acquisition.xml";
|
||||
string filefreeSpellingTaktil = "p300-tactile-4-online.xml";
|
||||
string fileXDawnTrainingTaktil = "p300-tactile-2-train-xDAWN.xml";
|
||||
string fileClassifierTrainingTaktil = "p300-tactile-3-train-classifier.xml";
|
||||
|
||||
string PATH_FILES_taktil = "Projekte/OpenVibe_THN-p300-bci-main/p300-tactile/";
|
||||
string pathOVFile_taktil = "Projekte/OpenVibe_THN-p300-bci-main/p300-tactile/signals/p300-xdawn-train.ov";
|
||||
string pathClassifierCFG_taktil = "Projekte/OpenVibe_THN-p300-bci-main/p300-tactile/cfg/p300-classifier.cfg";
|
||||
string pathSpatialCFG_taktil = "Projekte/OpenVibe_THN-p300-bci-main/p300-tactile/cfg/p300-spatial-filter.cfg";
|
||||
string PATH_DEFAULT_taktil = "Projekte/OpenVibe_THN-p300-bci-main/p300-tactile/datasets";
|
||||
|
||||
string PATH_FILES_ConfigFile = "Projekte/OpenVibe_THN-p300-bci-main/cfg/OV_TACTILE_PANDA.conf";
|
||||
|
||||
//Befehle
|
||||
//-------------------------------------------------------------------------------------------------------------------------------------
|
||||
string command = "bash";
|
||||
string nogui = "--no-gui";
|
||||
string play = "--play";
|
||||
string playFast = "--play-fast";
|
||||
string config = "--config";
|
||||
|
||||
|
||||
char* getCommandPS(){
|
||||
string s = "";
|
||||
s = s.append("ps").append(" ").append("-e");
|
||||
char char_array[s.length()+1];
|
||||
strcpy(char_array, s.c_str());
|
||||
char* s_convert = char_array;
|
||||
return s_convert;
|
||||
}
|
||||
|
||||
char* getCommandFreespellingTaktil()
|
||||
{
|
||||
string s = "";
|
||||
s = s.append(command).append(" ").append(PATH_OV).append(" ").append(config).append(" ").append(PATH_FILES_ConfigFile).append(" ").append( play).append(" ").append(PATH_FILES_taktil).append(filefreeSpellingTaktil).append(" ").append(nogui);
|
||||
char char_array[s.length()+1];
|
||||
strcpy(char_array, s.c_str());
|
||||
char* s_convert = char_array;
|
||||
return s_convert;
|
||||
}
|
||||
|
||||
char* getCommandFreespellingVisuell()
|
||||
{
|
||||
string s = "";
|
||||
s = s.append(command).append(" ").append(PATH_OV).append(" ").append( play).append(" ").append(PATH_FILES_Visual).append(filefreeSpellingVisuell).append(" ").append(nogui);
|
||||
char char_array[s.length()+1];
|
||||
strcpy(char_array, s.c_str());
|
||||
char* s_convert = char_array;
|
||||
return s_convert;
|
||||
}
|
||||
|
||||
char* getCommandCopyspellingTaktil()
|
||||
{
|
||||
string s = "";
|
||||
s = s.append(command).append(" ").append(PATH_OV).append(" ").append(config).append(" ").append(PATH_FILES_ConfigFile).append(" ").append( play).append(" ").append(PATH_FILES_taktil).append(fileCopySpellingTaktil).append(" ").append(nogui);
|
||||
char char_array[s.length()+1];
|
||||
strcpy(char_array, s.c_str());
|
||||
char* s_convert = char_array;
|
||||
return s_convert;
|
||||
}
|
||||
|
||||
char* getCommandCopyspellingVisuell()
|
||||
{
|
||||
string s = "";
|
||||
s = s.append(command).append(" ").append(PATH_OV).append(" ").append( play).append(" ").append(PATH_FILES_Visual).append(fileCopySpellingVisuell).append(" ").append(nogui);
|
||||
char char_array[s.length()+1];
|
||||
strcpy(char_array, s.c_str());
|
||||
char* s_convert = char_array;
|
||||
return s_convert;
|
||||
}
|
||||
|
||||
char* getCommandXDawn_taktil()
|
||||
{
|
||||
string s = "";
|
||||
s = s.append(command).append(" ").append(PATH_OV).append(" ").append(config).append(" ").append(PATH_FILES_ConfigFile).append(" ").append( playFast).append(" ").append(PATH_FILES_taktil).append(fileXDawnTrainingTaktil).append(" ").append(nogui);
|
||||
char char_array[s.length()+1];
|
||||
strcpy(char_array, s.c_str());
|
||||
char* s_convert = char_array;
|
||||
return s_convert;
|
||||
}
|
||||
|
||||
char* getCommandXDawn_visuell()
|
||||
{
|
||||
string s = "";
|
||||
s = s.append(command).append(" ").append(PATH_OV).append(" ").append( playFast).append(" ").append(PATH_FILES_Visual).append(fileXDawnTrainingVisuell).append(" ").append(nogui);
|
||||
char char_array[s.length()+1];
|
||||
strcpy(char_array, s.c_str());
|
||||
char* s_convert = char_array;
|
||||
return s_convert;
|
||||
}
|
||||
|
||||
char* getCommandClassifier_visuell()
|
||||
{
|
||||
string s = "";
|
||||
s = s.append(command).append(" ").append(PATH_OV).append(" ").append( playFast).append(" ").append(PATH_FILES_Visual).append(fileClassifierTrainingVisuell).append(" ").append(nogui);
|
||||
char char_array[s.length()+1];
|
||||
strcpy(char_array, s.c_str());
|
||||
char* s_convert = char_array;
|
||||
return s_convert;
|
||||
}
|
||||
|
||||
char* getCommandClassifier_taktil()
|
||||
{
|
||||
string s = "";
|
||||
s = s.append(command).append(" ").append(PATH_OV).append(" ").append(config).append(" ").append(PATH_FILES_ConfigFile).append(" ").append( playFast).append(" ").append(PATH_FILES_taktil).append(fileClassifierTrainingTaktil).append(" ").append(nogui);
|
||||
char char_array[s.length()+1];
|
||||
strcpy(char_array, s.c_str());
|
||||
char* s_convert = char_array;
|
||||
return s_convert;
|
||||
}
|
||||
|
||||
|
||||
char* getCommandStartAquisitionServer()
|
||||
{
|
||||
string s = "";
|
||||
s = s.append(command).append(" ").append(PATH_AquisitionServer);
|
||||
char char_array[s.length()+1];
|
||||
strcpy(char_array, s.c_str());
|
||||
char* s_convert = char_array;
|
||||
return s_convert;
|
||||
}
|
||||
|
||||
char* getDefaultPath_visuell()
|
||||
{
|
||||
string s = PATH_DEFAULT_visuell;
|
||||
char char_array[s.length()+1];
|
||||
strcpy(char_array, s.c_str());
|
||||
char* s_convert = char_array;
|
||||
return s_convert;
|
||||
}
|
||||
|
||||
char* getDefaultPath_taktil()
|
||||
{
|
||||
string s = PATH_DEFAULT_taktil;
|
||||
char char_array[s.length()+1];
|
||||
strcpy(char_array, s.c_str());
|
||||
char* s_convert = char_array;
|
||||
return s_convert;
|
||||
}
|
||||
|
||||
char* getPathOVFile_visuell()
|
||||
{
|
||||
string s = pathOVFile_visuell;
|
||||
char char_array[s.length()+1];
|
||||
strcpy(char_array, s.c_str());
|
||||
char* s_convert = char_array;
|
||||
return s_convert;
|
||||
}
|
||||
|
||||
char* getSpatialCFGFile_visuell()
|
||||
{
|
||||
string s = pathSpatialCFG_visuell;
|
||||
char char_array[s.length()+1];
|
||||
strcpy(char_array, s.c_str());
|
||||
char* s_convert = char_array;
|
||||
return s_convert;
|
||||
}
|
||||
|
||||
char* getClassifierCFGFile_visuell()
|
||||
{
|
||||
string s = pathClassifierCFG_visuell;
|
||||
char char_array[s.length()+1];
|
||||
strcpy(char_array, s.c_str());
|
||||
char* s_convert = char_array;
|
||||
return s_convert;
|
||||
}
|
||||
|
||||
char* getPathOVFile_taktil()
|
||||
{
|
||||
string s = pathOVFile_taktil;
|
||||
char char_array[s.length()+1];
|
||||
strcpy(char_array, s.c_str());
|
||||
char* s_convert = char_array;
|
||||
return s_convert;
|
||||
}
|
||||
|
||||
char* getSpatialCFGFile_taktil()
|
||||
{
|
||||
string s = pathSpatialCFG_taktil;
|
||||
char char_array[s.length()+1];
|
||||
strcpy(char_array, s.c_str());
|
||||
char* s_convert = char_array;
|
||||
return s_convert;
|
||||
}
|
||||
|
||||
char* getClassifierCFGFile_taktil()
|
||||
{
|
||||
string s = pathClassifierCFG_taktil;
|
||||
char char_array[s.length()+1];
|
||||
strcpy(char_array, s.c_str());
|
||||
char* s_convert = char_array;
|
||||
return s_convert;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
'''--------------------------------------------------------------------------------------------------
|
||||
In dem File wird eine Instany des Controllers erstellt. Der Controller ist die Schnittstelle
|
||||
zwischen GUI und Modell und koordiniert den Ablauf und die Erstellung der GUI
|
||||
'''
|
||||
|
||||
from UIController import *
|
||||
|
||||
controller = Controller()
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 84 KiB |
@@ -1,5 +0,0 @@
|
||||
# OpenVibe_THN-p300-bci
|
||||
|
||||
Die Szenarien für das Taktile und das Visuelle BCI, basieren auf dem OpenVibeSzenrio p300-speller-xDAWN.
|
||||
|
||||
In die jeweiligen Ordner können die aktuellen OpenVibe-Dateien für das taktile und visuelle Buchstabieren eingefügt werden. Die Dateien können im EFI-Git gefunden werden.
|
||||
@@ -1,36 +1,24 @@
|
||||
<h1>Grafische Oberfläche:</h1>
|
||||
|
||||
Die grafische Oberfläche wurde in Python geschrieben. Die Pfade von den OpenVibe Programmen sind in einer Shared Library hinterlegt (dll.so, bzw. ddl.cpp). Alle Python Dateien wurden in der Datei "gui" in eine ausführbare Datei zusammengefasst. Die Oberfläche kann durch ausführen dieser gestartet werden. Hierfür werden die Dateien "gui", "dll.so" und "icon.png" benötigt. Diese in den Ordner über meta kopieren.
|
||||
|
||||
Falls zusätzlich eine Desktop Applikation erstellt worden ist, wird noch die "BCI.desktop" und die "start.sh" Datei benötigt. Mittels der "BCI.desktop" Datei kann die Applikation installiert werden. Anschließend wird mit klick auf das Icon die "start.sh" Datei ausgeführt. Diese startet die "gui" und schreibt die logs in eine Textdatei.
|
||||
|
||||
<h2>Nutzungsanleitung</h2>
|
||||
|
||||
* Installation von xdotool und python-tkinter, falls noch nicht installiert (siehe script.sh)
|
||||
|
||||
* Einfügen der taktilen und visuellen OpenVibe Programme
|
||||
|
||||
* Anpassen der Defaultpfade in der dll.cpp Datei (Default-Ordnerstruktur ist im Ordnerstruktur.PNG hinterlegt)
|
||||
-> erstellen einer shared library mit g++ dll.cpp --shared -fPIC -o dll.so
|
||||
|
||||
* Fuer den Ablauf werden dann nur die Datei gui, dll.so und das icon (icon.png) benoetigt. Alle Dateien bitte im selben Ordner verschieben (Default im gleichen Ordner wie der Ordner meta).
|
||||
|
||||
* Das Programm kann nun mit den Kommandozeilenaufruf ./gui gestartet werden. (Hier darauf achten das die notwendigen Rechte vergeben wurden)
|
||||
|
||||
<h2>Zusätzlich für Desktop Applikation </h2>
|
||||
Fuer den Aufruf ueber ein Desktop Icon werden die Dateien BCI.desktop und start.sh benoetigt:
|
||||
|
||||
* Ggf. die Pfade zur start.sh datei und zum Icon in der "BCI.desktop" - Datei angepassen
|
||||
|
||||
* Pfade in der start.sh Datei anpassen
|
||||
|
||||
* BCI.desktop in den home folder legen und installiert werden
|
||||
(sudo desktop-file-install BCI.desktop)
|
||||
|
||||
* start.sh wird mit dem Icon aufgerufen
|
||||
|
||||
<h2>Bei Änderungen der Python Dateien </h2>
|
||||
|
||||
Wurde die Python Dateien verändert muss die "gui" Datei neu erstellt werden. Dies kann im Code Ordner mittels pyinstaller –onefile gui.py durchgeführt werden.
|
||||
# TactileBCI
|
||||
|
||||
|
||||
Enthält alle für das Taktile BCI der THN benötigten Box-Codes und Designer-Szenarien, sowie eine Anleitung zu deren Verwendung (s. TactileBCI/scenarios/manuals/).
|
||||
|
||||
Bei diesem taktilen BCI der THN, haben wir ein Hauptmenü mit 6 Elementen wovon 4 in untermenüs führen und die anderen 2 die antwortmöglichkeiten ja/nein darstellen.
|
||||
|
||||
Dabei wird jeder Menüpunkt von einem kleinen Vibrationsmotor ("Tactilo") repräsentiert.
|
||||
|
||||
Die Tactilos werden, über eine festgelegte Anzahl von Wiederholungen und Trials, in zufälliger Reihenfolge angesteuert um so sensorisch ein P300-Signal zu erzeugen.
|
||||
|
||||
Mit dieser vorgehensweise soll es möglich gemacht werden durch die Menüs der UI zu navigieren.
|
||||
|
||||
---------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
Verwendung:
|
||||
|
||||
**WICHTIG:** Das Plugin ist fuer die Verwendung mit OpenViBE 3.3 gemacht
|
||||
|
||||
1) git clone -b Taktiles-BCI https://git.efi.th-nuernberg.de/gitea/gieslerth/Brain_Computer_Interface.git
|
||||
|
||||
2) das erstellte verzeichniss "TactileBCI" nach /meta/extras/plugins/processing/ kopieren
|
||||
|
||||
3) Danach OpenViBE kompilieren
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
# TactiloControllerPanda
|
||||
Dieses Programm empfaengt Daten von der Korrespondierenden OpenViBE Box ueber eine serielle Schnittstelle. <br />
|
||||
Auf Basis der erhaltenen Daten, werden die bis zu zehn Tactilos des Taktilen Brain Computer Interface angesteuert. Das Timing wird dabei komplett von OpenViBE uebernommen.
|
||||
@@ -0,0 +1,144 @@
|
||||
|
||||
///-------------------------------------------------------------------------------------------------
|
||||
///
|
||||
/// \file TactiloControllerPanda.ino
|
||||
/// \brief Controlls the Tactilos on the Leonardos GPIOs, based on the messages from OpenVibes TactiloController Box Algorithm
|
||||
/// Hochladen mit der Arduino IDE
|
||||
/// \author Tobias Baumann (TH-Nürnberg).
|
||||
/// \version 1.0.
|
||||
/// \date Mon Mar 7 14:02:56 2022.
|
||||
///
|
||||
///-------------------------------------------------------------------------------------------------
|
||||
|
||||
//define used GPIO pins
|
||||
#define TAC1 13 //PWM
|
||||
#define TAC2 11 //PWM
|
||||
#define TAC3 10 //PWM
|
||||
#define TAC4 9 //PWM
|
||||
#define TAC5 6 //PWM
|
||||
#define TAC6 5 //PWM
|
||||
//reserve
|
||||
#define TAC7 3 //PWM
|
||||
#define TAC8 2
|
||||
#define TAC9 1
|
||||
#define TAC10 0
|
||||
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
//init serial
|
||||
Serial.begin(115200);
|
||||
|
||||
//init GPIOs
|
||||
Serial.println("...init GPIOs");
|
||||
set_PinMode();
|
||||
set_AllLow();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
char SerialData;
|
||||
|
||||
if(Serial.available() > 0)
|
||||
{
|
||||
SerialData = Serial.read();
|
||||
processSerialData(SerialData);
|
||||
}
|
||||
}
|
||||
|
||||
void set_PinMode()
|
||||
{
|
||||
//set all pins to OUTPUT
|
||||
pinMode(TAC1, OUTPUT);
|
||||
pinMode(TAC2, OUTPUT);
|
||||
pinMode(TAC3, OUTPUT);
|
||||
pinMode(TAC4, OUTPUT);
|
||||
pinMode(TAC5, OUTPUT);
|
||||
pinMode(TAC6, OUTPUT);
|
||||
pinMode(TAC7, OUTPUT);
|
||||
pinMode(TAC8, OUTPUT);
|
||||
pinMode(TAC9, OUTPUT);
|
||||
pinMode(TAC10, OUTPUT);
|
||||
}
|
||||
|
||||
void set_AllLow()
|
||||
{
|
||||
//set all pins to LOW
|
||||
digitalWrite(TAC1, LOW);
|
||||
digitalWrite(TAC2, LOW);
|
||||
digitalWrite(TAC3, LOW);
|
||||
digitalWrite(TAC4, LOW);
|
||||
digitalWrite(TAC5, LOW);
|
||||
digitalWrite(TAC6, LOW);
|
||||
digitalWrite(TAC7, LOW);
|
||||
digitalWrite(TAC8, LOW);
|
||||
digitalWrite(TAC9, LOW);
|
||||
digitalWrite(TAC10, LOW);
|
||||
}
|
||||
|
||||
void processSerialData(char SerialData)
|
||||
{
|
||||
switch(SerialData)
|
||||
{
|
||||
case '0':
|
||||
digitalWrite(TAC1, !digitalRead(TAC1));
|
||||
//Serial.print("Tactilo 1: ");
|
||||
//Serial.println(digitalRead(TAC1));
|
||||
break;
|
||||
case '1':
|
||||
digitalWrite(TAC2, !digitalRead(TAC2));
|
||||
//Serial.print("Tactilo 2: ");
|
||||
//Serial.println(digitalRead(TAC2));
|
||||
break;
|
||||
case '2':
|
||||
digitalWrite(TAC3, !digitalRead(TAC3));
|
||||
//Serial.print("Tactilo 3: ");
|
||||
//Serial.println(digitalRead(TAC3));
|
||||
break;
|
||||
case '3':
|
||||
digitalWrite(TAC4, !digitalRead(TAC4));
|
||||
//Serial.print("Tactilo 4: ");
|
||||
//Serial.println(digitalRead(TAC4));
|
||||
break;
|
||||
case '4':
|
||||
digitalWrite(TAC5, !digitalRead(TAC5));
|
||||
//Serial.print("Tactilo 5: ");
|
||||
//Serial.println(digitalRead(TAC5));
|
||||
break;
|
||||
case '5':
|
||||
digitalWrite(TAC6, !digitalRead(TAC6));
|
||||
//Serial.print("Tactilo 6: ");
|
||||
//Serial.println(digitalRead(TAC6));
|
||||
break;
|
||||
case '6':
|
||||
digitalWrite(TAC7, !digitalRead(TAC7));
|
||||
//Serial.print("Tactilo 7: ");
|
||||
//Serial.println(digitalRead(TAC7));
|
||||
break;
|
||||
case '7':
|
||||
digitalWrite(TAC8, !digitalRead(TAC8));
|
||||
//Serial.print("Tactilo 8: ");
|
||||
//Serial.println(digitalRead(TAC8));
|
||||
break;
|
||||
case '8':
|
||||
digitalWrite(TAC9, !digitalRead(TAC9));
|
||||
//Serial.print("Tactilo 9: ");
|
||||
//Serial.println(digitalRead(TAC9));
|
||||
break;
|
||||
case '9':
|
||||
digitalWrite(TAC10, !digitalRead(TAC10));
|
||||
//Serial.print("Tactilo 10: ");
|
||||
//Serial.println(digitalRead(TAC10));
|
||||
break;
|
||||
case 'b':
|
||||
Serial.println("...Begin Tactile Session");
|
||||
break;
|
||||
case 'e':
|
||||
set_AllLow();
|
||||
Serial.println("...End Tactile Session");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
########################################################################################################################
|
||||
# This configuration file contains declarations of variables used by the scenarios of the tactile BCI System #
|
||||
# #
|
||||
# Add --config PATH_TO_THIS_FILE when starting the designer from the command line #
|
||||
# USE --define TOKEN VALUE to assign a different value to a token without changing the default configuration #
|
||||
# #
|
||||
# #
|
||||
# Scenarios requiring this configuration file: p300-tactile-0-signal-monitoring.xml, p300-tactile-1-acquisition.xml, #
|
||||
# p300-tactile-2-train-xDAWN.xml, p300-tactile-3-train-classifier.xml, #
|
||||
# p300-tactile-4-online.xml #
|
||||
# #
|
||||
# Author : Tobias Baumann #
|
||||
# Date : 2021-12-27 #
|
||||
########################################################################################################################
|
||||
|
||||
|
||||
########################################################################################################################
|
||||
# General Settings #
|
||||
########################################################################################################################
|
||||
PATH_CONFIG = ${Player_ScenarioDirectory}/cfg
|
||||
PATH_SCRIPTS = ${Player_ScenarioDirectory}/scripts
|
||||
PATH_SIGNALS = ${Player_ScenarioDirectory}/signals
|
||||
PATH_UI = ${Player_ScenarioDirectory}/ui
|
||||
|
||||
ROW_BASE = OVTK_StimulationId_Label_01
|
||||
N_TACTILOS = 6
|
||||
FREE_SPELLING = true
|
||||
|
||||
|
||||
########################################################################################################################
|
||||
# Acquisition and Signal Processing #
|
||||
########################################################################################################################
|
||||
ACQUISITION_SERVER_HOST_NAME = ${AcquisitionServer_HostName}
|
||||
ACQUISITION_SERVER_PORT = 1024
|
||||
CHANNEL_SELECTION = 1;2;3;4;5;6;7;8
|
||||
SIGNAL_DECIMATION_FACTOR = 2
|
||||
FILTER_TYPE = Band Pass
|
||||
FILTER_ORDER = 4
|
||||
LOW_CUT_FREQUENCY = 1.000000
|
||||
HIGH_CUT_FREQUENCY = 20.000000
|
||||
|
||||
|
||||
|
||||
########################################################################################################################
|
||||
# Stimulation #
|
||||
########################################################################################################################
|
||||
SCRIPT_TACTILE_STIMULATOR = ${PATH_SCRIPTS}/p300-tactile-stimulator.lua
|
||||
N_REPETITIONS = 4
|
||||
N_TRIALS = 4
|
||||
STIM_DURATION = 0.2
|
||||
NO_STIM_DURATION = 0.1
|
||||
INTER_REPETITION_DELAY = 1.0
|
||||
INTER_TRIAL_DELAY = 4.0
|
||||
START_STIMULATION = OVTK_StimulationId_Label_00
|
||||
START_DELAY = 20
|
||||
|
||||
|
||||
########################################################################################################################
|
||||
# Tactilo Control #
|
||||
########################################################################################################################
|
||||
SERIAL_PORT = /dev/ttyACM0
|
||||
|
||||
|
||||
########################################################################################################################
|
||||
# Target Generation #
|
||||
########################################################################################################################
|
||||
SCRIPT_TARGET_GENERATION = ${PATH_SCRIPTS}/p300-tactile-target.lua
|
||||
SEND_DELAY = 2
|
||||
|
||||
|
||||
########################################################################################################################
|
||||
# FILE I/O #
|
||||
########################################################################################################################
|
||||
OUTPUT_FILE_NAME = ${PATH_SIGNALS}/p300-tactile-session.ov
|
||||
INPUT_FILE_NAME = ${PATH_SIGNALS}/p300-tactile-session.ov
|
||||
|
||||
|
||||
########################################################################################################################
|
||||
# xDAWN Spatial Filter #
|
||||
########################################################################################################################
|
||||
SPATIAL_TRAIN_TRIGGER = OVTK_StimulationId_ExperimentStop
|
||||
SPATIAL_FILTER_CONFIG = ${PATH_CONFIG}/p300-spatial-filter.cfg
|
||||
FILTER_DIMENSION = 2
|
||||
|
||||
|
||||
########################################################################################################################
|
||||
# P300 Classifier #
|
||||
########################################################################################################################
|
||||
CLASSIFIER_TRAIN_TRIGGER = OVTK_StimulationId_ExperimentStop
|
||||
CLASSIFIER_CONFIG = ${PATH_CONFIG}/p300-classifier.cfg
|
||||
MULTICLASS_STRATEGY = Native
|
||||
CLASS_1 = OVTK_StimulationId_Target
|
||||
CLASS_2 = OVTK_StimulationId_NonTarget
|
||||
ALGORITHM = Linear Discrimimant Analysis (LDA)
|
||||
USE_SHRINKAGE = false
|
||||
SHRINKAGE_COEFFICIENT = -1.000000
|
||||
SHRINKAGE_FORCE_DIAGONAL_COV = false
|
||||
N_PARTITIONS = 5
|
||||
CLASS_BALANCE = false
|
||||
|
||||
|
||||
########################################################################################################################
|
||||
# P300 ACCUMULATOR #
|
||||
########################################################################################################################
|
||||
SCRIPT_P300_ACCUMULATOR = ${PATH_SCRIPTS}/p300-tactile-accumulator.lua
|
||||
|
||||
|
||||
########################################################################################################################
|
||||
# Tactile Visualization #
|
||||
########################################################################################################################
|
||||
TACTILE_UI = ${PATH_UI}/p300-tactile-6.ui
|
||||
FLASH_BG = 5,5,5
|
||||
FLASH_FG = 100,100,100
|
||||
FLASH_FONT_SIZE = 50
|
||||
NO_FLASH_BG = 0,0,0
|
||||
NO_FLASH_FG = 25,25,25
|
||||
NO_FLASH_FONT_SIZE = 50
|
||||
TARGET_BG = 20,20,70
|
||||
TARGET_FG = 10,10,30
|
||||
TARGET_FONT_SIZE = 50
|
||||
SELECTED_BG = 10,40,10
|
||||
SELECTED_FG = 60,100,60
|
||||
SELECTED_FONT_SIZE = 50
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
<OpenViBE-SettingsOverride>
|
||||
<SettingValue>Epoch block average</SettingValue>
|
||||
<SettingValue>1</SettingValue>
|
||||
</OpenViBE-SettingsOverride>
|
||||
@@ -0,0 +1,58 @@
|
||||
#############################################################################################################################################################################################################################################
|
||||
# OpenViBE Command Lines Tactile-BCI #
|
||||
# #
|
||||
# Author : Tobias Baumann #
|
||||
# Date : 2022-01-18 #
|
||||
#############################################################################################################################################################################################################################################
|
||||
|
||||
#############################################################################################################################################################################################################################################
|
||||
# Start Acquisition Server #
|
||||
#############################################################################################################################################################################################################################################
|
||||
|
||||
OV_PATH\openvibe-acquisition-server.cmd --define AcquisitionServer_DefaultDriver DRIVER_NAME --define AcquisitionServer_DefaultSampleCountPerBuffer N_SAMPLES_PER_BUFFER --define AcquisitionServer_DefaultConnectionPort PORT_NUMBER
|
||||
|
||||
OV_PATH --> Pfad zur openvibe-acquisition-server.sh
|
||||
DRIVER_NAME --> Bezeichnung des zu verwendenden Treibers z.B.: "g.tec Unicorn Gipsa-lab"
|
||||
N_SAMPLES_PER_BUFFER --> Anzahl der Samples pro Buffer (4,8,16,32,64,128,256,512) (default: 32)
|
||||
PORT_NUMBER --> Vom Acquisition Server verwendeter Port (default: 1024)
|
||||
|
||||
|
||||
#############################################################################################################################################################################################################################################
|
||||
# Wiedergabe der Szenarios ohne Designer GUI und mit der Konfiguration für das Taktile BCI #
|
||||
#############################################################################################################################################################################################################################################
|
||||
|
||||
1. Allgemeiner Aufruf:
|
||||
|
||||
OV_PATH\openvibe-designer.cmd --no-gui --config CONFIG_PATH\OV_TACTILE_PANDA.conf --play SCENARIO_PATH\SCENARIO_NAME.xml
|
||||
|
||||
OV_PATH --> Pfad zur openvibe-designer.sh
|
||||
SCENARIO_PATH --> Pfad zu den Szenarios für das Taktile BCI
|
||||
SCENARIO_NAME --> Name des zu startenden Szenarios
|
||||
CONFIG_PATH --> Pfad zur Config für das Taktile BCI (=SCENARIO_PATH\cfg)
|
||||
|
||||
2. Szenario 0 - Signal Monitoring:
|
||||
|
||||
OV_PATH\openvibe-designer.sh --no-gui --config CONFIG_PATH\OV_TACTILE_PANDA.conf --play SCENARIO_PATH\p300-tactile-0-signal-monitoring.xml
|
||||
|
||||
3. Szenario 1 - Acquisition:
|
||||
|
||||
OV_PATH\openvibe-designer.sh --no-gui --config CONFIG_PATH\OV_TACTILE_PANDA.conf --play SCENARIO_PATH\p300-tactile-1-acquisition.xml
|
||||
|
||||
4. Szenario 2 - Train xDAWN Filter:
|
||||
|
||||
OV_PATH\openvibe-designer.sh --no-gui --config CONFIG_PATH\OV_TACTILE_PANDA.conf --playfast SCENARIO_PATH\p300-tactile-2-train-xDAWN.xml
|
||||
|
||||
4. Szenario 3 - Train P300 Classifier:
|
||||
|
||||
OV_PATH\openvibe-designer.sh --no-gui --config CONFIG_PATH\OV_TACTILE_PANDA.conf --playfast SCENARIO_PATH\p300-tactile-3-train-classifier.xml
|
||||
|
||||
5. Szenario 4 - Online(Free_Spelling):
|
||||
|
||||
OV_PATH\openvibe-designer.sh --no-gui --config CONFIG_PATH\OV_TACTILE_PANDA.conf --define FREE_SPELLING true --play SCENARIO_PATH\p300-tactile-4-online.xml
|
||||
|
||||
6. Szenario 4 - Online(Copy_Spelling):
|
||||
|
||||
OV_PATH\openvibe-designer.sh --no-gui --config CONFIG_PATH\OV_TACTILE_PANDA.conf --define FREE_SPELLING false --play SCENARIO_PATH\p300-tactile-4-online.xml
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
p300-tactile:
|
||||
|
||||
- Die Szenarien für das Taktile BCI basieren auf dem OpenVibeSzenrio p300-speller-xDAWN.
|
||||
- Die Ausführungsreihenfolge ist Acquisition -> train-xDAWN -> train-classifier -> online.
|
||||
|
||||
- der Designer muss mit --config CONFIG_PATH\OV_TACTILE_PANDA.conf von der konsole gestartet werden um die im config file festgelegten Tokens verwenden zu können
|
||||
- weitere Informationen zum ausführen der Szenarios sind in "Commands_TactileBCI.txt" zu finden
|
||||
@@ -0,0 +1,743 @@
|
||||
<OpenViBE-Scenario>
|
||||
<FormatVersion>2</FormatVersion>
|
||||
<Creator>OpenViBE Designer</Creator>
|
||||
<CreatorVersion>3.3.0</CreatorVersion>
|
||||
<Settings></Settings>
|
||||
<Inputs></Inputs>
|
||||
<Outputs></Outputs>
|
||||
<Boxes>
|
||||
<Box>
|
||||
<Identifier>(0x000014bf, 0x000034db)</Identifier>
|
||||
<Name>Identity</Name>
|
||||
<AlgorithmClassIdentifier>(0x5dffe431, 0x35215c50)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Input stream 1</Name>
|
||||
</Input>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Input stream 2</Name>
|
||||
</Input>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Input stream 3</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Output stream 1</Name>
|
||||
</Output>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Output stream 2</Name>
|
||||
</Output>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Output stream 3</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x17ee7c08, 0x94c14893)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>432</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>928</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x30a4e5c9, 0x83502953)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0xa8ffe2a3, 0x27038f03)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x527ad68d, 0x16d746a0)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xac367a9c, 0x2da95abe)</Identifier>
|
||||
<Value>6</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xfba64161, 0x65304e21)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x00003f1b, 0x00003c78)</Identifier>
|
||||
<Name>Signal Decimation</Name>
|
||||
<AlgorithmClassIdentifier>(0x012f4bea, 0x3be37c66)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Input signal</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Output signal</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
|
||||
<Name>Decimation factor</Name>
|
||||
<DefaultValue>8</DefaultValue>
|
||||
<Value>${SIGNAL_DECIMATION_FACTOR}</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>336</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>816</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x5082af41, 0xd0fbf4cb)</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x000046bc, 0x00003f08)</Identifier>
|
||||
<Name>Temporal Filter</Name>
|
||||
<AlgorithmClassIdentifier>(0xb4f9d042, 0x9d79f2e5)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Input signal</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Output signal</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0xfa20178e, 0x4cba62e9)</TypeIdentifier>
|
||||
<Name>Filter Type</Name>
|
||||
<DefaultValue>Band Pass</DefaultValue>
|
||||
<Value>${FILTER_TYPE}</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
|
||||
<Name>Filter Order</Name>
|
||||
<DefaultValue>4</DefaultValue>
|
||||
<Value>${FILTER_ORDER}</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Low Cut-off Frequency (Hz)</Name>
|
||||
<DefaultValue>1</DefaultValue>
|
||||
<Value>${LOW_CUT_FREQUENCY}</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>High Cut-off Frequency (Hz)</Name>
|
||||
<DefaultValue>40</DefaultValue>
|
||||
<Value>${HIGH_CUT_FREQUENCY}</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x17ee7c08, 0x94c14893)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>256</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>816</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x6a7c1e9b, 0x6b00b5c5)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>4</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x00005c5c, 0x00007610)</Identifier>
|
||||
<Name>Raw</Name>
|
||||
<AlgorithmClassIdentifier>(0x0055be5f, 0x087bdd12)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Data</Name>
|
||||
</Input>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Stimulations</Name>
|
||||
</Input>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x6ab26b81, 0x0f8c02f3)</TypeIdentifier>
|
||||
<Name>Channel Units</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x5de046a6, 0x086340aa)</TypeIdentifier>
|
||||
<Name>Display Mode</Name>
|
||||
<DefaultValue>Scan</DefaultValue>
|
||||
<Value>Scan</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x33a30739, 0x00d5299b)</TypeIdentifier>
|
||||
<Name>Auto vertical scale</Name>
|
||||
<DefaultValue>Per channel</DefaultValue>
|
||||
<Value>Per channel</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Scale refresh interval (secs)</Name>
|
||||
<DefaultValue>5</DefaultValue>
|
||||
<Value>0.000000</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Vertical Scale</Name>
|
||||
<DefaultValue>100</DefaultValue>
|
||||
<Value>100</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Vertical Offset</Name>
|
||||
<DefaultValue>0</DefaultValue>
|
||||
<Value>0</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Time Scale</Name>
|
||||
<DefaultValue>10</DefaultValue>
|
||||
<Value>5.000000</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2cdb2f0b, 0x12f231ea)</TypeIdentifier>
|
||||
<Name>Horizontal ruler</Name>
|
||||
<DefaultValue>true</DefaultValue>
|
||||
<Value>true</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2cdb2f0b, 0x12f231ea)</TypeIdentifier>
|
||||
<Name>Vertical ruler</Name>
|
||||
<DefaultValue>false</DefaultValue>
|
||||
<Value>false</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2cdb2f0b, 0x12f231ea)</TypeIdentifier>
|
||||
<Name>Multiview</Name>
|
||||
<DefaultValue>false</DefaultValue>
|
||||
<Value>false</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>560</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>1024</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x92c056a7, 0x2dc71aff)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x527ad68d, 0x16d746a0)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc73e83ec, 0xf855c5bc)</Identifier>
|
||||
<Value>false</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>9</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
|
||||
<Value>3</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x00006b6d, 0x00002690)</Identifier>
|
||||
<Name>Acquisition client</Name>
|
||||
<AlgorithmClassIdentifier>(0x35d225cb, 0x3e6e3a5f)</AlgorithmClassIdentifier>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x403488e7, 0x565d70b6)</TypeIdentifier>
|
||||
<Name>Experiment information</Name>
|
||||
</Output>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Signal stream</Name>
|
||||
</Output>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Stimulations</Name>
|
||||
</Output>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x013df452, 0xa3a8879a)</TypeIdentifier>
|
||||
<Name>Channel localisation</Name>
|
||||
</Output>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x6ab26b81, 0x0f8c02f3)</TypeIdentifier>
|
||||
<Name>Channel units</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x79a9edeb, 0x245d83fc)</TypeIdentifier>
|
||||
<Name>Acquisition server hostname</Name>
|
||||
<DefaultValue>${AcquisitionServer_HostName}</DefaultValue>
|
||||
<Value>${ACQUISITION_SERVER_HOST_NAME}</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
|
||||
<Name>Acquisition server port</Name>
|
||||
<DefaultValue>1024</DefaultValue>
|
||||
<Value>${ACQUISITION_SERVER_PORT}</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>64</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>944</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x0d4656c0, 0xc95b1fa8)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc73e83ec, 0xf855c5bc)</Identifier>
|
||||
<Value>false</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
|
||||
<Value>5</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>2</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x00007e4e, 0x00006b7b)</Identifier>
|
||||
<Name>Filtered</Name>
|
||||
<AlgorithmClassIdentifier>(0x0055be5f, 0x087bdd12)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Data</Name>
|
||||
</Input>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Stimulations</Name>
|
||||
</Input>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x6ab26b81, 0x0f8c02f3)</TypeIdentifier>
|
||||
<Name>Channel Units</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x5de046a6, 0x086340aa)</TypeIdentifier>
|
||||
<Name>Display Mode</Name>
|
||||
<DefaultValue>Scan</DefaultValue>
|
||||
<Value>Scan</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x33a30739, 0x00d5299b)</TypeIdentifier>
|
||||
<Name>Auto vertical scale</Name>
|
||||
<DefaultValue>Per channel</DefaultValue>
|
||||
<Value>Per channel</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Scale refresh interval (secs)</Name>
|
||||
<DefaultValue>5</DefaultValue>
|
||||
<Value>0.000000</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Vertical Scale</Name>
|
||||
<DefaultValue>100</DefaultValue>
|
||||
<Value>100</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Vertical Offset</Name>
|
||||
<DefaultValue>0</DefaultValue>
|
||||
<Value>0</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Time Scale</Name>
|
||||
<DefaultValue>10</DefaultValue>
|
||||
<Value>5.000000</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2cdb2f0b, 0x12f231ea)</TypeIdentifier>
|
||||
<Name>Horizontal ruler</Name>
|
||||
<DefaultValue>true</DefaultValue>
|
||||
<Value>true</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2cdb2f0b, 0x12f231ea)</TypeIdentifier>
|
||||
<Name>Vertical ruler</Name>
|
||||
<DefaultValue>false</DefaultValue>
|
||||
<Value>false</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2cdb2f0b, 0x12f231ea)</TypeIdentifier>
|
||||
<Name>Multiview</Name>
|
||||
<DefaultValue>false</DefaultValue>
|
||||
<Value>false</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>560</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>832</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x92c056a7, 0x2dc71aff)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x527ad68d, 0x16d746a0)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc73e83ec, 0xf855c5bc)</Identifier>
|
||||
<Value>false</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>9</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
|
||||
<Value>3</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x4ff47ca1, 0x133bd33b)</Identifier>
|
||||
<Name>EEG Signal Selection</Name>
|
||||
<AlgorithmClassIdentifier>(0x361722e8, 0x311574e8)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Input signal</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Output signal</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x79a9edeb, 0x245d83fc)</TypeIdentifier>
|
||||
<Name>Channel List</Name>
|
||||
<DefaultValue>:</DefaultValue>
|
||||
<Value>${CHANNEL_SELECTION}</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x3bcf9e67, 0x0c23994d)</TypeIdentifier>
|
||||
<Name>Action</Name>
|
||||
<DefaultValue>Select</DefaultValue>
|
||||
<Value>Select</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x666f25e9, 0x3e5738d6)</TypeIdentifier>
|
||||
<Name>Channel Matching Method</Name>
|
||||
<DefaultValue>Smart</DefaultValue>
|
||||
<Value>Index</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>176</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>864</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x30a4e5c9, 0x83502953)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x277826e1, 0xa30a3bd0)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x527ad68d, 0x16d746a0)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>3</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
</Boxes>
|
||||
<Links>
|
||||
<Link>
|
||||
<Identifier>(0x000003a7, 0x000034db)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x000014bf, 0x000034db)</BoxIdentifier>
|
||||
<BoxOutputIndex>2</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x00005c5c, 0x00007610)</BoxIdentifier>
|
||||
<BoxInputIndex>1</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x00000554, 0x0000661a)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x000014bf, 0x000034db)</BoxIdentifier>
|
||||
<BoxOutputIndex>2</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x00007e4e, 0x00006b7b)</BoxIdentifier>
|
||||
<BoxInputIndex>1</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x00001d33, 0x00002bb0)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x00006b6d, 0x00002690)</BoxIdentifier>
|
||||
<BoxOutputIndex>2</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x000014bf, 0x000034db)</BoxIdentifier>
|
||||
<BoxInputIndex>2</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x00003f04, 0x000045c3)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x000014bf, 0x000034db)</BoxIdentifier>
|
||||
<BoxOutputIndex>1</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x00005c5c, 0x00007610)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x00004b11, 0x00006a43)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x00003f1b, 0x00003c78)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x000014bf, 0x000034db)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x000056fd, 0x00004795)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x000014bf, 0x000034db)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x00007e4e, 0x00006b7b)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x2336eb7d, 0x44803e51)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x4ff47ca1, 0x133bd33b)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x000046bc, 0x00003f08)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x384b6f31, 0x639fff7d)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x4ff47ca1, 0x133bd33b)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x000014bf, 0x000034db)</BoxIdentifier>
|
||||
<BoxInputIndex>1</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x771fd1ca, 0x72794515)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x000046bc, 0x00003f08)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x00003f1b, 0x00003c78)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x7c0285ed, 0x7aaf8bb7)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x00006b6d, 0x00002690)</BoxIdentifier>
|
||||
<BoxOutputIndex>1</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x4ff47ca1, 0x133bd33b)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
</Links>
|
||||
<Comments>
|
||||
<Comment>
|
||||
<Identifier>(0x000028e8, 0x00003dee)</Identifier>
|
||||
<Text><u><b><big>Scenario Overview</big></b></u>
|
||||
|
||||
This scenario can be used in order
|
||||
to check the quality of the signals
|
||||
before starting an experiment.
|
||||
|
||||
One should <u>definitely</u>
|
||||
check the quality of the signals
|
||||
and ensure that :
|
||||
|
||||
- <b>eye blinks</b> are visible
|
||||
- <b>jaw clenching</b> are visible
|
||||
- <b>alpha waves</b> are visible when closing eyes
|
||||
|
||||
Two Signals are displayed, one is the raw EEG-Signal
|
||||
and the other one is the filtered signal.
|
||||
The filtered signal is the one, that will actually be used
|
||||
in other scenarios.</Text>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x473d9a43, 0x97fc0a97)</Identifier>
|
||||
<Value>576</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x7234b86b, 0x2b8651a5)</Identifier>
|
||||
<Value>272</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Comment>
|
||||
</Comments>
|
||||
<Metadata>
|
||||
<Entry>
|
||||
<Identifier>(0x0000775c, 0x000078ff)</Identifier>
|
||||
<Type>(0x3bcce5d2, 0x43f2d968)</Type>
|
||||
<Data>[{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":1,"height":635,"identifier":"(0x000077ee, 0x0000254d)","name":"default","parentIdentifier":"(0xffffffff, 0xffffffff)","type":1,"width":783},{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":1,"identifier":"(0x00004579, 0x00005fcb)","index":0,"name":"Default tab","parentIdentifier":"(0x000077ee, 0x0000254d)","type":2},{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":2,"dividerPosition":293,"identifier":"(0x00005446, 0x000043a1)","index":0,"maxDividerPosition":590,"name":"Vertical split","parentIdentifier":"(0x00004579, 0x00005fcb)","type":4},{"boxIdentifier":"(0x00005c5c, 0x00007610)","childCount":0,"identifier":"(0x00000e42, 0x000074b8)","index":0,"parentIdentifier":"(0x00005446, 0x000043a1)","type":3},{"boxIdentifier":"(0x00007e4e, 0x00006b7b)","childCount":0,"identifier":"(0x00005db7, 0x000032ad)","index":1,"parentIdentifier":"(0x00005446, 0x000043a1)","type":3}]</Data>
|
||||
</Entry>
|
||||
</Metadata>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x790d75b8, 0x3bb90c33)</Identifier>
|
||||
<Value>Yann Renard</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x8c1fc55b, 0x7b433dc2)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x9f5c4075, 0x4a0d3666)</Identifier>
|
||||
<Value>Signal Monitoring</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xf36a1567, 0xd13c53da)</Identifier>
|
||||
<Value>http://openvibe.inria.fr/p300-speller-xdawn/</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xf6b2e3fa, 0x7bd43926)</Identifier>
|
||||
<Value>xDAWN P300 Speller</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xf8034a49, 0x8b3f37cc)</Identifier>
|
||||
<Value>INRIA</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</OpenViBE-Scenario>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,438 @@
|
||||
<OpenViBE-Scenario>
|
||||
<FormatVersion>2</FormatVersion>
|
||||
<Creator>OpenViBE Designer</Creator>
|
||||
<CreatorVersion>3.3.0</CreatorVersion>
|
||||
<Settings></Settings>
|
||||
<Inputs></Inputs>
|
||||
<Outputs></Outputs>
|
||||
<Boxes>
|
||||
<Box>
|
||||
<Identifier>(0x00001db8, 0x00001848)</Identifier>
|
||||
<Name>xDAWN Trainer</Name>
|
||||
<AlgorithmClassIdentifier>(0x27542f6e, 0x14aa3548)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Stimulations</Name>
|
||||
</Input>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Session signal</Name>
|
||||
</Input>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Evoked potential epochs</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Train-completed Flag</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Train stimulation</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Train</DefaultValue>
|
||||
<Value>${SPATIAL_TRAIN_TRIGGER}</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x330306dd, 0x74a95f98)</TypeIdentifier>
|
||||
<Name>Spatial filter configuration</Name>
|
||||
<DefaultValue></DefaultValue>
|
||||
<Value>${SPATIAL_FILTER_CONFIG}</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
|
||||
<Name>Filter dimension</Name>
|
||||
<DefaultValue>4</DefaultValue>
|
||||
<Value>${FILTER_DIMENSION}</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2cdb2f0b, 0x12f231ea)</TypeIdentifier>
|
||||
<Name>Save as box config</Name>
|
||||
<DefaultValue>true</DefaultValue>
|
||||
<Value>true</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>176</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>288</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x4b49a133, 0x42f38d94)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x00002514, 0x00001614)</Identifier>
|
||||
<Name>Generic stream reader</Name>
|
||||
<AlgorithmClassIdentifier>(0x6468099f, 0x0370095a)</AlgorithmClassIdentifier>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x403488e7, 0x565d70b6)</TypeIdentifier>
|
||||
<Name>Output stream 1</Name>
|
||||
</Output>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Output stream 2</Name>
|
||||
</Output>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Output stream 3</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x330306dd, 0x74a95f98)</TypeIdentifier>
|
||||
<Name>Filename</Name>
|
||||
<DefaultValue></DefaultValue>
|
||||
<Value>${INPUT_FILE_NAME}</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x17ee7c08, 0x94c14893)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>-128</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>400</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x30a4e5c9, 0x83502953)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0xf37b8e7a, 0x1bc33e4e)</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x0000267a, 0x0000427f)</Identifier>
|
||||
<Name>Time based epoching</Name>
|
||||
<AlgorithmClassIdentifier>(0x00777fa0, 0x5dc3f560)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Input signal</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Epoched signal 1</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Epoch 1 duration (in sec)</Name>
|
||||
<DefaultValue>1</DefaultValue>
|
||||
<Value>0.250000</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Epoch 1 intervals (in sec)</Name>
|
||||
<DefaultValue>0.5</DefaultValue>
|
||||
<Value>0.250000</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x17ee7c08, 0x94c14893)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>-16</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>288</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0xc5ff41e9, 0xccc59a01)</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x00004aea, 0x00001465)</Identifier>
|
||||
<Name>Player Controller</Name>
|
||||
<AlgorithmClassIdentifier>(0x5f426dce, 0x08456e13)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Stimulations</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Stimulation name</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Label_00</DefaultValue>
|
||||
<Value>OVTK_StimulationId_TrainCompleted</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0xcc14d8d6, 0xf27ecb73)</TypeIdentifier>
|
||||
<Name>Action to perform</Name>
|
||||
<DefaultValue>Pause</DefaultValue>
|
||||
<Value>Stop</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>240</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>288</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x568d148e, 0x650792b3)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>2</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x00006fa4, 0x00003c77)</Identifier>
|
||||
<Name>Target Selection</Name>
|
||||
<AlgorithmClassIdentifier>(0x426163d1, 0x324237b0)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Input signal</Name>
|
||||
</Input>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Input stimulations</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Epoched signal</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Epoch duration (in sec)</Name>
|
||||
<DefaultValue>1</DefaultValue>
|
||||
<Value>0.6</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Epoch offset (in sec)</Name>
|
||||
<DefaultValue>0.5</DefaultValue>
|
||||
<Value>0</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Stimulation to epoch from</Name>
|
||||
<DefaultValue>OVTK_GDF_VEP</DefaultValue>
|
||||
<Value>OVTK_StimulationId_Target</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>64</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>416</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x5de31172, 0xa1304456)</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
</Boxes>
|
||||
<Links>
|
||||
<Link>
|
||||
<Identifier>(0x00003920, 0x00007a30)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x0000267a, 0x0000427f)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x00001db8, 0x00001848)</BoxIdentifier>
|
||||
<BoxInputIndex>1</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x00004bf5, 0x00007908)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x00001db8, 0x00001848)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x00004aea, 0x00001465)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x000059e8, 0x00000032)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x00002514, 0x00001614)</BoxIdentifier>
|
||||
<BoxOutputIndex>2</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x00001db8, 0x00001848)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x00006913, 0x00003182)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x00002514, 0x00001614)</BoxIdentifier>
|
||||
<BoxOutputIndex>1</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x0000267a, 0x0000427f)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x074b170c, 0x37e84571)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x0000267a, 0x0000427f)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x00006fa4, 0x00003c77)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x188f2058, 0x7ac23f09)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x00006fa4, 0x00003c77)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x00001db8, 0x00001848)</BoxIdentifier>
|
||||
<BoxInputIndex>2</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x2b245a90, 0x47f6e438)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x00002514, 0x00001614)</BoxIdentifier>
|
||||
<BoxOutputIndex>2</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x00006fa4, 0x00003c77)</BoxIdentifier>
|
||||
<BoxInputIndex>1</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
</Links>
|
||||
<Comments>
|
||||
<Comment>
|
||||
<Identifier>(0x000049d6, 0x00006e67)</Identifier>
|
||||
<Text><u><b><big>Scenario Overview</big></b></u>
|
||||
|
||||
This scenario should be used to train
|
||||
the spatial filter using the xDAWN algorithm.
|
||||
|
||||
At the end of the training, you will have line in
|
||||
the console about eigen values.
|
||||
Using a <i>Player Controller</i> the scenario will
|
||||
automatically pause at the end of the training.
|
||||
|
||||
If you want details on this values, you should read
|
||||
<u>http://www.icp.inpg.fr/~rivetber/Publications/references/Rivet2009a.pdf</u></Text>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x473d9a43, 0x97fc0a97)</Identifier>
|
||||
<Value>704</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x7234b86b, 0x2b8651a5)</Identifier>
|
||||
<Value>-32</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Comment>
|
||||
</Comments>
|
||||
<Metadata>
|
||||
<Entry>
|
||||
<Identifier>(0x0000775c, 0x000078ff)</Identifier>
|
||||
<Type>(0x3bcce5d2, 0x43f2d968)</Type>
|
||||
<Data>[]</Data>
|
||||
</Entry>
|
||||
</Metadata>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x790d75b8, 0x3bb90c33)</Identifier>
|
||||
<Value>Yann Renard</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x8c1fc55b, 0x7b433dc2)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x9f5c4075, 0x4a0d3666)</Identifier>
|
||||
<Value>Spatial Filter Training</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xf36a1567, 0xd13c53da)</Identifier>
|
||||
<Value>http://openvibe.inria.fr/p300-speller-xdawn/</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xf6b2e3fa, 0x7bd43926)</Identifier>
|
||||
<Value>xDAWN P300 Speller</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xf8034a49, 0x8b3f37cc)</Identifier>
|
||||
<Value>INRIA</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</OpenViBE-Scenario>
|
||||
@@ -0,0 +1,898 @@
|
||||
<OpenViBE-Scenario>
|
||||
<FormatVersion>2</FormatVersion>
|
||||
<Creator>OpenViBE Designer</Creator>
|
||||
<CreatorVersion>3.3.0</CreatorVersion>
|
||||
<Settings></Settings>
|
||||
<Inputs></Inputs>
|
||||
<Outputs></Outputs>
|
||||
<Boxes>
|
||||
<Box>
|
||||
<Identifier>(0x00000b2d, 0x00006d61)</Identifier>
|
||||
<Name>Feature aggregator</Name>
|
||||
<AlgorithmClassIdentifier>(0x00682417, 0x453635f9)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x544a003e, 0x6dcba5f6)</TypeIdentifier>
|
||||
<Name>Input stream 1</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x17341935, 0x152ff448)</TypeIdentifier>
|
||||
<Name>Feature vector stream</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>240</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>336</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0xb5d15cc9, 0x6c8c28fb)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc46b3d00, 0x3e0454e1)</Identifier>
|
||||
<Value>(0x00000000, 0x002bb807)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xfba64161, 0x65304e21)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x00000d41, 0x000013b7)</Identifier>
|
||||
<Name>Feature aggregator</Name>
|
||||
<AlgorithmClassIdentifier>(0x00682417, 0x453635f9)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x544a003e, 0x6dcba5f6)</TypeIdentifier>
|
||||
<Name>Input stream 1</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x17341935, 0x152ff448)</TypeIdentifier>
|
||||
<Name>Feature vector stream</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>240</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>528</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0xb5d15cc9, 0x6c8c28fb)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc46b3d00, 0x3e0454e1)</Identifier>
|
||||
<Value>(0x00000000, 0x002b7d6e)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xfba64161, 0x65304e21)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x00001f83, 0x00004e32)</Identifier>
|
||||
<Name>Generic stream reader</Name>
|
||||
<AlgorithmClassIdentifier>(0x6468099f, 0x0370095a)</AlgorithmClassIdentifier>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x403488e7, 0x565d70b6)</TypeIdentifier>
|
||||
<Name>Output stream 1</Name>
|
||||
</Output>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Output stream 2</Name>
|
||||
</Output>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Output stream 3</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x330306dd, 0x74a95f98)</TypeIdentifier>
|
||||
<Name>Filename</Name>
|
||||
<DefaultValue></DefaultValue>
|
||||
<Value>${INPUT_FILE_NAME}</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x17ee7c08, 0x94c14893)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>-160</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>400</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x30a4e5c9, 0x83502953)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0xf37b8e7a, 0x1bc33e4e)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc46b3d00, 0x3e0454e1)</Identifier>
|
||||
<Value>(0x00000000, 0x008e34c7)</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x00002c8b, 0x000001d5)</Identifier>
|
||||
<Name>Player Controller</Name>
|
||||
<AlgorithmClassIdentifier>(0x5f426dce, 0x08456e13)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Stimulations</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Stimulation name</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Label_00</DefaultValue>
|
||||
<Value>OVTK_StimulationId_TrainCompleted</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0xcc14d8d6, 0xf27ecb73)</TypeIdentifier>
|
||||
<Name>Action to perform</Name>
|
||||
<DefaultValue>Pause</DefaultValue>
|
||||
<Value>Stop</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>416</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>448</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x568d148e, 0x650792b3)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc46b3d00, 0x3e0454e1)</Identifier>
|
||||
<Value>(0x00000000, 0x00301c7f)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc73e83ec, 0xf855c5bc)</Identifier>
|
||||
<Value>false</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>2</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x00002f94, 0x00000342)</Identifier>
|
||||
<Name>Non Target Selection</Name>
|
||||
<AlgorithmClassIdentifier>(0x426163d1, 0x324237b0)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Input signal</Name>
|
||||
</Input>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Input stimulations</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Epoched signal</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Epoch duration (in sec)</Name>
|
||||
<DefaultValue>1</DefaultValue>
|
||||
<Value>0.6</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Epoch offset (in sec)</Name>
|
||||
<DefaultValue>0.5</DefaultValue>
|
||||
<Value>0</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Stimulation to epoch from</Name>
|
||||
<DefaultValue>OVTK_GDF_VEP</DefaultValue>
|
||||
<Value>OVTK_StimulationId_NonTarget</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>112</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>528</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x5de31172, 0xa1304456)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc46b3d00, 0x3e0454e1)</Identifier>
|
||||
<Value>(0x00000000, 0x002bbddf)</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x000063a5, 0x0000197d)</Identifier>
|
||||
<Name>Target Selection</Name>
|
||||
<AlgorithmClassIdentifier>(0x426163d1, 0x324237b0)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Input signal</Name>
|
||||
</Input>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Input stimulations</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Epoched signal</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Epoch duration (in sec)</Name>
|
||||
<DefaultValue>1</DefaultValue>
|
||||
<Value>0.6</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Epoch offset (in sec)</Name>
|
||||
<DefaultValue>0.5</DefaultValue>
|
||||
<Value>0</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Stimulation to epoch from</Name>
|
||||
<DefaultValue>OVTK_GDF_VEP</DefaultValue>
|
||||
<Value>OVTK_StimulationId_Target</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>112</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>336</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x5de31172, 0xa1304456)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc46b3d00, 0x3e0454e1)</Identifier>
|
||||
<Value>(0x00000000, 0x002b4e91)</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x000078d0, 0x000029bc)</Identifier>
|
||||
<Name>Epoch average</Name>
|
||||
<AlgorithmClassIdentifier>(0x21283d9f, 0xe76ff640)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Input epochs</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Averaged epochs</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x6530bdb1, 0xd057bbfe)</TypeIdentifier>
|
||||
<Name>Averaging type</Name>
|
||||
<DefaultValue>Epoch block average</DefaultValue>
|
||||
<Value>Epoch block average</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
|
||||
<Name>Epoch count</Name>
|
||||
<DefaultValue>4</DefaultValue>
|
||||
<Value>1</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>176</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>336</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x30a4e5c9, 0x83502953)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0xb73cee83, 0xf7215d60)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x527ad68d, 0x16d746a0)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x8d21ff41, 0xdf6afe7e)</Identifier>
|
||||
<Value>${Player_ScenarioDirectory}/cfg/p300-epoch-average.cfg</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc46b3d00, 0x3e0454e1)</Identifier>
|
||||
<Value>(0x00000000, 0x002b5470)</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x000078f9, 0x000063eb)</Identifier>
|
||||
<Name>xDAWN Spatial Filter</Name>
|
||||
<AlgorithmClassIdentifier>(0xdd332c6c, 0x195b4fd4)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Input Signal</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Output Signal</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x79a9edeb, 0x245d83fc)</TypeIdentifier>
|
||||
<Name>Spatial Filter Coefficients</Name>
|
||||
<DefaultValue>1;0;0;0;0;1;0;0;0;0;1;0;0;0;0;1</DefaultValue>
|
||||
<Value>9.970221e-001 -3.729500e-002 -1.177390e-002 2.814447e-002 -3.772446e-003 3.371324e-002 -5.480030e-003 8.893039e-003 -1.565213e-002 -9.956694e-003 -2.347757e-002 -2.312669e-003 -1.847227e-002 -7.550644e-004 -8.423513e-003 3.243223e-002 2.079848e-002 5.079737e-001 -2.835127e-002 8.259231e-002 -3.621803e-001 -2.004259e-001 -2.432480e-001 -1.861558e-001 -3.798139e-001 9.614762e-002 3.407766e-001 -2.158597e-001 3.720552e-001 7.500469e-002 -8.628774e-002 -3.182367e-002 5.923482e-002 4.124707e-001 2.083913e-001 -2.629501e-001 2.023081e-001 -2.658446e-001 4.022738e-001 -1.785569e-001 4.450742e-001 3.549239e-001 1.550204e-002 3.750389e-002 3.114249e-002 9.273764e-002 -7.093797e-002 -2.610929e-001</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
|
||||
<Name>Number of Output Channels</Name>
|
||||
<DefaultValue>4</DefaultValue>
|
||||
<Value>3</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
|
||||
<Name>Number of Input Channels</Name>
|
||||
<DefaultValue>4</DefaultValue>
|
||||
<Value>16</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x330306dd, 0x74a95f98)</TypeIdentifier>
|
||||
<Name>Filter matrix file</Name>
|
||||
<DefaultValue></DefaultValue>
|
||||
<Value></Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>-32</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>304</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x30a4e5c9, 0x83502953)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x81db9bf9, 0xf1cf4ed7)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x527ad68d, 0x16d746a0)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x8d21ff41, 0xdf6afe7e)</Identifier>
|
||||
<Value>${SPATIAL_FILTER_CONFIG}</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc46b3d00, 0x3e0454e1)</Identifier>
|
||||
<Value>(0x00000000, 0x002b601f)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>3</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x00007b56, 0x000033f9)</Identifier>
|
||||
<Name>Epoch average</Name>
|
||||
<AlgorithmClassIdentifier>(0x21283d9f, 0xe76ff640)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Input epochs</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Averaged epochs</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x6530bdb1, 0xd057bbfe)</TypeIdentifier>
|
||||
<Name>Averaging type</Name>
|
||||
<DefaultValue>Epoch block average</DefaultValue>
|
||||
<Value>Epoch block average</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
|
||||
<Name>Epoch count</Name>
|
||||
<DefaultValue>4</DefaultValue>
|
||||
<Value>1</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>176</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>528</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x30a4e5c9, 0x83502953)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0xb73cee83, 0xf7215d60)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x527ad68d, 0x16d746a0)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x8d21ff41, 0xdf6afe7e)</Identifier>
|
||||
<Value>${Player_ScenarioDirectory}/cfg/p300-epoch-average.cfg</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc46b3d00, 0x3e0454e1)</Identifier>
|
||||
<Value>(0x00000000, 0x002c2168)</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x0a5a6a4a, 0x1d92a778)</Identifier>
|
||||
<Name>Classifier trainer</Name>
|
||||
<AlgorithmClassIdentifier>(0xf3dae8a8, 0x3b444154)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Stimulations</Name>
|
||||
</Input>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x17341935, 0x152ff448)</TypeIdentifier>
|
||||
<Name>Features for class 1</Name>
|
||||
</Input>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x17341935, 0x152ff448)</TypeIdentifier>
|
||||
<Name>Features for class 2</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Train-completed Flag</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Train trigger</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Train</DefaultValue>
|
||||
<Value>${CLASSIFIER_TRAIN_TRIGGER}</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x330306dd, 0x74a95f98)</TypeIdentifier>
|
||||
<Name>Filename to save configuration to</Name>
|
||||
<DefaultValue>${Path_UserData}/my-classifier.xml</DefaultValue>
|
||||
<Value>${CLASSIFIER_CONFIG}</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0xbe9eba5c, 0xa8415d37)</TypeIdentifier>
|
||||
<Name>Multiclass strategy to apply</Name>
|
||||
<DefaultValue>Native</DefaultValue>
|
||||
<Value>${MULTICLASS_STRATEGY}</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Class 1 label</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Label_01</DefaultValue>
|
||||
<Value>${CLASS_1}</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Class 2 label</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Label_02</DefaultValue>
|
||||
<Value>${CLASS_2}</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0xd765a736, 0xed708c65)</TypeIdentifier>
|
||||
<Name>Algorithm to use</Name>
|
||||
<DefaultValue>Linear Discrimimant Analysis (LDA)</DefaultValue>
|
||||
<Value>${ALGORITHM}</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2cdb2f0b, 0x12f231ea)</TypeIdentifier>
|
||||
<Name>Use shrinkage</Name>
|
||||
<DefaultValue>false</DefaultValue>
|
||||
<Value>${USE_SHRINKAGE}</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Shrinkage coefficient (-1 == auto)</Name>
|
||||
<DefaultValue>-1.000000</DefaultValue>
|
||||
<Value>${SHRINKAGE_COEFFICIENT}</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2cdb2f0b, 0x12f231ea)</TypeIdentifier>
|
||||
<Name>Shrinkage: Force diagonal cov (DDA)</Name>
|
||||
<DefaultValue>false</DefaultValue>
|
||||
<Value>${SHRINKAGE_FORCE_DIAGONAL_COV}</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
|
||||
<Name>Number of partitions for k-fold cross-validation test</Name>
|
||||
<DefaultValue>10</DefaultValue>
|
||||
<Value>${N_PARTITIONS}</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2cdb2f0b, 0x12f231ea)</TypeIdentifier>
|
||||
<Name>Balance classes</Name>
|
||||
<DefaultValue>false</DefaultValue>
|
||||
<Value>${CLASS_BALANCE}</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>336</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>448</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x9de21779, 0x37776c89)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc73e83ec, 0xf855c5bc)</Identifier>
|
||||
<Value>false</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>6</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
|
||||
<Value>3</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xfba64161, 0x65304e21)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
</Boxes>
|
||||
<Links>
|
||||
<Link>
|
||||
<Identifier>(0x00000192, 0x0000714e)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x00001f83, 0x00004e32)</BoxIdentifier>
|
||||
<BoxOutputIndex>1</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x000078f9, 0x000063eb)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x00001717, 0x00003cf9)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x000078d0, 0x000029bc)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x00000b2d, 0x00006d61)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x00004674, 0x000061af)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x00007b56, 0x000033f9)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x00000d41, 0x000013b7)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x0ac1c4d1, 0x0a9429d6)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x000063a5, 0x0000197d)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x000078d0, 0x000029bc)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x0f719dbe, 0x6b9207ad)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x000078f9, 0x000063eb)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x00002f94, 0x00000342)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x175e412c, 0x0692f4ee)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x00000d41, 0x000013b7)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x0a5a6a4a, 0x1d92a778)</BoxIdentifier>
|
||||
<BoxInputIndex>2</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x26545f2f, 0x4e793786)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x000078f9, 0x000063eb)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x000063a5, 0x0000197d)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x26dbc15a, 0x2ae965d4)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x00001f83, 0x00004e32)</BoxIdentifier>
|
||||
<BoxOutputIndex>2</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x000063a5, 0x0000197d)</BoxIdentifier>
|
||||
<BoxInputIndex>1</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x33c4df2d, 0x7548b76f)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x00001f83, 0x00004e32)</BoxIdentifier>
|
||||
<BoxOutputIndex>2</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x00002f94, 0x00000342)</BoxIdentifier>
|
||||
<BoxInputIndex>1</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x431fd3b9, 0x43484889)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x00002f94, 0x00000342)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x00007b56, 0x000033f9)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x5a67b7d8, 0x1cf07f9a)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x00001f83, 0x00004e32)</BoxIdentifier>
|
||||
<BoxOutputIndex>2</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x0a5a6a4a, 0x1d92a778)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x616495af, 0x5c020b32)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x0a5a6a4a, 0x1d92a778)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x00002c8b, 0x000001d5)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x63fa63da, 0x0e447c5b)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x00000b2d, 0x00006d61)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x0a5a6a4a, 0x1d92a778)</BoxIdentifier>
|
||||
<BoxInputIndex>1</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
</Links>
|
||||
<Comments>
|
||||
<Comment>
|
||||
<Identifier>(0x00005277, 0x00007fbe)</Identifier>
|
||||
<Text><u><b><big>Scenario Overview</big></b></u>
|
||||
|
||||
This scenario should be used to train
|
||||
the LDA classifier.
|
||||
|
||||
At the end of the training, you will have an estimation
|
||||
of the classifier performance printed in the console.
|
||||
If this performance is lower than 70%, just run a new
|
||||
<i>4-online</i> session to have better results.
|
||||
|
||||
<u><b>Note:</b></u> in order to run this scenario,
|
||||
the spatial filter should have been trained using
|
||||
<i>2-train-xDAWN</i> !</Text>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x473d9a43, 0x97fc0a97)</Identifier>
|
||||
<Value>688</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x7234b86b, 0x2b8651a5)</Identifier>
|
||||
<Value>-64</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Comment>
|
||||
</Comments>
|
||||
<Metadata>
|
||||
<Entry>
|
||||
<Identifier>(0x0000775c, 0x000078ff)</Identifier>
|
||||
<Type>(0x3bcce5d2, 0x43f2d968)</Type>
|
||||
<Data>[]</Data>
|
||||
</Entry>
|
||||
</Metadata>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x790d75b8, 0x3bb90c33)</Identifier>
|
||||
<Value>Yann Renard</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x8c1fc55b, 0x7b433dc2)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x9f5c4075, 0x4a0d3666)</Identifier>
|
||||
<Value>LDA Classifier Trainer</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xf36a1567, 0xd13c53da)</Identifier>
|
||||
<Value>http://openvibe.inria.fr/p300-speller-xdawn/</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xf6b2e3fa, 0x7bd43926)</Identifier>
|
||||
<Value>xDAWN P300 Speller</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xf8034a49, 0x8b3f37cc)</Identifier>
|
||||
<Value>INRIA</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</OpenViBE-Scenario>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,202 @@
|
||||
|
||||
function arrayMax(a)
|
||||
if #a == 0 then return nil, nil end
|
||||
local maxIdx, maxValue = 0, a[0]
|
||||
for i = 1, (#a -1 ) do
|
||||
if maxValue < a[i] then
|
||||
maxIdx, maxValue = i, a[i]
|
||||
end
|
||||
end
|
||||
return maxIdx, maxValue
|
||||
end
|
||||
|
||||
-- For handling target fifo
|
||||
|
||||
List = {}
|
||||
function List.new ()
|
||||
return {first = 0, last = -1}
|
||||
end
|
||||
|
||||
function List.pushright (list, value)
|
||||
local last = list.last + 1
|
||||
list.last = last
|
||||
list[last] = value
|
||||
end
|
||||
|
||||
function List.popleft (list)
|
||||
local first = list.first
|
||||
if first > list.last then
|
||||
error("list is empty")
|
||||
end
|
||||
local value = list[first]
|
||||
list[first] = nil -- to allow garbage collection
|
||||
list.first = first + 1
|
||||
return value
|
||||
end
|
||||
|
||||
function List.isempty (list)
|
||||
if list.first > list.last then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
-- this function is called when the box is initialized
|
||||
function initialize(box)
|
||||
|
||||
dofile(box:get_config("${Path_Data}") .. "/plugins/stimulation/lua-stimulator-stim-codes.lua")
|
||||
|
||||
row_base = _G[box:get_setting(2)]
|
||||
n_tactilos = box:get_setting(3)
|
||||
segment_start = _G[box:get_setting(4)]
|
||||
segment_stop = _G[box:get_setting(5)]
|
||||
|
||||
col_base = row_base + n_tactilos
|
||||
|
||||
-- 0 inactive, 1 segment started, 2 segment stopped (can vote)
|
||||
segment_status = 0
|
||||
|
||||
-- the idea is to push the flash states to the fifo, and when predictions arrive (with some delay), they are matched in oldest-first fashion.
|
||||
target_fifo = List.new()
|
||||
|
||||
-- box:log("Info", string.format("pop %d %d", id[1], id[2]))
|
||||
|
||||
row_votes = {}
|
||||
col_votes = {}
|
||||
|
||||
do_debug = false
|
||||
|
||||
end
|
||||
|
||||
-- this function is called when the box is uninitialized
|
||||
function uninitialize(box)
|
||||
|
||||
end
|
||||
|
||||
function process(box)
|
||||
-- loops until box is stopped
|
||||
while box:keep_processing() do
|
||||
|
||||
-- first, parse the timeline stream
|
||||
for stimulation = 1, box:get_stimulation_count(2) do
|
||||
-- gets the received stimulation
|
||||
local identifier, date, duration = box:get_stimulation(2, 1)
|
||||
-- discards it
|
||||
box:remove_stimulation(2, 1)
|
||||
|
||||
if identifier == segment_start then
|
||||
if do_debug then
|
||||
box:log("Info", string.format("Trial start"))
|
||||
box:log("Info", string.format("Clear votes"))
|
||||
end
|
||||
-- zero the votes
|
||||
col_votes = {}
|
||||
row_votes = {}
|
||||
target_fifo = List.new()
|
||||
-- fixme fixed 20
|
||||
for i = 0,20 do
|
||||
col_votes[i] = 0
|
||||
row_votes[i] = 0
|
||||
end
|
||||
segment_status = 1
|
||||
end
|
||||
|
||||
-- Does the identifier code a flash? if so, put into fifo
|
||||
if segment_status == 1 and identifier >= row_base and identifier <= OVTK_StimulationId_LabelEnd then
|
||||
|
||||
-- assume rows before cols
|
||||
if identifier < col_base then
|
||||
local t = {"row", identifier - row_base}
|
||||
List.pushright(target_fifo,t)
|
||||
if do_debug then
|
||||
box:log("Info", string.format("Push row target %d", identifier - row_base ))
|
||||
end
|
||||
else
|
||||
local t = {"col", identifier - col_base}
|
||||
List.pushright(target_fifo,t)
|
||||
if do_debug then
|
||||
box:log("Info", string.format("Push col target %d", identifier - col_base ))
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
if identifier == segment_stop then
|
||||
if do_debug then
|
||||
box:log("Info", string.format("Trial stop"))
|
||||
end
|
||||
segment_status = 2
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- then parse the classifications
|
||||
for stimulation = 1, box:get_stimulation_count(1) do
|
||||
|
||||
-- gets the received stimulation
|
||||
local identifier, date, duration = box:get_stimulation(1, 1)
|
||||
-- discards it
|
||||
box:remove_stimulation(1, 1)
|
||||
|
||||
-- Is it an in-class prediction?
|
||||
if identifier == OVTK_StimulationId_Target then
|
||||
local t = List.popleft(target_fifo)
|
||||
if do_debug then
|
||||
box:log("Info", string.format("Pred fifo %s %d is target", t[1], t[2]))
|
||||
end
|
||||
if t[1]=="row" then
|
||||
row_votes[t[2]] = row_votes[t[2]] + 1
|
||||
else
|
||||
col_votes[t[2]] = col_votes[t[2]] + 1
|
||||
end
|
||||
end
|
||||
|
||||
if identifier == OVTK_StimulationId_NonTarget then
|
||||
local t = List.popleft(target_fifo)
|
||||
if do_debug then
|
||||
box:log("Info", string.format("Pred fifo %s %d is nontarget", t[1], t[2]))
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if segment_status == 2 and List.isempty(target_fifo) then
|
||||
-- output the vote after the segment end when we've matched all predictions
|
||||
|
||||
local maxRowIdx, maxRowValue = arrayMax(row_votes)
|
||||
local maxColIdx, maxColValue = arrayMax(col_votes)
|
||||
|
||||
if maxRowValue == 0 and maxColValue == 0 then
|
||||
box:log("Warning", string.format("Classifier predicted 'no p300' for all flashes of the trial"));
|
||||
end
|
||||
|
||||
if do_debug then
|
||||
local rowVotes = 0
|
||||
local colVotes = 0
|
||||
for ir, val in pairs(row_votes) do
|
||||
rowVotes = rowVotes + val
|
||||
end
|
||||
for ir, val in pairs(col_votes) do
|
||||
colVotes = colVotes + val
|
||||
end
|
||||
|
||||
box:log("Info", string.format("Vote [%d %d] wt [%d,%d]", maxRowIdx+row_base, maxColIdx+col_base, maxRowValue, maxColValue))
|
||||
box:log("Info", string.format(" Total [%d %d]", rowVotes, colVotes))
|
||||
end
|
||||
|
||||
|
||||
|
||||
local now = box:get_current_time()
|
||||
|
||||
box:send_stimulation(1, maxRowIdx + row_base, now, 0)
|
||||
-- box:send_stimulation(2, maxColIdx + col_base, now, 0)
|
||||
|
||||
segment_status = 0
|
||||
end
|
||||
|
||||
box:sleep()
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
|
||||
-- Picks out 'flashes' from a stimulation stream
|
||||
|
||||
-- this function is called when the box is initialized
|
||||
function initialize(box)
|
||||
|
||||
dofile(box:get_config("${Path_Data}") .. "/plugins/stimulation/lua-stimulator-stim-codes.lua")
|
||||
|
||||
box:set_filter_mode(1);
|
||||
|
||||
state = 0
|
||||
|
||||
do_debug = false
|
||||
end
|
||||
|
||||
-- this function is called when the box is uninitialized
|
||||
function uninitialize(box)
|
||||
end
|
||||
|
||||
-- this function is called once by the box
|
||||
function process(box)
|
||||
|
||||
-- loop until box:keep_processing() returns zero
|
||||
-- cpu will be released with a call to sleep
|
||||
-- at the end of the loop
|
||||
while box:keep_processing() do
|
||||
|
||||
-- gets current simulated time
|
||||
t = box:get_current_time()
|
||||
|
||||
-- loops on every received stimulation for a given input
|
||||
for stimulation = 1, box:get_stimulation_count(1) do
|
||||
|
||||
-- gets stimulation
|
||||
stimulation_id, stimulation_time, stimulation_duration = box:get_stimulation(1, 1)
|
||||
|
||||
if stimulation_id == OVTK_StimulationId_SegmentStart then
|
||||
state = 1
|
||||
elseif stimulation_id == OVTK_StimulationId_SegmentStop then
|
||||
state = 0
|
||||
end
|
||||
|
||||
-- If we're between 'rest start' and 'rest_stop', this specifies a target
|
||||
if state == 1 and stimulation_id >= OVTK_StimulationId_LabelStart and stimulation_id <= OVTK_StimulationId_LabelEnd then
|
||||
|
||||
box:send_stimulation(1, stimulation_id, stimulation_time, 0)
|
||||
|
||||
if do_debug then
|
||||
box:log("Info", string.format("Push a target %d at %f (now %f)", stimulation_id, stimulation_time, t))
|
||||
end
|
||||
end
|
||||
|
||||
-- discards it
|
||||
box:remove_stimulation(1, 1)
|
||||
|
||||
end
|
||||
|
||||
-- releases cpu
|
||||
box:sleep()
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,61 @@
|
||||
|
||||
-- Picks out 'targets' from a stimulation stream
|
||||
|
||||
-- this function is called when the box is initialized
|
||||
function initialize(box)
|
||||
|
||||
dofile(box:get_config("${Path_Data}") .. "/plugins/stimulation/lua-stimulator-stim-codes.lua")
|
||||
|
||||
state = 0
|
||||
|
||||
box:set_filter_mode(1);
|
||||
|
||||
do_debug = false
|
||||
end
|
||||
|
||||
-- this function is called when the box is uninitialized
|
||||
function uninitialize(box)
|
||||
end
|
||||
|
||||
-- this function is called once by the box
|
||||
function process(box)
|
||||
|
||||
-- loop until box:keep_processing() returns zero
|
||||
-- cpu will be released with a call to sleep
|
||||
-- at the end of the loop
|
||||
while box:keep_processing() do
|
||||
|
||||
-- gets current simulated time
|
||||
t = box:get_current_time()
|
||||
|
||||
-- loops on every received stimulation for a given input
|
||||
for stimulation = 1, box:get_stimulation_count(1) do
|
||||
|
||||
-- gets stimulation
|
||||
stimulation_id, stimulation_time, stimulation_duration = box:get_stimulation(1, 1)
|
||||
|
||||
if stimulation_id == OVTK_StimulationId_RestStart then
|
||||
state = 1
|
||||
elseif stimulation_id == OVTK_StimulationId_RestStop then
|
||||
state = 0
|
||||
end
|
||||
|
||||
-- If we're between 'rest start' and 'rest_stop', this specifies a target
|
||||
if state == 1 and stimulation_id >= OVTK_StimulationId_LabelStart and stimulation_id <= OVTK_StimulationId_LabelEnd then
|
||||
|
||||
box:send_stimulation(1, stimulation_id, stimulation_time, 0)
|
||||
|
||||
if do_debug then
|
||||
box:log("Info", string.format("Push a target %d at %f (now = %f)", stimulation_id, stimulation_time, t))
|
||||
end
|
||||
end
|
||||
|
||||
-- discards it
|
||||
box:remove_stimulation(1, 1)
|
||||
|
||||
end
|
||||
|
||||
-- releases cpu
|
||||
box:sleep()
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,21 @@
|
||||
|
||||
-- this function is called when the box is initialized
|
||||
function initialize(box)
|
||||
|
||||
dofile(box:get_config("${Path_Data}") .. "/plugins/stimulation/lua-stimulator-stim-codes.lua")
|
||||
|
||||
stim = _G[box:get_setting(2)]
|
||||
launchTime = box:get_setting(3)
|
||||
|
||||
end
|
||||
|
||||
-- this function is called when the box is uninitialized
|
||||
function uninitialize(box)
|
||||
end
|
||||
|
||||
-- this function is called once by the box
|
||||
function process(box)
|
||||
|
||||
box:send_stimulation(1, stim, launchTime, 0)
|
||||
|
||||
end
|
||||
@@ -0,0 +1,138 @@
|
||||
-- This Lua script sends Stimulations to the speller visualization box for a tactile p300-System with 6 stimulators
|
||||
--
|
||||
-- Author : Tobias Baumann
|
||||
-- Date : 2021-12-06
|
||||
-- Revised: 2021-19-11
|
||||
|
||||
--This function lets the box sleep until a fixed moment
|
||||
function wait_until(box, time)
|
||||
while box:get_current_time() < time do
|
||||
box:sleep()
|
||||
end
|
||||
end
|
||||
|
||||
--This function lets the box wait for a fixed duration
|
||||
function wait_for(box, duration)
|
||||
wait_until(box, box:get_current_time() + duration)
|
||||
end
|
||||
|
||||
--this function checks, wether value already is an element of the given stim_matrix
|
||||
function is_element(matrix, value)
|
||||
for i = 1, #matrix do
|
||||
if #matrix == 0 then
|
||||
return(false)
|
||||
elseif value == matrix[i] then
|
||||
return(true)
|
||||
end
|
||||
end
|
||||
return(false)
|
||||
end
|
||||
--this function creates a sequence of stimulations by shuffeling the values of the given stim_matrix
|
||||
function create_sequence(matrix)
|
||||
local stim_matrix = {}
|
||||
local stim_code = 0
|
||||
local i = 1
|
||||
while i <= #matrix do
|
||||
stim_code = matrix[math.random(1,#matrix)]
|
||||
if is_element(stim_matrix, stim_code) == false then
|
||||
stim_matrix[i] = stim_code
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
return(stim_matrix)
|
||||
end
|
||||
|
||||
-- this function is called when the box is initialized
|
||||
function initialize(box)
|
||||
--randomseed
|
||||
math.randomseed(os.time())
|
||||
|
||||
--load stimulation codes
|
||||
dofile(box:get_config("${Path_Data}") .. "/plugins/stimulation/lua-stimulator-stim-codes.lua")
|
||||
|
||||
--load box settings
|
||||
row_base = _G[box:get_setting(2)]
|
||||
n_tactilos = box:get_setting(3)
|
||||
n_repetitions = box:get_setting(4)
|
||||
n_trials = box:get_setting(5)
|
||||
flash_duration = box:get_setting(6)
|
||||
noflash_duration = box:get_setting(7)
|
||||
inter_repetition_delay = box:get_setting(8)
|
||||
inter_trial_delay = box:get_setting(9)
|
||||
send_toggle = _G[box:get_setting(10)]
|
||||
free_spelling = box:get_setting(11)
|
||||
time_to_send = box:get_setting(12)
|
||||
|
||||
--Set number of trials to 1 in free spelling mode
|
||||
if free_spelling == 'true' then
|
||||
n_trials = 1
|
||||
end
|
||||
|
||||
--Lua variables
|
||||
send = false
|
||||
experiment_end = false
|
||||
tactilo_stimcodes = {}
|
||||
for x = 1, n_tactilos do
|
||||
tactilo_stimcodes[x] = row_base + x - 1
|
||||
end
|
||||
end
|
||||
|
||||
-- this function is called when the box is uninitialized
|
||||
function uninitialize(box)
|
||||
|
||||
end
|
||||
|
||||
-- this function is called once by the box
|
||||
function process(box)
|
||||
while box:keep_processing() do
|
||||
|
||||
if send and not experiment_end then
|
||||
-- iterate over the number of trials
|
||||
for trial = 1, n_trials do
|
||||
box:send_stimulation(1, OVTK_StimulationId_RestStart, box:get_current_time() , 0)
|
||||
wait_for(box, inter_trial_delay)
|
||||
box:send_stimulation(1, OVTK_StimulationId_RestStop, box:get_current_time() , 0)
|
||||
box:send_stimulation(1, OVTK_StimulationId_TrialStart ,box:get_current_time() , 0)
|
||||
|
||||
-- iterate over the number of repetitions
|
||||
for segment = 1, n_repetitions do
|
||||
tactilo_stimcodes = create_sequence(tactilo_stimcodes)
|
||||
box:send_stimulation(1, OVTK_StimulationId_SegmentStart ,box:get_current_time() , 0)
|
||||
|
||||
-- iterate over the number of tactilos
|
||||
for i = 1, #tactilo_stimcodes do
|
||||
box:send_stimulation(1, tactilo_stimcodes[i] ,box:get_current_time() , 0)
|
||||
box:send_stimulation(1, OVTK_StimulationId_VisualStimulationStart ,box:get_current_time() , 0)
|
||||
wait_for(box, flash_duration)
|
||||
box:send_stimulation(1, OVTK_StimulationId_VisualStimulationStop ,box:get_current_time() , 0)
|
||||
wait_for(box, noflash_duration)
|
||||
end
|
||||
|
||||
box:send_stimulation(1, OVTK_StimulationId_SegmentStop ,box:get_current_time() , 0)
|
||||
wait_for(box, inter_repetition_delay)
|
||||
end
|
||||
|
||||
box:send_stimulation(1, OVTK_StimulationId_TrialStop ,box:get_current_time() , 0)
|
||||
|
||||
end
|
||||
|
||||
if free_spelling == 'false' then
|
||||
-- end experiment if set to copy spelling
|
||||
box:send_stimulation(1, OVTK_StimulationId_ExperimentStop ,box:get_current_time() , 0)
|
||||
send = false
|
||||
experiment_end = true
|
||||
end
|
||||
|
||||
else if not send and not experiment_end then
|
||||
-- delay the start of the experiment by t = time_to_send
|
||||
wait_for(box, time_to_send)
|
||||
send = true
|
||||
box:send_stimulation(1, OVTK_StimulationId_ExperimentStart ,box:get_current_time() , 0)
|
||||
end
|
||||
|
||||
end
|
||||
-- releases cpu
|
||||
box:sleep()
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,61 @@
|
||||
-- This Lua script generates target stimulations the 1x6 p300-tactile matrix
|
||||
--
|
||||
-- Author : Tobias Baumann
|
||||
-- Date : 2021-06-09
|
||||
|
||||
-- this function is called when the box is initialized
|
||||
function initialize(box)
|
||||
|
||||
dofile(box:get_config("${Path_Data}") .. "/plugins/stimulation/lua-stimulator-stim-codes.lua")
|
||||
|
||||
math.randomseed(os.time())
|
||||
row_base = _G[box:get_setting(2)]
|
||||
n_tactilos = box:get_setting(3)
|
||||
delay = box:get_setting(4)
|
||||
free_spelling = box:get_setting(5)
|
||||
|
||||
end
|
||||
|
||||
-- this function is called when the box is uninitialized
|
||||
function uninitialize(box)
|
||||
end
|
||||
|
||||
-- this function is called once by the box
|
||||
function process(box)
|
||||
|
||||
-- loop until box:keep_processing() returns zero
|
||||
-- cpu will be released with a call to sleep
|
||||
-- at the end of the loop
|
||||
while box:keep_processing() do
|
||||
|
||||
-- gets current simulated time
|
||||
t = box:get_current_time()
|
||||
|
||||
-- loops on every received stimulation for a given input
|
||||
for stimulation = 1, box:get_stimulation_count(1) do
|
||||
|
||||
-- gets stimulation
|
||||
stimulation_id, stimulation_time, stimulation_duration = box:get_stimulation(1, 1)
|
||||
|
||||
if free_spelling == 'false' then
|
||||
if stimulation_id == OVTK_StimulationId_RestStart then
|
||||
|
||||
-- triggers the target
|
||||
box:send_stimulation(1, row_base+math.random(1,n_tactilos)-1, t+delay, 0)
|
||||
|
||||
elseif stimulation_id == OVTK_StimulationId_ExperimentStop then
|
||||
|
||||
-- triggers train stimulation
|
||||
box:send_stimulation(1, OVTK_StimulationId_Train, t+delay+1, 0)
|
||||
|
||||
end
|
||||
end
|
||||
-- discards it
|
||||
box:remove_stimulation(1, 1)
|
||||
|
||||
end
|
||||
|
||||
-- releases cpu
|
||||
box:sleep()
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,3 @@
|
||||
|
||||
The scenario will record its signals here.
|
||||
|
||||
@@ -0,0 +1,321 @@
|
||||
<?xml version="1.0"?>
|
||||
<interface>
|
||||
<!-- interface-requires gtk+ 2.12 -->
|
||||
<!-- interface-naming-policy toplevel-contextual -->
|
||||
<object class="GtkWindow" id="p300-tactile">
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<child>
|
||||
<object class="GtkTable" id="p300-tactile-main">
|
||||
<property name="visible">True</property>
|
||||
<property name="n_rows">3</property>
|
||||
<property name="row_spacing">4</property>
|
||||
<child>
|
||||
<object class="GtkTable" id="p300-tactile-table">
|
||||
<property name="visible">True</property>
|
||||
<property name="n_rows">10</property>
|
||||
<property name="n_columns">1</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-1">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo1</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-2">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-2">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo2</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-3">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-3">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo3</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-4">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-4">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo4</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="bottom_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-5">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-5">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo5</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">4</property>
|
||||
<property name="bottom_attach">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-6">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-6">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo6</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">5</property>
|
||||
<property name="bottom_attach">6</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-7">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-7">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo7</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">6</property>
|
||||
<property name="bottom_attach">7</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-8">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-8">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo8</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">7</property>
|
||||
<property name="bottom_attach">8</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-9">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-9">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo9</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">8</property>
|
||||
<property name="bottom_attach">9</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-10">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-10">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo10</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">9</property>
|
||||
<property name="bottom_attach">10</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTable" id="p300-tactile-table-target-result">
|
||||
<property name="visible">True</property>
|
||||
<property name="n_rows">2</property>
|
||||
<property name="n_columns">3</property>
|
||||
<property name="column_spacing">4</property>
|
||||
<property name="row_spacing">4</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-result">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="right_attach">3</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-target">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="right_attach">3</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-result-title">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Result :</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-target-title">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Target :</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImage" id="image">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock">gtk-select-font</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options"></property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkHSeparator" id="hseparator">
|
||||
<property name="visible">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkWindow" id="p300-tactile-toolbar">
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="title" translatable="yes">P300 tactile</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
<child>
|
||||
<object class="GtkToolbar" id="toolbar">
|
||||
<property name="width_request">640</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="toolbar_style">both</property>
|
||||
<child>
|
||||
<object class="GtkToggleToolButton" id="toolbutton-show_target_text">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Show Target Text</property>
|
||||
<property name="stock_id">gtk-info</property>
|
||||
<property name="active">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToggleToolButton" id="toolbutton-show_result_text">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Show Result Text</property>
|
||||
<property name="stock_id">gtk-info</property>
|
||||
<property name="active">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
@@ -0,0 +1,185 @@
|
||||
<?xml version="1.0"?>
|
||||
<interface>
|
||||
<!-- interface-requires gtk+ 2.12 -->
|
||||
<!-- interface-naming-policy toplevel-contextual -->
|
||||
<object class="GtkWindow" id="p300-tactile">
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<child>
|
||||
<object class="GtkTable" id="p300-tactile-main">
|
||||
<property name="visible">True</property>
|
||||
<property name="n_rows">3</property>
|
||||
<property name="row_spacing">4</property>
|
||||
<child>
|
||||
<object class="GtkTable" id="p300-tactile-table">
|
||||
<property name="visible">True</property>
|
||||
<property name="n_rows">2</property>
|
||||
<property name="n_columns">1</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-1">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo1</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-2">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-2">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo2</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTable" id="p300-tactile-table-target-result">
|
||||
<property name="visible">True</property>
|
||||
<property name="n_rows">2</property>
|
||||
<property name="n_columns">3</property>
|
||||
<property name="column_spacing">4</property>
|
||||
<property name="row_spacing">4</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-result">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="right_attach">3</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-target">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="right_attach">3</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-result-title">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Result :</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-target-title">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Target :</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImage" id="image">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock">gtk-select-font</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options"></property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkHSeparator" id="hseparator">
|
||||
<property name="visible">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkWindow" id="p300-tactile-toolbar">
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="title" translatable="yes">P300 tactile</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
<child>
|
||||
<object class="GtkToolbar" id="toolbar">
|
||||
<property name="width_request">640</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="toolbar_style">both</property>
|
||||
<child>
|
||||
<object class="GtkToggleToolButton" id="toolbutton-show_target_text">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Show Target Text</property>
|
||||
<property name="stock_id">gtk-info</property>
|
||||
<property name="active">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToggleToolButton" id="toolbutton-show_result_text">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Show Result Text</property>
|
||||
<property name="stock_id">gtk-info</property>
|
||||
<property name="active">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
@@ -0,0 +1,202 @@
|
||||
<?xml version="1.0"?>
|
||||
<interface>
|
||||
<!-- interface-requires gtk+ 2.12 -->
|
||||
<!-- interface-naming-policy toplevel-contextual -->
|
||||
<object class="GtkWindow" id="p300-tactile">
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<child>
|
||||
<object class="GtkTable" id="p300-tactile-main">
|
||||
<property name="visible">True</property>
|
||||
<property name="n_rows">3</property>
|
||||
<property name="row_spacing">4</property>
|
||||
<child>
|
||||
<object class="GtkTable" id="p300-tactile-table">
|
||||
<property name="visible">True</property>
|
||||
<property name="n_rows">3</property>
|
||||
<property name="n_columns">1</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-1">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo1</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-2">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-2">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo2</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-3">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-3">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo3</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTable" id="p300-tactile-table-target-result">
|
||||
<property name="visible">True</property>
|
||||
<property name="n_rows">2</property>
|
||||
<property name="n_columns">3</property>
|
||||
<property name="column_spacing">4</property>
|
||||
<property name="row_spacing">4</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-result">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="right_attach">3</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-target">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="right_attach">3</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-result-title">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Result :</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-target-title">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Target :</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImage" id="image">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock">gtk-select-font</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options"></property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkHSeparator" id="hseparator">
|
||||
<property name="visible">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkWindow" id="p300-tactile-toolbar">
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="title" translatable="yes">P300 tactile</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
<child>
|
||||
<object class="GtkToolbar" id="toolbar">
|
||||
<property name="width_request">640</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="toolbar_style">both</property>
|
||||
<child>
|
||||
<object class="GtkToggleToolButton" id="toolbutton-show_target_text">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Show Target Text</property>
|
||||
<property name="stock_id">gtk-info</property>
|
||||
<property name="active">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToggleToolButton" id="toolbutton-show_result_text">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Show Result Text</property>
|
||||
<property name="stock_id">gtk-info</property>
|
||||
<property name="active">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
@@ -0,0 +1,219 @@
|
||||
<?xml version="1.0"?>
|
||||
<interface>
|
||||
<!-- interface-requires gtk+ 2.12 -->
|
||||
<!-- interface-naming-policy toplevel-contextual -->
|
||||
<object class="GtkWindow" id="p300-tactile">
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<child>
|
||||
<object class="GtkTable" id="p300-tactile-main">
|
||||
<property name="visible">True</property>
|
||||
<property name="n_rows">3</property>
|
||||
<property name="row_spacing">4</property>
|
||||
<child>
|
||||
<object class="GtkTable" id="p300-tactile-table">
|
||||
<property name="visible">True</property>
|
||||
<property name="n_rows">4</property>
|
||||
<property name="n_columns">1</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-1">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo1</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-2">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-2">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo2</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-3">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-3">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo3</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-4">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-4">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo4</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="bottom_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTable" id="p300-tactile-table-target-result">
|
||||
<property name="visible">True</property>
|
||||
<property name="n_rows">2</property>
|
||||
<property name="n_columns">3</property>
|
||||
<property name="column_spacing">4</property>
|
||||
<property name="row_spacing">4</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-result">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="right_attach">3</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-target">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="right_attach">3</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-result-title">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Result :</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-target-title">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Target :</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImage" id="image">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock">gtk-select-font</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options"></property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkHSeparator" id="hseparator">
|
||||
<property name="visible">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkWindow" id="p300-tactile-toolbar">
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="title" translatable="yes">P300 tactile</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
<child>
|
||||
<object class="GtkToolbar" id="toolbar">
|
||||
<property name="width_request">640</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="toolbar_style">both</property>
|
||||
<child>
|
||||
<object class="GtkToggleToolButton" id="toolbutton-show_target_text">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Show Target Text</property>
|
||||
<property name="stock_id">gtk-info</property>
|
||||
<property name="active">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToggleToolButton" id="toolbutton-show_result_text">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Show Result Text</property>
|
||||
<property name="stock_id">gtk-info</property>
|
||||
<property name="active">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
@@ -0,0 +1,235 @@
|
||||
<?xml version="1.0"?>
|
||||
<interface>
|
||||
<!-- interface-requires gtk+ 2.12 -->
|
||||
<!-- interface-naming-policy toplevel-contextual -->
|
||||
<object class="GtkWindow" id="p300-tactile">
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<child>
|
||||
<object class="GtkTable" id="p300-tactile-main">
|
||||
<property name="visible">True</property>
|
||||
<property name="n_rows">3</property>
|
||||
<property name="row_spacing">4</property>
|
||||
<child>
|
||||
<object class="GtkTable" id="p300-tactile-table">
|
||||
<property name="visible">True</property>
|
||||
<property name="n_rows">5</property>
|
||||
<property name="n_columns">1</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-1">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo1</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-2">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-2">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo2</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-3">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-3">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo3</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-4">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-4">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo4</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="bottom_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-5">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-5">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo5</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">4</property>
|
||||
<property name="bottom_attach">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTable" id="p300-tactile-table-target-result">
|
||||
<property name="visible">True</property>
|
||||
<property name="n_rows">2</property>
|
||||
<property name="n_columns">3</property>
|
||||
<property name="column_spacing">4</property>
|
||||
<property name="row_spacing">4</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-result">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="right_attach">3</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-target">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="right_attach">3</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-result-title">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Result :</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-target-title">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Target :</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImage" id="image">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock">gtk-select-font</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options"></property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkHSeparator" id="hseparator">
|
||||
<property name="visible">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkWindow" id="p300-tactile-toolbar">
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="title" translatable="yes">P300 tactile</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
<child>
|
||||
<object class="GtkToolbar" id="toolbar">
|
||||
<property name="width_request">640</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="toolbar_style">both</property>
|
||||
<child>
|
||||
<object class="GtkToggleToolButton" id="toolbutton-show_target_text">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Show Target Text</property>
|
||||
<property name="stock_id">gtk-info</property>
|
||||
<property name="active">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToggleToolButton" id="toolbutton-show_result_text">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Show Result Text</property>
|
||||
<property name="stock_id">gtk-info</property>
|
||||
<property name="active">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
@@ -0,0 +1,253 @@
|
||||
<?xml version="1.0"?>
|
||||
<interface>
|
||||
<!-- interface-requires gtk+ 2.12 -->
|
||||
<!-- interface-naming-policy toplevel-contextual -->
|
||||
<object class="GtkWindow" id="p300-tactile">
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<child>
|
||||
<object class="GtkTable" id="p300-tactile-main">
|
||||
<property name="visible">True</property>
|
||||
<property name="n_rows">3</property>
|
||||
<property name="row_spacing">4</property>
|
||||
<child>
|
||||
<object class="GtkTable" id="p300-tactile-table">
|
||||
<property name="visible">True</property>
|
||||
<property name="n_rows">6</property>
|
||||
<property name="n_columns">1</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-1">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo1</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-2">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-2">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo2</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-3">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-3">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo3</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-4">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-4">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo4</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="bottom_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-5">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-5">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo5</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">4</property>
|
||||
<property name="bottom_attach">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-6">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-6">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo6</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">5</property>
|
||||
<property name="bottom_attach">6</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTable" id="p300-tactile-table-target-result">
|
||||
<property name="visible">True</property>
|
||||
<property name="n_rows">2</property>
|
||||
<property name="n_columns">3</property>
|
||||
<property name="column_spacing">4</property>
|
||||
<property name="row_spacing">4</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-result">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="right_attach">3</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-target">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="right_attach">3</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-result-title">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Result :</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-target-title">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Target :</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImage" id="image">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock">gtk-select-font</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options"></property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkHSeparator" id="hseparator">
|
||||
<property name="visible">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkWindow" id="p300-tactile-toolbar">
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="title" translatable="yes">P300 tactile</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
<child>
|
||||
<object class="GtkToolbar" id="toolbar">
|
||||
<property name="width_request">640</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="toolbar_style">both</property>
|
||||
<child>
|
||||
<object class="GtkToggleToolButton" id="toolbutton-show_target_text">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Show Target Text</property>
|
||||
<property name="stock_id">gtk-info</property>
|
||||
<property name="active">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToggleToolButton" id="toolbutton-show_result_text">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Show Result Text</property>
|
||||
<property name="stock_id">gtk-info</property>
|
||||
<property name="active">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
@@ -0,0 +1,270 @@
|
||||
<?xml version="1.0"?>
|
||||
<interface>
|
||||
<!-- interface-requires gtk+ 2.12 -->
|
||||
<!-- interface-naming-policy toplevel-contextual -->
|
||||
<object class="GtkWindow" id="p300-tactile">
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<child>
|
||||
<object class="GtkTable" id="p300-tactile-main">
|
||||
<property name="visible">True</property>
|
||||
<property name="n_rows">3</property>
|
||||
<property name="row_spacing">4</property>
|
||||
<child>
|
||||
<object class="GtkTable" id="p300-tactile-table">
|
||||
<property name="visible">True</property>
|
||||
<property name="n_rows">7</property>
|
||||
<property name="n_columns">1</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-1">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo1</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-2">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-2">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo2</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-3">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-3">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo3</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-4">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-4">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo4</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="bottom_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-5">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-5">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo5</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">4</property>
|
||||
<property name="bottom_attach">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-6">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-6">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo6</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">5</property>
|
||||
<property name="bottom_attach">6</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-7">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-7">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo7</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">6</property>
|
||||
<property name="bottom_attach">7</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTable" id="p300-tactile-table-target-result">
|
||||
<property name="visible">True</property>
|
||||
<property name="n_rows">2</property>
|
||||
<property name="n_columns">3</property>
|
||||
<property name="column_spacing">4</property>
|
||||
<property name="row_spacing">4</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-result">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="right_attach">3</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-target">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="right_attach">3</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-result-title">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Result :</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-target-title">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Target :</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImage" id="image">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock">gtk-select-font</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options"></property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkHSeparator" id="hseparator">
|
||||
<property name="visible">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkWindow" id="p300-tactile-toolbar">
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="title" translatable="yes">P300 tactile</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
<child>
|
||||
<object class="GtkToolbar" id="toolbar">
|
||||
<property name="width_request">640</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="toolbar_style">both</property>
|
||||
<child>
|
||||
<object class="GtkToggleToolButton" id="toolbutton-show_target_text">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Show Target Text</property>
|
||||
<property name="stock_id">gtk-info</property>
|
||||
<property name="active">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToggleToolButton" id="toolbutton-show_result_text">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Show Result Text</property>
|
||||
<property name="stock_id">gtk-info</property>
|
||||
<property name="active">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
@@ -0,0 +1,287 @@
|
||||
<?xml version="1.0"?>
|
||||
<interface>
|
||||
<!-- interface-requires gtk+ 2.12 -->
|
||||
<!-- interface-naming-policy toplevel-contextual -->
|
||||
<object class="GtkWindow" id="p300-tactile">
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<child>
|
||||
<object class="GtkTable" id="p300-tactile-main">
|
||||
<property name="visible">True</property>
|
||||
<property name="n_rows">3</property>
|
||||
<property name="row_spacing">4</property>
|
||||
<child>
|
||||
<object class="GtkTable" id="p300-tactile-table">
|
||||
<property name="visible">True</property>
|
||||
<property name="n_rows">8</property>
|
||||
<property name="n_columns">1</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-1">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo1</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-2">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-2">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo2</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-3">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-3">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo3</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-4">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-4">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo4</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="bottom_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-5">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-5">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo5</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">4</property>
|
||||
<property name="bottom_attach">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-6">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-6">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo6</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">5</property>
|
||||
<property name="bottom_attach">6</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-7">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-7">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo7</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">6</property>
|
||||
<property name="bottom_attach">7</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-8">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-8">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo8</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">7</property>
|
||||
<property name="bottom_attach">8</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTable" id="p300-tactile-table-target-result">
|
||||
<property name="visible">True</property>
|
||||
<property name="n_rows">2</property>
|
||||
<property name="n_columns">3</property>
|
||||
<property name="column_spacing">4</property>
|
||||
<property name="row_spacing">4</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-result">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="right_attach">3</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-target">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="right_attach">3</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-result-title">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Result :</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-target-title">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Target :</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImage" id="image">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock">gtk-select-font</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options"></property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkHSeparator" id="hseparator">
|
||||
<property name="visible">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkWindow" id="p300-tactile-toolbar">
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="title" translatable="yes">P300 tactile</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
<child>
|
||||
<object class="GtkToolbar" id="toolbar">
|
||||
<property name="width_request">640</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="toolbar_style">both</property>
|
||||
<child>
|
||||
<object class="GtkToggleToolButton" id="toolbutton-show_target_text">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Show Target Text</property>
|
||||
<property name="stock_id">gtk-info</property>
|
||||
<property name="active">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToggleToolButton" id="toolbutton-show_result_text">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Show Result Text</property>
|
||||
<property name="stock_id">gtk-info</property>
|
||||
<property name="active">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
@@ -0,0 +1,304 @@
|
||||
<?xml version="1.0"?>
|
||||
<interface>
|
||||
<!-- interface-requires gtk+ 2.12 -->
|
||||
<!-- interface-naming-policy toplevel-contextual -->
|
||||
<object class="GtkWindow" id="p300-tactile">
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<child>
|
||||
<object class="GtkTable" id="p300-tactile-main">
|
||||
<property name="visible">True</property>
|
||||
<property name="n_rows">3</property>
|
||||
<property name="row_spacing">4</property>
|
||||
<child>
|
||||
<object class="GtkTable" id="p300-tactile-table">
|
||||
<property name="visible">True</property>
|
||||
<property name="n_rows">9</property>
|
||||
<property name="n_columns">1</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-1">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo1</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-2">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-2">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo2</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-3">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-3">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo3</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-4">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-4">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo4</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="bottom_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-5">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-5">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo5</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">4</property>
|
||||
<property name="bottom_attach">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-6">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-6">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo6</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">5</property>
|
||||
<property name="bottom_attach">6</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-7">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-7">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo7</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">6</property>
|
||||
<property name="bottom_attach">7</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-8">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-8">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo8</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">7</property>
|
||||
<property name="bottom_attach">8</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox-9">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-9">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Tactilo9</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">8</property>
|
||||
<property name="bottom_attach">9</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTable" id="p300-tactile-table-target-result">
|
||||
<property name="visible">True</property>
|
||||
<property name="n_rows">2</property>
|
||||
<property name="n_columns">3</property>
|
||||
<property name="column_spacing">4</property>
|
||||
<property name="row_spacing">4</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-result">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="right_attach">3</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-target">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="right_attach">3</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-result-title">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Result :</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-target-title">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Target :</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImage" id="image">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock">gtk-select-font</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options"></property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkHSeparator" id="hseparator">
|
||||
<property name="visible">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkWindow" id="p300-tactile-toolbar">
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="title" translatable="yes">P300 tactile</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
<child>
|
||||
<object class="GtkToolbar" id="toolbar">
|
||||
<property name="width_request">640</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="toolbar_style">both</property>
|
||||
<child>
|
||||
<object class="GtkToggleToolButton" id="toolbutton-show_target_text">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Show Target Text</property>
|
||||
<property name="stock_id">gtk-info</property>
|
||||
<property name="active">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToggleToolButton" id="toolbutton-show_result_text">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Show Result Text</property>
|
||||
<property name="stock_id">gtk-info</property>
|
||||
<property name="active">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
@@ -1,7 +0,0 @@
|
||||
sudo apt-get install python-tk
|
||||
sudo apt-get install xdotool
|
||||
|
||||
sudo apt-get install python-setuptools
|
||||
sudo apt-get install python-pip
|
||||
|
||||
pip install pyinstaller==3.6
|
||||
@@ -0,0 +1,52 @@
|
||||
///-------------------------------------------------------------------------------------------------
|
||||
///
|
||||
/// \file TactileMenu.cpp
|
||||
/// \brief Definitions for class TactileMenu
|
||||
/// \author Tobias Baumann (TH Nuernberg).
|
||||
/// \version 1.0.
|
||||
/// \date Mon Feb 10 17:11:34 2022.
|
||||
/// \copyright <a href="https://choosealicense.com/licenses/agpl-3.0/">GNU Affero General Public License v3.0</a>.
|
||||
///
|
||||
///-------------------------------------------------------------------------------------------------
|
||||
|
||||
//includes
|
||||
#include "TactileMenu.h"
|
||||
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Tactilebci {
|
||||
|
||||
//TactileMenu Memberfunctions
|
||||
TactileMenu::TactileMenu(int n_Tactilos)
|
||||
{
|
||||
for(int i = 1; i <= n_Tactilos; i++)
|
||||
{
|
||||
m_LabelText.push_back("Tactilo" + std::to_string(i));
|
||||
m_SubMenu.push_back(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void TactileMenu::set_LabelText(int i, std::string Text)
|
||||
{
|
||||
m_LabelText[i] = Text;
|
||||
}
|
||||
|
||||
void TactileMenu::set_SubMenu(int i, TactileMenu* Menu)
|
||||
{
|
||||
m_SubMenu[i] = Menu;
|
||||
}
|
||||
|
||||
std::string TactileMenu::get_LabelText(int i)
|
||||
{
|
||||
return(m_LabelText[i]);
|
||||
}
|
||||
|
||||
TactileMenu* TactileMenu::get_SubMenu(int i)
|
||||
{
|
||||
return(m_SubMenu[i]);
|
||||
}
|
||||
|
||||
} // namespace Tactilebci
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
@@ -0,0 +1,46 @@
|
||||
///-------------------------------------------------------------------------------------------------
|
||||
///
|
||||
/// \file TactileMenu.h
|
||||
/// \brief Class for the Menues of the Tactile P300 System
|
||||
/// \author Tobias Baumann (TH Nuernberg).
|
||||
/// \version 1.0.
|
||||
/// \date Mon Feb 10 17:10:32 2022.
|
||||
/// \copyright <a href="https://choosealicense.com/licenses/agpl-3.0/">GNU Affero General Public License v3.0</a>.
|
||||
///
|
||||
///-------------------------------------------------------------------------------------------------
|
||||
//includes
|
||||
#pragma once
|
||||
|
||||
#include "../ovp_defines.h"
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <openvibe/ov_all.h>
|
||||
#include <toolkit/ovtk_all.h>
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Tactilebci {
|
||||
|
||||
//Class TactileMenu
|
||||
class TactileMenu
|
||||
{
|
||||
private:
|
||||
std::vector<std::string> m_LabelText;
|
||||
std::vector<TactileMenu*> m_SubMenu;
|
||||
|
||||
public:
|
||||
TactileMenu(int n_Tactilos);
|
||||
|
||||
std::string get_LabelText(int i);
|
||||
TactileMenu* get_SubMenu(int i);
|
||||
|
||||
void set_LabelText(int i, std::string Text);
|
||||
void set_SubMenu(int i, TactileMenu* Menu);
|
||||
};
|
||||
|
||||
} // namespace Tactilebci
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
@@ -0,0 +1,480 @@
|
||||
#include "ovpCBoxAlgorithmP300TactileVisualization.h"
|
||||
|
||||
using namespace OpenViBE;
|
||||
using namespace /*OpenViBE::*/Kernel;
|
||||
using namespace /*OpenViBE::*/Plugins;
|
||||
using namespace /*OpenViBE::Plugins::*/Tactilebci;
|
||||
|
||||
// This callback flushes all accumulated stimulations to the TCP Tagging
|
||||
// after the rendering has completed.
|
||||
static gboolean FlushCB(gpointer data)
|
||||
{
|
||||
(static_cast<CBoxAlgorithmP300TactileVisualization*>(data))->flushQueue();
|
||||
|
||||
return false; // Only run once
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmP300TactileVisualization::initialize()
|
||||
{
|
||||
// ------ Init decoder/encoder
|
||||
m_SequenceInputDecoder.initialize(*this, 0);
|
||||
m_TargetInputDecoder.initialize(*this, 1);
|
||||
m_ResultInputDecoder.initialize(*this, 2);
|
||||
m_ResultOutputEncoder.initialize(*this, 0);
|
||||
|
||||
// ------ Get box settings
|
||||
m_InterfaceFilename = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 0);
|
||||
m_RowBase = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 1);
|
||||
m_nTactilos = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 2);
|
||||
m_FreeSpelling = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 3);
|
||||
|
||||
//set m_nTactilos minimum number of 2, if lower
|
||||
if(m_nTactilos < 2)
|
||||
{
|
||||
m_nTactilos = 2;
|
||||
}
|
||||
|
||||
//set m_nTactilos maximum number of MAX_TACTILOS(10), if higher
|
||||
if(m_nTactilos > MAX_TACTILOS)
|
||||
{
|
||||
m_nTactilos = MAX_TACTILOS;
|
||||
}
|
||||
|
||||
// ------ Setup acquisition server TCP tagging
|
||||
m_stimuliQueue.clear();
|
||||
m_stimulusSender = TCPTagging::CreateStimulusSender();
|
||||
if(!m_stimulusSender->connect("localhost", "15361"))
|
||||
{
|
||||
this->getLogManager() << LogLevel_Warning << "Failed to connect to acquisition server TCP tagging.\n";
|
||||
}
|
||||
|
||||
// ------ Gtk variables
|
||||
// Build main UI elements
|
||||
m_MainWidgetInterface = gtk_builder_new();
|
||||
if(!gtk_builder_add_from_file(m_MainWidgetInterface, m_InterfaceFilename.toASCIIString(), nullptr))//error
|
||||
{
|
||||
this->getLogManager() << LogLevel_ImportantWarning << "Failed to load UI file [" << m_InterfaceFilename << "]\n";
|
||||
this->getLogManager() << LogLevel_ImportantWarning << "Make sure, that the given filename and path are correct\n";
|
||||
return(false);
|
||||
}
|
||||
m_MainWindow = GTK_WIDGET(gtk_builder_get_object(m_MainWidgetInterface, "p300-tactile-main"));
|
||||
m_Table = GTK_TABLE(gtk_builder_get_object(m_MainWidgetInterface, "p300-tactile-table"));
|
||||
m_ResultLabel = GTK_LABEL(gtk_builder_get_object(m_MainWidgetInterface, "label-result"));
|
||||
m_TargetLabel = GTK_LABEL(gtk_builder_get_object(m_MainWidgetInterface, "label-target"));
|
||||
|
||||
// Create font description
|
||||
m_FontDesc = pango_font_description_copy(pango_context_get_font_description(gtk_widget_get_pango_context(m_MainWindow)));
|
||||
pango_font_description_set_size(m_FontDesc, gint(FontSize*PANGO_SCALE));
|
||||
|
||||
// test if the UI-file fits the number of tactilos
|
||||
guint nRow = 0;
|
||||
g_object_get(m_Table, "n-rows", &nRow, nullptr);
|
||||
if(m_nTactilos != nRow)
|
||||
{
|
||||
this->getLogManager() << LogLevel_ImportantWarning << "The number of tactilos " << m_nTactilos<<" used and the number of rows "<< nRow << " in the ui file must be the same.\n";
|
||||
this->getLogManager() << LogLevel_ImportantWarning << "Make sure to choose the right UI-File, e.g. p300-tactile-6.ui for 6 tactilos\n";
|
||||
return(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(uint64_t i = 0; i < m_nTactilos; i++)
|
||||
{
|
||||
std::string eventbox_id = "eventbox-" + std::to_string(i+1);
|
||||
|
||||
m_EventBox.push_back(GTK_WIDGET(gtk_builder_get_object(m_MainWidgetInterface, eventbox_id.c_str())));
|
||||
}
|
||||
}
|
||||
|
||||
// ------ Setup tactile UI
|
||||
//Create UI for m_nTactilos = 6
|
||||
if(m_nTactilos == 6)
|
||||
{
|
||||
//create free spelling UI for 6 tactilos
|
||||
if(m_FreeSpelling)
|
||||
{
|
||||
//mainmenu
|
||||
m_Menu.push_back(TactileMenu(6));
|
||||
m_Menu[0].set_LabelText(0, "Ja");
|
||||
m_Menu[0].set_LabelText(1, "Nein");
|
||||
m_Menu[0].set_LabelText(2, "Geräte");
|
||||
m_Menu[0].set_LabelText(3, "Körper");
|
||||
m_Menu[0].set_LabelText(4, "Hilfe");
|
||||
m_Menu[0].set_LabelText(5, "Schmerzen");
|
||||
//submenu Geräte
|
||||
m_Menu.push_back(TactileMenu(6));
|
||||
m_Menu[1].set_LabelText(0, "Ja");
|
||||
m_Menu[1].set_LabelText(1, "Nein");
|
||||
m_Menu[1].set_LabelText(2, "Atemgerät");
|
||||
m_Menu[1].set_LabelText(3, "Computer");
|
||||
m_Menu[1].set_LabelText(4, "Rollstuhl");
|
||||
m_Menu[1].set_LabelText(5, "Hauptmenü");
|
||||
//submenu Körper
|
||||
m_Menu.push_back(TactileMenu(6));
|
||||
m_Menu[2].set_LabelText(0, "Ja");
|
||||
m_Menu[2].set_LabelText(1, "Nein");
|
||||
m_Menu[2].set_LabelText(2, "Hunger/Durst");
|
||||
m_Menu[2].set_LabelText(3, "warm/kalt");
|
||||
m_Menu[2].set_LabelText(4, "Müdigkeit");
|
||||
m_Menu[2].set_LabelText(5, "Hauptmenü");
|
||||
//submenu Hilfe
|
||||
m_Menu.push_back(TactileMenu(6));
|
||||
m_Menu[3].set_LabelText(0, "Ja");
|
||||
m_Menu[3].set_LabelText(1, "Nein");
|
||||
m_Menu[3].set_LabelText(2, "Lage");
|
||||
m_Menu[3].set_LabelText(3, "Atemnot");
|
||||
m_Menu[3].set_LabelText(4, "Anderes Problem");
|
||||
m_Menu[3].set_LabelText(5, "Hauptmenü");
|
||||
//submenu Schmerzen
|
||||
m_Menu.push_back(TactileMenu(6));
|
||||
m_Menu[3].set_LabelText(0, "Ja");
|
||||
m_Menu[3].set_LabelText(1, "Nein");
|
||||
m_Menu[3].set_LabelText(2, "Kopf");
|
||||
m_Menu[3].set_LabelText(3, "Torso");
|
||||
m_Menu[3].set_LabelText(4, "Glieder");
|
||||
m_Menu[3].set_LabelText(5, "Hauptmenü");
|
||||
|
||||
//set SubMenu ptr
|
||||
m_Menu[0].set_SubMenu(2, &m_Menu[1]);//main --> Geräte
|
||||
m_Menu[0].set_SubMenu(3, &m_Menu[2]);//main --> Körper
|
||||
m_Menu[0].set_SubMenu(4, &m_Menu[3]);//main --> Hilfe
|
||||
m_Menu[0].set_SubMenu(5, &m_Menu[4]);//main --> Schmerzen
|
||||
m_Menu[1].set_SubMenu(5, &m_Menu[0]);//Geräte --> main
|
||||
m_Menu[2].set_SubMenu(5, &m_Menu[0]);//Körper --> main
|
||||
m_Menu[3].set_SubMenu(5, &m_Menu[0]);//Hilfe --> main
|
||||
m_Menu[3].set_SubMenu(5, &m_Menu[0]);//Schmerzen --> main
|
||||
|
||||
//set curr Menu ptr to main menu
|
||||
m_CurrMenu = &m_Menu[0];
|
||||
}
|
||||
//create copy spelling UI for 6 tactilos
|
||||
else
|
||||
{
|
||||
m_Menu.push_back(TactileMenu(6));
|
||||
m_Menu[0].set_LabelText(0, "Bein links");
|
||||
m_Menu[0].set_LabelText(1, "Bein rechts");
|
||||
m_Menu[0].set_LabelText(2, "Arm links");
|
||||
m_Menu[0].set_LabelText(3, "Arm rechts");
|
||||
m_Menu[0].set_LabelText(4, "Brust");
|
||||
m_Menu[0].set_LabelText(5, "Rücken");
|
||||
|
||||
m_CurrMenu = &m_Menu[0];
|
||||
}
|
||||
}
|
||||
//Create default UI for m_nTactilos != 6
|
||||
else
|
||||
{
|
||||
m_Menu.push_back(TactileMenu(m_nTactilos));
|
||||
m_CurrMenu = &m_Menu[0];
|
||||
}
|
||||
|
||||
// ------ Init UI
|
||||
m_visualizationCtx = dynamic_cast<VisualizationToolkit::IVisualizationContext*>(this->createPluginObject(OVP_ClassId_Plugin_VisualizationCtx));
|
||||
m_visualizationCtx->setWidget(*this, m_MainWindow);
|
||||
|
||||
for(uint64_t i = 0; i < m_nTactilos; ++i)
|
||||
{
|
||||
resetColor();
|
||||
gtk_widget_modify_font(gtk_bin_get_child(GTK_BIN(m_EventBox[i])), m_FontDesc);
|
||||
}
|
||||
|
||||
toggleLabelText();
|
||||
|
||||
return(true);
|
||||
}
|
||||
/*******************************************************************************/
|
||||
|
||||
bool CBoxAlgorithmP300TactileVisualization::uninitialize()
|
||||
{
|
||||
// ------ uninitialize decoder/encoder
|
||||
m_SequenceInputDecoder.uninitialize();
|
||||
m_TargetInputDecoder.uninitialize();
|
||||
m_ResultInputDecoder.uninitialize();
|
||||
m_ResultOutputEncoder.uninitialize();
|
||||
|
||||
// ------ uninitialize GTK UI
|
||||
if (m_MainWidgetInterface)
|
||||
{
|
||||
g_object_unref(m_MainWidgetInterface);
|
||||
m_MainWidgetInterface = nullptr;
|
||||
}
|
||||
if (m_visualizationCtx)
|
||||
{
|
||||
this->releasePluginObject(m_visualizationCtx);
|
||||
}
|
||||
|
||||
// ------ uinitialize TCP Tagging
|
||||
if (m_idleFuncTag != 0)
|
||||
{
|
||||
m_stimuliQueue.clear();
|
||||
g_source_remove(m_idleFuncTag);
|
||||
m_idleFuncTag = 0;
|
||||
}
|
||||
if (m_stimulusSender)
|
||||
{
|
||||
delete m_stimulusSender;
|
||||
m_stimulusSender = nullptr;
|
||||
}
|
||||
|
||||
return(true);
|
||||
}
|
||||
/*******************************************************************************/
|
||||
|
||||
|
||||
bool CBoxAlgorithmP300TactileVisualization::processInput(const size_t index)
|
||||
{
|
||||
// ------ ready to process
|
||||
getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
/*******************************************************************************/
|
||||
|
||||
|
||||
bool CBoxAlgorithmP300TactileVisualization::process()
|
||||
{
|
||||
const IBox& staticBoxContext=this->getStaticBoxContext();
|
||||
IBoxIO& boxContext = this->getDynamicBoxContext();
|
||||
|
||||
//variables for processing of input chunks
|
||||
uint64_t SequenceID = 0;
|
||||
uint64_t TargetID = 0;
|
||||
uint64_t ResultID = 0;
|
||||
int Row = -1;
|
||||
bool IsTarget = false;
|
||||
bool TargetReceived = false;
|
||||
bool ResultReceived = false;
|
||||
|
||||
//variables for forwarding of target stimulations
|
||||
uint64_t ChunkStartTime = 0;
|
||||
uint64_t ChunkEndTime = 0;
|
||||
uint64_t Size = 0;
|
||||
const uint8_t* Buffer = nullptr;
|
||||
|
||||
|
||||
// ------ Sequence stimulation
|
||||
for(uint64_t i = 0; i < boxContext.getInputChunkCount(0); ++i)
|
||||
{
|
||||
m_SequenceInputDecoder.decode(i);
|
||||
m_LastTime = boxContext.getInputChunkEndTime(0, i);
|
||||
|
||||
// if header received
|
||||
if(m_SequenceInputDecoder.isHeaderReceived())
|
||||
{}
|
||||
|
||||
// if buffer received
|
||||
if(m_SequenceInputDecoder.isBufferReceived())
|
||||
{
|
||||
//check received stimulations on sequence input
|
||||
CStimulationSet* SequenceStimulationSet = m_SequenceInputDecoder.getOutputStimulationSet();
|
||||
for(uint64_t j = 0; j < SequenceStimulationSet->size(); ++j)
|
||||
{
|
||||
SequenceID = SequenceStimulationSet->getId(j);
|
||||
|
||||
if(SequenceID >= m_RowBase && SequenceID < m_RowBase + m_nTactilos)
|
||||
{
|
||||
Row = SequenceID - m_RowBase;
|
||||
IsTarget = (Row == (int)m_LastTarget);
|
||||
}
|
||||
if(SequenceID == OVTK_StimulationId_VisualStimulationStart)
|
||||
{
|
||||
resetColor();
|
||||
toggleFlashColor(Row);
|
||||
if (IsTarget)
|
||||
{
|
||||
m_stimuliQueue.push_back(OVTK_StimulationId_Target);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_stimuliQueue.push_back(OVTK_StimulationId_NonTarget);
|
||||
}
|
||||
}
|
||||
if(SequenceID == OVTK_StimulationId_VisualStimulationStop)
|
||||
{
|
||||
resetColor();
|
||||
}
|
||||
if(SequenceID == OVTK_StimulationId_SegmentStart)
|
||||
{
|
||||
toggleLabelText();
|
||||
}
|
||||
|
||||
m_stimuliQueue.push_back(SequenceID);
|
||||
}
|
||||
}
|
||||
|
||||
// if end received
|
||||
if(m_SequenceInputDecoder.isEndReceived())
|
||||
{}
|
||||
|
||||
boxContext.markInputAsDeprecated(0, i);
|
||||
}
|
||||
|
||||
// ------ Target stimulation
|
||||
for(uint64_t i = 0; i < boxContext.getInputChunkCount(1); ++i)
|
||||
{
|
||||
if(m_LastTime >= boxContext.getInputChunkStartTime(1, i))
|
||||
{
|
||||
m_TargetInputDecoder.decode(i);
|
||||
|
||||
// if header received
|
||||
if(m_SequenceInputDecoder.isHeaderReceived())
|
||||
{}
|
||||
|
||||
// if buffer received
|
||||
if(m_SequenceInputDecoder.isBufferReceived())
|
||||
{
|
||||
// check received dtimulations on Target input
|
||||
CStimulationSet* TargetStimulationSet = m_TargetInputDecoder.getOutputStimulationSet();
|
||||
for(uint64_t j = 0; j < TargetStimulationSet->size(); ++j)
|
||||
{
|
||||
TargetID = TargetStimulationSet->getId(j);
|
||||
|
||||
if(TargetID >= m_RowBase && TargetID < m_RowBase + m_nTactilos)
|
||||
{
|
||||
Row = TargetID - m_RowBase;
|
||||
TargetReceived = true;
|
||||
}
|
||||
if(TargetReceived)
|
||||
{
|
||||
toggleTargetColor(Row);
|
||||
m_stimuliQueue.push_back(TargetID);
|
||||
|
||||
std::string TargetLabel = gtk_label_get_text(m_TargetLabel);
|
||||
TargetLabel += gtk_label_get_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN(m_EventBox[Row]))));
|
||||
gtk_label_set_text(m_TargetLabel, TargetLabel.c_str());
|
||||
|
||||
m_LastTarget = Row;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if end received
|
||||
if(m_SequenceInputDecoder.isEndReceived())
|
||||
{}
|
||||
|
||||
boxContext.markInputAsDeprecated(1, i);
|
||||
}
|
||||
}
|
||||
|
||||
// ------ Result stimulation
|
||||
for(uint64_t i = 0; i < boxContext.getInputChunkCount(2); ++i)
|
||||
{
|
||||
if(m_LastTime >= boxContext.getInputChunkStartTime(2, i))
|
||||
{
|
||||
m_ResultInputDecoder.decode(i);
|
||||
|
||||
// if header received
|
||||
if(m_SequenceInputDecoder.isHeaderReceived())
|
||||
{}
|
||||
|
||||
// if buffer received
|
||||
if(m_SequenceInputDecoder.isBufferReceived())
|
||||
{
|
||||
// check received stimulations on result input
|
||||
CStimulationSet* ResultStimulationSet = m_ResultInputDecoder.getOutputStimulationSet();
|
||||
for(uint64_t j = 0; j < ResultStimulationSet->size(); ++j)
|
||||
{
|
||||
ResultID = ResultStimulationSet->getId(j);
|
||||
|
||||
if(ResultID >= m_RowBase && ResultID < m_RowBase + m_nTactilos)
|
||||
{
|
||||
Row = ResultID - m_RowBase;
|
||||
ResultReceived = true;
|
||||
}
|
||||
if(ResultReceived)
|
||||
{
|
||||
toggleResultColor(Row);
|
||||
|
||||
std::string ResultLabel = gtk_label_get_text(m_ResultLabel);
|
||||
ResultLabel += gtk_label_get_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN(m_EventBox[Row]))));
|
||||
gtk_label_set_text(m_ResultLabel, ResultLabel.c_str());
|
||||
|
||||
//switch current menu ptr to submenu
|
||||
if(m_CurrMenu->get_SubMenu(Row) != nullptr)
|
||||
{
|
||||
m_CurrMenu = m_CurrMenu->get_SubMenu(Row);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if end received
|
||||
if(m_SequenceInputDecoder.isEndReceived())
|
||||
{}
|
||||
|
||||
// forward target stimulations
|
||||
boxContext.getInputChunk(2, i, ChunkStartTime, ChunkEndTime, Size, Buffer);
|
||||
boxContext.appendOutputChunkData(0, Buffer, Size);
|
||||
boxContext.markOutputAsReadyToSend(0, ChunkStartTime, ChunkEndTime);
|
||||
boxContext.markInputAsDeprecated(2, i);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// ------ Send accumulated stimuli to the acquisition server
|
||||
if(m_idleFuncTag == 0)
|
||||
{
|
||||
m_idleFuncTag = g_idle_add(FlushCB, this);
|
||||
}
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ------ Function Definitions
|
||||
|
||||
|
||||
// Sends all accumulated stimuli to the TCP Tagging
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
// Change labels fore-/background
|
||||
void CBoxAlgorithmP300TactileVisualization::toggleFlashColor(uint64_t id)
|
||||
{
|
||||
gtk_widget_modify_fg(gtk_bin_get_child(GTK_BIN(m_EventBox[id])), GTK_STATE_NORMAL, &m_FlashFG);
|
||||
gtk_widget_modify_bg(m_EventBox[id], GTK_STATE_NORMAL, &m_FlashBG);
|
||||
}
|
||||
|
||||
void CBoxAlgorithmP300TactileVisualization::toggleTargetColor(uint64_t id)
|
||||
{
|
||||
gtk_widget_modify_fg(gtk_bin_get_child(GTK_BIN(m_EventBox[id])), GTK_STATE_NORMAL, &m_TargetFG);
|
||||
gtk_widget_modify_bg(m_EventBox[id], GTK_STATE_NORMAL, &m_TargetBG);
|
||||
}
|
||||
|
||||
void CBoxAlgorithmP300TactileVisualization::toggleResultColor(uint64_t id)
|
||||
{
|
||||
gtk_widget_modify_fg(gtk_bin_get_child(GTK_BIN(m_EventBox[id])), GTK_STATE_NORMAL, &m_ResultFG);
|
||||
gtk_widget_modify_bg(m_EventBox[id], GTK_STATE_NORMAL, &m_ResultBG);
|
||||
}
|
||||
|
||||
void CBoxAlgorithmP300TactileVisualization::resetColor()
|
||||
{
|
||||
for(uint64_t i = 0; i < m_nTactilos; i++)
|
||||
{
|
||||
gtk_widget_modify_fg(gtk_bin_get_child(GTK_BIN(m_EventBox[i])), GTK_STATE_NORMAL, &m_NoFlashFG);
|
||||
gtk_widget_modify_bg(m_EventBox[i], GTK_STATE_NORMAL, &m_NoFlashBG);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Change label text
|
||||
void CBoxAlgorithmP300TactileVisualization::toggleLabelText()
|
||||
{
|
||||
for(uint64_t i = 0; i < m_nTactilos; i++)
|
||||
{
|
||||
std::string label_text = m_CurrMenu->get_LabelText(i);
|
||||
|
||||
gtk_label_set_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN(m_EventBox[i]))), label_text.c_str());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
///-------------------------------------------------------------------------------------------------
|
||||
///
|
||||
/// \file CBoxAlgorithmP300TactileVisualization.h
|
||||
/// \brief Classes of the Box P300TactileVisualization.
|
||||
/// \author Tobias Baumann (TH Nuernberg).
|
||||
/// \version 1.0.
|
||||
/// \date Sat May 07 14:20:29 2022.
|
||||
/// \copyright <a href="https://choosealicense.com/licenses/agpl-3.0/">GNU Affero General Public License v3.0</a>.
|
||||
///
|
||||
///-------------------------------------------------------------------------------------------------
|
||||
#pragma once
|
||||
|
||||
//You may have to change this path to match your folder organisation
|
||||
#include "../ovp_defines.h"
|
||||
#include "TactileMenu.h"
|
||||
#include <openvibe/ov_all.h>
|
||||
#include <toolkit/ovtk_all.h>
|
||||
#include <tcptagging/IStimulusSender.h>
|
||||
#include <visualization-toolkit/ovviz_all.h>
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include "../utils.h"
|
||||
|
||||
|
||||
namespace TCPTagging {
|
||||
class IStimulusSender; // fwd declare
|
||||
}
|
||||
|
||||
namespace OpenViBE
|
||||
{
|
||||
namespace Plugins
|
||||
{
|
||||
namespace Tactilebci
|
||||
{
|
||||
/// <summary> The class CBoxAlgorithmP300TactileVisualization describes the box P300TactileVisualization. </summary>
|
||||
class CBoxAlgorithmP300TactileVisualization final : virtual public Toolkit::TBoxAlgorithm<IBoxAlgorithm>
|
||||
{
|
||||
public:
|
||||
// ------ OV base functions
|
||||
void release() override { delete this; }
|
||||
|
||||
bool initialize() override;
|
||||
bool uninitialize() override;
|
||||
|
||||
//Process Callback on new input received (the most common behaviour for signal processing) :
|
||||
bool processInput(const size_t index) override;
|
||||
|
||||
bool process() override;
|
||||
|
||||
// As we do with any class in openvibe, we use the macro below to associate this box to an unique identifier.
|
||||
// The inheritance information is also made available, as we provide the superclass Toolkit::TBoxAlgorithm < IBoxAlgorithm >
|
||||
_IsDerivedFromClass_Final_(Toolkit::TBoxAlgorithm<IBoxAlgorithm>, OVP_ClassId_BoxAlgorithm_P300TactileVisualization)
|
||||
|
||||
// ------ TCP Tagging
|
||||
void flushQueue();
|
||||
|
||||
// ------ UI Functions
|
||||
void toggleFlashColor(uint64_t id);
|
||||
void toggleTargetColor(uint64_t id);
|
||||
void toggleResultColor(uint64_t id);
|
||||
void resetColor();
|
||||
void toggleLabelText();
|
||||
|
||||
protected:
|
||||
// ------ Input decoder:
|
||||
Toolkit::TStimulationDecoder<CBoxAlgorithmP300TactileVisualization> m_SequenceInputDecoder;
|
||||
Toolkit::TStimulationDecoder<CBoxAlgorithmP300TactileVisualization> m_TargetInputDecoder;
|
||||
Toolkit::TStimulationDecoder<CBoxAlgorithmP300TactileVisualization> m_ResultInputDecoder;
|
||||
// ------ Output decoder:
|
||||
Toolkit::TStimulationEncoder<CBoxAlgorithmP300TactileVisualization> m_ResultOutputEncoder;
|
||||
|
||||
private:
|
||||
uint64_t m_LastTarget = 0;
|
||||
uint64_t m_LastTime = 0;
|
||||
|
||||
// ------ Box setting variables
|
||||
CString m_InterfaceFilename;
|
||||
uint64_t m_RowBase = 0;
|
||||
uint64_t m_nTactilos = 6;
|
||||
bool m_FreeSpelling = false;
|
||||
|
||||
// ------TactileMenu variables
|
||||
std::vector<TactileMenu> m_Menu;
|
||||
TactileMenu* m_CurrMenu = nullptr;
|
||||
|
||||
// ------ GTK variables
|
||||
GtkBuilder* m_MainWidgetInterface = nullptr;
|
||||
GtkWidget* m_MainWindow = nullptr;
|
||||
GtkTable* m_Table = nullptr;
|
||||
std::vector<GtkWidget*> m_EventBox;
|
||||
GtkLabel* m_ResultLabel = nullptr;
|
||||
GtkLabel* m_TargetLabel = nullptr;
|
||||
|
||||
GdkColor m_FlashBG = InitGDKColor(0, 3276, 3276, 3276);
|
||||
GdkColor m_FlashFG = InitGDKColor(0, 65535, 65535, 65535);
|
||||
GdkColor m_NoFlashBG = InitGDKColor(0, 0, 0, 0);
|
||||
GdkColor m_NoFlashFG = InitGDKColor(0, 16383, 16383, 16383);
|
||||
GdkColor m_TargetBG = InitGDKColor(0, 13107, 13107, 45874);
|
||||
GdkColor m_TargetFG = InitGDKColor(0, 6553, 6553, 19660);
|
||||
GdkColor m_ResultBG = InitGDKColor(0, 6553, 26214, 6553);
|
||||
GdkColor m_ResultFG = InitGDKColor(0, 39321, 65535, 39321);
|
||||
|
||||
uint64_t FontSize = 50;
|
||||
PangoFontDescription* m_FontDesc = nullptr;
|
||||
|
||||
// ------ TCP Tagging
|
||||
std::vector<uint64_t> m_stimuliQueue;
|
||||
guint m_idleFuncTag = 0;
|
||||
TCPTagging::IStimulusSender* m_stimulusSender = nullptr;
|
||||
|
||||
// ------ Box visualization
|
||||
VisualizationToolkit::IVisualizationContext* m_visualizationCtx = nullptr;
|
||||
};
|
||||
|
||||
/// <summary> Descriptor of the box P300TactileVisualization. </summary>
|
||||
class CBoxAlgorithmP300TactileVisualizationDesc final : virtual public IBoxAlgorithmDesc
|
||||
{
|
||||
public:
|
||||
|
||||
void release() override { }
|
||||
|
||||
CString getName() const override { return CString("P300TactileVisualization"); }
|
||||
CString getAuthorName() const override { return CString("Tobias Baumann"); }
|
||||
CString getAuthorCompanyName() const override { return CString("TH Nuernberg"); }
|
||||
CString getShortDescription() const override { return CString(""); }
|
||||
CString getDetailedDescription() const override { return CString(""); }
|
||||
CString getCategory() const override { return CString("TactileBCI"); }
|
||||
CString getVersion() const override { return CString("1.0"); }
|
||||
CString getStockItemName() const override { return CString("gtk-underline"); }
|
||||
|
||||
CIdentifier getCreatedClass() const override { return OVP_ClassId_BoxAlgorithm_P300TactileVisualization; }
|
||||
IPluginObject* create() override { return new CBoxAlgorithmP300TactileVisualization; }
|
||||
|
||||
bool hasFunctionality(const EPluginFunctionality functionality) const override { return functionality == EPluginFunctionality::Visualization; }
|
||||
|
||||
bool getBoxPrototype(Kernel::IBoxProto& prototype) const override
|
||||
{
|
||||
prototype.addInput("Sequence",OV_TypeId_Stimulations);
|
||||
prototype.addInput("Target",OV_TypeId_Stimulations);
|
||||
prototype.addInput("Result",OV_TypeId_Stimulations);
|
||||
|
||||
prototype.addOutput("Result",OV_TypeId_Stimulations);
|
||||
|
||||
prototype.addSetting("Interface Filename",OV_TypeId_Filename,"${Player_ScenarioDirectory}/ui/p300-tactile-6.ui");
|
||||
prototype.addSetting("Row Stimulation Base",OV_TypeId_Stimulation,"OVTK_StimulationId_Label_01");
|
||||
prototype.addSetting("Number of Tactilos",OV_TypeId_Integer,"6");
|
||||
prototype.addSetting("Free Spelling",OV_TypeId_Boolean,"false");
|
||||
|
||||
prototype.addFlag(OV_AttributeId_Box_FlagIsUnstable);
|
||||
|
||||
return true;
|
||||
}
|
||||
_IsDerivedFromClass_Final_(IBoxAlgorithmDesc, OVP_ClassId_BoxAlgorithm_P300TactileVisualizationDesc)
|
||||
};
|
||||
} // namespace Tactilebci
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
@@ -0,0 +1,140 @@
|
||||
///-------------------------------------------------------------------------------------------------
|
||||
///
|
||||
/// \file ovpCBoxAlgorithmTactiloController.cpp
|
||||
/// \brief Functions of the Box Tactilo Controller.
|
||||
/// \author Tobias Baumann (TH-Nürnberg).
|
||||
/// \version 1.0.
|
||||
/// \date Mon Feb 21 14:59:56 2022.
|
||||
/// \copyright <a href="https://choosealicense.com/licenses/agpl-3.0/">GNU Affero General Public License v3.0</a>.
|
||||
///
|
||||
///-------------------------------------------------------------------------------------------------
|
||||
|
||||
//includes
|
||||
#include "ovpCBoxAlgorithmTactiloController.h"
|
||||
|
||||
using namespace OpenViBE;
|
||||
using namespace /*OpenViBE::*/Kernel;
|
||||
using namespace /*OpenViBE::*/Plugins;
|
||||
using namespace /*OpenViBE::Plugins::*/Tactilebci;
|
||||
|
||||
/*******************************************************************************/
|
||||
|
||||
bool CBoxAlgorithmTactiloController::initialize()
|
||||
{
|
||||
m_StimDecoder.initialize(*this, 0);
|
||||
m_StimEncoder.initialize(*this, 0);
|
||||
|
||||
//get Box Settings
|
||||
m_PortName = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 0);
|
||||
m_RowBase = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 1);
|
||||
m_nTactilos = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 2);
|
||||
|
||||
//set m_nTactilos to 2 if lower than 2
|
||||
if(m_nTactilos < 2)
|
||||
{
|
||||
m_nTactilos = 2;
|
||||
}
|
||||
//set m_nTactilos to MAX if greater than MAX_TACTILOS
|
||||
if(m_nTactilos > MAX_TACTILOS)
|
||||
{
|
||||
m_nTactilos = MAX_TACTILOS;
|
||||
}
|
||||
|
||||
//open serial port and set baudrate to 115200
|
||||
m_Port.open(m_PortName.toASCIIString());
|
||||
m_Port.set_option(boost::asio::serial_port::baud_rate(115200));
|
||||
|
||||
if(m_Port.is_open())
|
||||
{
|
||||
this->getLogManager() << LogLevel_Info << "Connected to Serial Port: " << m_PortName << "\n";
|
||||
m_Port.write_some(boost::asio::buffer("b"));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*******************************************************************************/
|
||||
|
||||
bool CBoxAlgorithmTactiloController::uninitialize()
|
||||
{
|
||||
this->getLogManager() << LogLevel_Info << "Disconnect from Serial Port: " << m_PortName << "\n";
|
||||
m_Port.write_some(boost::asio::buffer("e"));
|
||||
m_Port.close();
|
||||
|
||||
m_StimDecoder.uninitialize();
|
||||
m_StimEncoder.uninitialize();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*******************************************************************************/
|
||||
|
||||
bool CBoxAlgorithmTactiloController::processInput(const size_t index)
|
||||
{
|
||||
// some pre-processing code if needed...
|
||||
|
||||
// ready to process !
|
||||
getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*******************************************************************************/
|
||||
bool CBoxAlgorithmTactiloController::process()
|
||||
{
|
||||
|
||||
// the static box context describes the box inputs, outputs, settings structures
|
||||
const IBox& staticBoxContext = this->getStaticBoxContext();
|
||||
// the dynamic box context describes the current state of the box inputs and outputs (i.e. the chunks)
|
||||
IBoxIO& boxContext = this->getDynamicBoxContext();
|
||||
|
||||
uint64_t ChunkStartTime = 0;
|
||||
uint64_t ChunkEndTime = 0;
|
||||
uint64_t Size = 0;
|
||||
const uint8_t* Buffer = nullptr;
|
||||
|
||||
//iterate over all chunk on input 0
|
||||
for (uint64_t i = 0; i < boxContext.getInputChunkCount(0); ++i)
|
||||
{
|
||||
// decode the chunk i
|
||||
m_StimDecoder.decode(i);
|
||||
|
||||
if(m_StimDecoder.isBufferReceived())
|
||||
{
|
||||
//check received stimulations
|
||||
CStimulationSet* StimSet = m_StimDecoder.getOutputStimulationSet();
|
||||
for(uint64_t j=0; j<StimSet->size(); j++)
|
||||
{
|
||||
uint64_t StimulationID = StimSet->getId(j);
|
||||
|
||||
if(StimulationID >= m_RowBase && StimulationID < (m_RowBase + m_nTactilos))
|
||||
{
|
||||
m_currTactiloID = StimulationID-m_RowBase;
|
||||
}
|
||||
if(StimulationID == OVTK_StimulationId_VisualStimulationStart || StimulationID == OVTK_StimulationId_VisualStimulationStop)
|
||||
{
|
||||
boost::asio::async_write(m_Port, boost::asio::buffer(std::to_string(m_currTactiloID), 1), boost::bind(&CBoxAlgorithmTactiloController::handler, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// forward input chunks
|
||||
boxContext.getInputChunk(0, i, ChunkStartTime, ChunkEndTime, Size, Buffer);
|
||||
boxContext.appendOutputChunkData(0, Buffer, Size);
|
||||
boxContext.markOutputAsReadyToSend(0, ChunkStartTime, ChunkEndTime);
|
||||
boxContext.markInputAsDeprecated(0, i);
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*******************************************************************************/
|
||||
|
||||
void CBoxAlgorithmTactiloController::handler(const boost::system::error_code& error, std::size_t bytes_transferred)
|
||||
{
|
||||
if(error)
|
||||
{
|
||||
this->getLogManager() << LogLevel_Warning << error.message() << "\n";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
///-------------------------------------------------------------------------------------------------
|
||||
///
|
||||
/// \file ovpCBoxAlgorithmTactiloController.h
|
||||
/// \brief Classes of the Box Tactilo Controller.
|
||||
/// \author Tobias Baumann (TH-Nürnberg).
|
||||
/// \version 1.0.
|
||||
/// \date Mon Feb 21 14:59:56 2022.
|
||||
/// \copyright <a href="https://choosealicense.com/licenses/agpl-3.0/">GNU Affero General Public License v3.0</a>.
|
||||
///
|
||||
///-------------------------------------------------------------------------------------------------
|
||||
|
||||
//includes
|
||||
#pragma once
|
||||
|
||||
#include "../ovp_defines.h"
|
||||
|
||||
#include <openvibe/ov_all.h>
|
||||
#include <toolkit/ovtk_all.h>
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace OpenViBE
|
||||
{
|
||||
namespace Plugins
|
||||
{
|
||||
namespace Tactilebci
|
||||
{
|
||||
/// <summary> The class CBoxAlgorithmTactiloController describes the box Tactilo Controller. </summary>
|
||||
class CBoxAlgorithmTactiloController final : virtual public Toolkit::TBoxAlgorithm<IBoxAlgorithm>
|
||||
{
|
||||
public:
|
||||
void release() override { delete this; }
|
||||
|
||||
bool initialize() override;
|
||||
bool uninitialize() override;
|
||||
bool processInput(const size_t index) override;
|
||||
bool process() override;
|
||||
|
||||
// write handler
|
||||
void handler(const boost::system::error_code& error, std::size_t bytes_transferred);
|
||||
|
||||
// As we do with any class in openvibe, we use the macro below to associate this box to an unique identifier.
|
||||
// The inheritance information is also made available, as we provide the superclass Toolkit::TBoxAlgorithm < IBoxAlgorithm >
|
||||
_IsDerivedFromClass_Final_(Toolkit::TBoxAlgorithm<IBoxAlgorithm>, OVP_ClassId_BoxAlgorithm_TactiloController)
|
||||
|
||||
protected:
|
||||
// Input decoder:
|
||||
Toolkit::TStimulationDecoder<CBoxAlgorithmTactiloController> m_StimDecoder;
|
||||
// Output decoder:
|
||||
Toolkit::TStimulationEncoder<CBoxAlgorithmTactiloController> m_StimEncoder;
|
||||
|
||||
private:
|
||||
//variable to store the current TactiloNr
|
||||
uint64_t m_currTactiloID = 0;
|
||||
//Box Settings
|
||||
CString m_PortName = "";
|
||||
uint64_t m_RowBase = 0;
|
||||
uint64_t m_nTactilos = 0;
|
||||
|
||||
//Serial Port
|
||||
boost::asio::io_service m_IOService;
|
||||
boost::asio::serial_port m_Port{m_IOService};
|
||||
};
|
||||
|
||||
/// <summary> Descriptor of the box Tactilo Controller. </summary>
|
||||
class CBoxAlgorithmTactiloControllerDesc final : virtual public IBoxAlgorithmDesc
|
||||
{
|
||||
public:
|
||||
|
||||
void release() override { }
|
||||
|
||||
CString getName() const override { return CString("Tactilo Controller"); }
|
||||
CString getAuthorName() const override { return CString("Tobias Baumann"); }
|
||||
CString getAuthorCompanyName() const override { return CString("TH-Nürnberg"); }
|
||||
CString getShortDescription() const override { return CString("Controls the Tactilos on the Lattepandas GPIOs"); }
|
||||
CString getDetailedDescription() const override { return CString("Communicates with the Arduino Coprocessor of the Lattepanda over a Serial Inteface, to control the Tactilos connected to the Arduinos GPIOs"); }
|
||||
CString getCategory() const override { return CString("TactileBCI"); }
|
||||
CString getVersion() const override { return CString("1.0"); }
|
||||
CString getStockItemName() const override { return CString("gtk-network"); }
|
||||
|
||||
CIdentifier getCreatedClass() const override { return OVP_ClassId_BoxAlgorithm_TactiloController; }
|
||||
IPluginObject* create() override { return new CBoxAlgorithmTactiloController; }
|
||||
|
||||
bool getBoxPrototype(Kernel::IBoxProto& prototype) const override
|
||||
{
|
||||
prototype.addInput("StimInput",OV_TypeId_Stimulations);
|
||||
|
||||
//prototype.addFlag(Kernel::BoxFlag_CanModifyInput);
|
||||
//prototype.addFlag(Kernel::BoxFlag_CanAddInput);
|
||||
|
||||
prototype.addOutput("StimOutput",OV_TypeId_Stimulations);
|
||||
|
||||
//prototype.addFlag(Kernel::BoxFlag_CanModifyOutput);
|
||||
//prototype.addFlag(Kernel::BoxFlag_CanAddOutput);
|
||||
|
||||
//Box Settings
|
||||
prototype.addSetting("Serial Port Name",OV_TypeId_String,"/dev/ttyACM0");
|
||||
prototype.addSetting("Row Stimulation Base",OV_TypeId_Stimulation,"OVTK_StimulationId_Label_01");
|
||||
prototype.addSetting("Number of Tactilos",OV_TypeId_Integer,"6");
|
||||
|
||||
//prototype.addFlag(Kernel::BoxFlag_CanModifySetting);
|
||||
//prototype.addFlag(Kernel::BoxFlag_CanAddSetting);
|
||||
|
||||
prototype.addFlag(OV_AttributeId_Box_FlagIsUnstable);
|
||||
|
||||
return true;
|
||||
}
|
||||
_IsDerivedFromClass_Final_(IBoxAlgorithmDesc, OVP_ClassId_BoxAlgorithm_TactiloControllerDesc)
|
||||
};
|
||||
} // namespace Tactilebci
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
@@ -0,0 +1,113 @@
|
||||
///-------------------------------------------------------------------------------------------------
|
||||
///
|
||||
/// \file CBoxAlgorithmUDPStimcodeSender.cpp
|
||||
/// \brief Functions of Class UDP-StimCode-Sender
|
||||
/// \author Tobias Baumann (TH Nuernberg).
|
||||
/// \version 1.2.
|
||||
/// \date Mon Oct 04 12:43:53 2021.
|
||||
/// \copyright <a href="https://choosealicense.com/licenses/agpl-3.0/">GNU Affero General Public License v3.0</a>.
|
||||
///
|
||||
///-------------------------------------------------------------------------------------------------
|
||||
|
||||
//includes
|
||||
#include "ovpCBoxAlgorithmUDPStimcodeSender.h"
|
||||
|
||||
using namespace OpenViBE;
|
||||
using namespace /*OpenViBE::*/Kernel;
|
||||
using namespace /*OpenViBE::*/Plugins;
|
||||
using namespace /*OpenViBE::Plugins::*/Tactilebci;
|
||||
|
||||
bool CBoxAlgorithmUDPStimcodeSender::initialize()
|
||||
{
|
||||
m_StimDecoder.initialize(*this, 0);
|
||||
m_StimEncoder.initialize(*this, 0);
|
||||
|
||||
// retrieve box settings
|
||||
m_IP = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 0);
|
||||
m_Port = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 1);
|
||||
m_RowBase = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 2);
|
||||
m_nTactilos = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 3);
|
||||
|
||||
//set m_nTactilos to 2 if lower than 2
|
||||
if(m_nTactilos < 2)
|
||||
{
|
||||
m_nTactilos = 2;
|
||||
}
|
||||
//set m_nTactilos to MAX if greater than MAX_TACTILOS
|
||||
if(m_nTactilos > MAX_TACTILOS)
|
||||
{
|
||||
m_nTactilos = MAX_TACTILOS;
|
||||
}
|
||||
|
||||
// connect UDP socket
|
||||
boost::asio::ip::udp::endpoint m_Endpoint(boost::asio::ip::address::from_string(m_IP), m_Port);
|
||||
m_Socket.connect(m_Endpoint);
|
||||
|
||||
return true;
|
||||
}
|
||||
/*******************************************************************************/
|
||||
|
||||
bool CBoxAlgorithmUDPStimcodeSender::uninitialize()
|
||||
{
|
||||
m_StimDecoder.uninitialize();
|
||||
m_StimEncoder.uninitialize();
|
||||
|
||||
return true;
|
||||
}
|
||||
/*******************************************************************************/
|
||||
|
||||
bool CBoxAlgorithmUDPStimcodeSender::processInput(const size_t index)
|
||||
{
|
||||
// some pre-processing code if needed...
|
||||
|
||||
// ready to process !
|
||||
getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*******************************************************************************/
|
||||
|
||||
|
||||
bool CBoxAlgorithmUDPStimcodeSender::process()
|
||||
{
|
||||
|
||||
// the static box context describes the box inputs, outputs, settings structures
|
||||
const IBox& staticBoxContext = this->getStaticBoxContext();
|
||||
// the dynamic box context describes the current state of the box inputs and outputs (i.e. the chunks)
|
||||
IBoxIO& boxContext = this->getDynamicBoxContext();
|
||||
uint64_t StimulationID = 0;
|
||||
uint64_t ChunkStartTime = 0;
|
||||
uint64_t ChunkEndTime = 0;
|
||||
uint64_t Size = 0;
|
||||
const uint8_t* Buffer = nullptr;
|
||||
|
||||
//iterate over all chunk on input 0
|
||||
for (uint64_t i = 0; i < boxContext.getInputChunkCount(0); ++i)
|
||||
{
|
||||
// decode the chunk i
|
||||
m_StimDecoder.decode(i);
|
||||
if(m_StimDecoder.isBufferReceived())
|
||||
{
|
||||
//check received stimulations
|
||||
IStimulationSet* StimSet = m_StimDecoder.getOutputStimulationSet();
|
||||
for(uint64_t j=0; j<StimSet->getStimulationCount(); j++)
|
||||
{
|
||||
StimulationID = StimSet->getStimulationIdentifier(j);
|
||||
|
||||
if(StimulationID >= m_RowBase && StimulationID < (m_RowBase + m_nTactilos))
|
||||
{
|
||||
this->getLogManager() << LogLevel_Debug << "send udp : [StimulusCode " << (StimulationID-m_RowBase+1) << "]\n";
|
||||
m_Socket.send(boost::asio::buffer(std::to_string(StimulationID-m_RowBase+1)));
|
||||
}
|
||||
}
|
||||
}
|
||||
// forward input chunks
|
||||
boxContext.getInputChunk(0, i, ChunkStartTime, ChunkEndTime, Size, Buffer);
|
||||
boxContext.appendOutputChunkData(0, Buffer, Size);
|
||||
boxContext.markOutputAsReadyToSend(0, ChunkStartTime, ChunkEndTime);
|
||||
boxContext.markInputAsDeprecated(0, i);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
///-------------------------------------------------------------------------------------------------
|
||||
///
|
||||
/// \file CBoxAlgorithmUDPStimcodeSender.h
|
||||
/// \brief Classes of the Box UDPStimcodeSender.
|
||||
/// \author Tobias Baumann (TH Nuernberg).
|
||||
/// \version 1.1.
|
||||
/// \date Mon Oct 04 12:43:53 2021.
|
||||
/// \copyright <a href="https://choosealicense.com/licenses/agpl-3.0/">GNU Affero General Public License v3.0</a>.
|
||||
///
|
||||
///-------------------------------------------------------------------------------------------------
|
||||
|
||||
//includes
|
||||
#pragma once
|
||||
//You may have to change this path to match your folder organisation
|
||||
#include "../ovp_defines.h"
|
||||
|
||||
#include <openvibe/ov_all.h>
|
||||
#include <toolkit/ovtk_all.h>
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
|
||||
namespace OpenViBE
|
||||
{
|
||||
namespace Plugins
|
||||
{
|
||||
namespace Tactilebci
|
||||
{
|
||||
/// <summary> The class CBoxAlgorithmUDPStimcodeSender describes the box UDPStimcodeSender. </summary>
|
||||
class CBoxAlgorithmUDPStimcodeSender final : virtual public Toolkit::TBoxAlgorithm<IBoxAlgorithm>
|
||||
{
|
||||
public:
|
||||
void release() override { delete this; }
|
||||
|
||||
bool initialize() override;
|
||||
bool uninitialize() override;
|
||||
bool processInput(const size_t index) override;
|
||||
bool process() override;
|
||||
|
||||
// As we do with any class in openvibe, we use the macro below to associate this box to an unique identifier.
|
||||
// The inheritance information is also made available, as we provide the superclass Toolkit::TBoxAlgorithm < IBoxAlgorithm >
|
||||
_IsDerivedFromClass_Final_(Toolkit::TBoxAlgorithm<IBoxAlgorithm>, OVP_ClassId_BoxAlgorithm_UDPStimcodeSender)
|
||||
|
||||
protected:
|
||||
// Input decoder:
|
||||
Toolkit::TStimulationDecoder<CBoxAlgorithmUDPStimcodeSender> m_StimDecoder;
|
||||
// Output decoder:
|
||||
Toolkit::TStimulationEncoder<CBoxAlgorithmUDPStimcodeSender> m_StimEncoder;
|
||||
private:
|
||||
// Box setting variables
|
||||
CString m_IP = "";
|
||||
uint64_t m_Port = 0;
|
||||
uint64_t m_RowBase = 0;
|
||||
uint64_t m_nTactilos = 0;
|
||||
// Socket
|
||||
boost::asio::io_service m_IOService;
|
||||
boost::asio::ip::udp::socket m_Socket{m_IOService};
|
||||
};
|
||||
|
||||
|
||||
/// <summary> Descriptor of the box UDPStimcodeSender. </summary>
|
||||
class CBoxAlgorithmUDPStimcodeSenderDesc final : virtual public IBoxAlgorithmDesc
|
||||
{
|
||||
public:
|
||||
|
||||
void release() override { }
|
||||
|
||||
CString getName() const override { return CString("UDPStimcodeSender"); }
|
||||
CString getAuthorName() const override { return CString("Tobias Baumann"); }
|
||||
CString getAuthorCompanyName() const override { return CString("TH Nuernberg"); }
|
||||
CString getShortDescription() const override { return CString("Sends Stimulationcodes via UDP"); }
|
||||
CString getDetailedDescription() const override { return CString("Sends the received Stimulationcodes the Adafruit Feather, using UDP. The Input Stimulation will be passed to the Output unchanged."); }
|
||||
CString getCategory() const override { return CString("TactileBCI"); }
|
||||
CString getVersion() const override { return CString("1.1"); }
|
||||
CString getStockItemName() const override { return CString("gtk-network"); }
|
||||
|
||||
CIdentifier getCreatedClass() const override { return OVP_ClassId_BoxAlgorithm_UDPStimcodeSender; }
|
||||
IPluginObject* create() override { return new CBoxAlgorithmUDPStimcodeSender; }
|
||||
|
||||
bool getBoxPrototype(Kernel::IBoxProto& prototype) const override
|
||||
{
|
||||
prototype.addInput("StimcodeIn",OV_TypeId_Stimulations);
|
||||
|
||||
//prototype.addFlag(Kernel::BoxFlag_CanModifyInput);
|
||||
//prototype.addFlag(Kernel::BoxFlag_CanAddInput);
|
||||
|
||||
prototype.addOutput("StimcodeOut",OV_TypeId_Stimulations);
|
||||
|
||||
//prototype.addFlag(Kernel::BoxFlag_CanModifyOutput);
|
||||
//prototype.addFlag(Kernel::BoxFlag_CanAddOutput);
|
||||
|
||||
prototype.addSetting("FeatherIP",OV_TypeId_String,"192.168.4.1");
|
||||
prototype.addSetting("FeatherPort",OV_TypeId_Integer,"8888");
|
||||
prototype.addSetting("RowStimulationBase",OV_TypeId_Stimulation,"OVTK_StimulationId_Label_01");
|
||||
prototype.addSetting("Number of Tactilos",OV_TypeId_Integer,"6");
|
||||
|
||||
prototype.addFlag(Kernel::BoxFlag_CanModifySetting);
|
||||
//prototype.addFlag(Kernel::BoxFlag_CanAddSetting);
|
||||
|
||||
prototype.addFlag(OV_AttributeId_Box_FlagIsUnstable);
|
||||
|
||||
return true;
|
||||
}
|
||||
_IsDerivedFromClass_Final_(IBoxAlgorithmDesc, OVP_ClassId_BoxAlgorithm_UDPStimcodeSenderDesc)
|
||||
};
|
||||
} // namespace Tactilebci
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
@@ -0,0 +1,36 @@
|
||||
///-------------------------------------------------------------------------------------------------
|
||||
///
|
||||
/// \file ovp_defines.h
|
||||
/// \brief defines for the TactileBCI Plugin
|
||||
/// \author Tobias Baumann (TH-Nürnberg).
|
||||
/// \date Mon Feb 04 14:59:56 2022.
|
||||
/// \copyright <a href="https://choosealicense.com/licenses/agpl-3.0/">GNU Affero General Public License v3.0</a>.
|
||||
///
|
||||
///-------------------------------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
// Boxes
|
||||
// The unique identifiers for the boxes and their descriptors.
|
||||
// Identifier are randomly chosen by the skeleton-generator.
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
#define OVP_ClassId_BoxAlgorithm_P300TactileVisualization OpenViBE::CIdentifier(0xd463df86, 0x7fbfdd81)
|
||||
#define OVP_ClassId_BoxAlgorithm_P300TactileVisualizationDesc OpenViBE::CIdentifier(0x3e7f0ef5, 0x5ca2a1fc)
|
||||
|
||||
#define OVP_ClassId_BoxAlgorithm_UDPStimcodeSender OpenViBE::CIdentifier(0xc326e786, 0xcd512965)
|
||||
#define OVP_ClassId_BoxAlgorithm_UDPStimcodeSenderDesc OpenViBE::CIdentifier(0x82aeb3c9, 0x37303d0e)
|
||||
|
||||
#define OVP_ClassId_BoxAlgorithm_TactiloController OpenViBE::CIdentifier(0x823bbe28, 0x0daf2111)
|
||||
#define OVP_ClassId_BoxAlgorithm_TactiloControllerDesc OpenViBE::CIdentifier(0xdb6e9c60, 0x4ce98ac3)
|
||||
|
||||
// Global defines
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
#define MAX_TACTILOS 10
|
||||
|
||||
#ifdef TARGET_HAS_ThirdPartyOpenViBEPluginsGlobalDefines
|
||||
#include "ovp_global_defines.h"
|
||||
#endif // TARGET_HAS_ThirdPartyOpenViBEPluginsGlobalDefines
|
||||
|
||||
#define OV_AttributeId_Box_FlagIsUnstable OpenViBE::CIdentifier(0x666FFFFF, 0x666FFFFF)
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
///-------------------------------------------------------------------------------------------------
|
||||
///
|
||||
/// \file ovp_main.cpp
|
||||
/// \brief Declarations/Includes for the TactileBCI Plugin
|
||||
/// \author Tobias Baumann (TH-Nürnberg).
|
||||
/// \date Mon Feb 07 14:59:56 2022.
|
||||
/// \copyright <a href="https://choosealicense.com/licenses/agpl-3.0/">GNU Affero General Public License v3.0</a>.
|
||||
///
|
||||
///-------------------------------------------------------------------------------------------------
|
||||
|
||||
//Tactile BCI Includes
|
||||
#include <vector>
|
||||
#include <openvibe/ov_all.h>
|
||||
#include "ovp_defines.h"
|
||||
|
||||
#include "TactileVisualization/ovpCBoxAlgorithmP300TactileVisualization.h"
|
||||
#include "UDPStimCodeSender/ovpCBoxAlgorithmUDPStimcodeSender.h"
|
||||
#include "TactiloController/ovpCBoxAlgorithmTactiloController.h"
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Tactilebci {
|
||||
|
||||
OVP_Declare_Begin()
|
||||
|
||||
OVP_Declare_New(CBoxAlgorithmP300TactileVisualizationDesc);
|
||||
OVP_Declare_New(CBoxAlgorithmUDPStimcodeSenderDesc);
|
||||
OVP_Declare_New(CBoxAlgorithmTactiloControllerDesc);
|
||||
|
||||
OVP_Declare_End()
|
||||
|
||||
} // namespace Tactilebci
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
|
||||
#include <openvibe/ov_all.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <sstream>
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
/// <summary> Initializes the color of the GDK. with old compiler as vs2013 we can't initialize structure easily.....</summary>
|
||||
/// <param name="pixel"> For allocated colors, the pixel value used to draw this color on the screen.Not used anymore.</param>
|
||||
/// <param name="r"> The red component of the color. This is a value between 0 and 65535, with 65535 indicating full intensity.</param>
|
||||
/// <param name="g"> The green component of the color.</param>
|
||||
/// <param name="b"> The blue component of the color.</param>
|
||||
/// <returns> The initialized color (</returns>
|
||||
inline GdkColor InitGDKColor(const guint32 pixel = 0, const guint16 r = 0, const guint16 g = 0, const guint16 b = 0)
|
||||
{
|
||||
GdkColor c;
|
||||
c.pixel = pixel;
|
||||
c.red = r;
|
||||
c.green = g;
|
||||
c.blue = b;
|
||||
return c;
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
class CGdkcolorAutoCast
|
||||
{
|
||||
public:
|
||||
CGdkcolorAutoCast(const OpenViBE::Kernel::IBox& box, OpenViBE::Kernel::IConfigurationManager& configManager, const size_t index)
|
||||
: m_configManager(configManager)
|
||||
{
|
||||
box.getSettingValue(index, m_settingValue);
|
||||
m_settingValue = m_configManager.expand(m_settingValue);
|
||||
}
|
||||
|
||||
operator GdkColor() const
|
||||
{
|
||||
std::stringstream ss(m_settingValue.toASCIIString());
|
||||
int r = 0, g = 0, b = 0;
|
||||
char c;
|
||||
ss >> r >> c >> g >> c >> b;
|
||||
return InitGDKColor(0, guint16(r * 655.35), guint16(g * 655.35), guint16(b * 655.35));
|
||||
}
|
||||
|
||||
protected:
|
||||
OpenViBE::Kernel::IConfigurationManager& m_configManager;
|
||||
OpenViBE::CString m_settingValue;
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
Reference in New Issue
Block a user