<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://www.bci2000.org/mediawiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Mmarcus</id>
	<title>BCI2000 Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://www.bci2000.org/mediawiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Mmarcus"/>
	<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php/Special:Contributions/Mmarcus"/>
	<updated>2026-06-29T17:10:22Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.6</generator>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:Manually_Build_BCI2000_on_Non-Windows_Platforms&amp;diff=10484</id>
		<title>Programming Howto:Manually Build BCI2000 on Non-Windows Platforms</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:Manually_Build_BCI2000_on_Non-Windows_Platforms&amp;diff=10484"/>
		<updated>2023-06-21T15:42:13Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: /* Choose Build Options */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Installing Dependencies==&lt;br /&gt;
There are three dependencies that need to be installed before you can compile BCI2000:&lt;br /&gt;
*ffmpeg (version 4.4.1, version 5 does not work with BCI2000)&lt;br /&gt;
*portaudio&lt;br /&gt;
*sdl2&lt;br /&gt;
These can be installed using the &lt;br /&gt;
 install_dependencies&lt;br /&gt;
script in the BCI2000 home directory. This will automatically detect your homebrew or it will download a portable version of homebrew in your BCI2000 directory. Then it will install the necessary dependencies. Alternatively, you can manually install them, and they will be automatically detected by CMake. If you have already installed homebrew, this can be done with&lt;br /&gt;
 brew install ffmpeg@4&lt;br /&gt;
 brew link ffmpeg@4&lt;br /&gt;
 brew install portaudio&lt;br /&gt;
 brew install sdl2&lt;br /&gt;
&lt;br /&gt;
==Configure BCI2000 for Compilation==&lt;br /&gt;
&lt;br /&gt;
===Run the CMake GUI===&lt;br /&gt;
Double-click &amp;quot;Configure.sh.cmd&amp;quot; in your BCI2000 build directory.&lt;br /&gt;
&lt;br /&gt;
[[File:Cmake-init-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Tell CMake which Qt installation to use===&lt;br /&gt;
Click &amp;quot;AddEntry&amp;quot; in the CMake window (&amp;lt;i&amp;gt;Note that checking off &amp;quot;Advanced&amp;quot; in Cmake is optional and does not impact the compilation&amp;lt;/i&amp;gt;) and enter the path to a Qt directory. If you installed Qt with homebrew, this can be found with&lt;br /&gt;
 brew list qt@5&lt;br /&gt;
The installation directory is only the part of the paths that are&lt;br /&gt;
 .../hombrew/Cellar/qt@5/&amp;lt;version&amp;gt;&lt;br /&gt;
Use everything up to the version and nothing past it.&lt;br /&gt;
Use CMAKE_PREFIX_PATH as the name for the new entry. Be aware that the entry&#039;s name is case sensitive. &amp;lt;b&amp;gt;Currently, on non-windows platform, Qt 5 is the only version that is supported.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Cmake-add-cache-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Configuration===&lt;br /&gt;
In the CMake window, click &amp;quot;Configure&amp;quot; and choose a generator that is consistent with your compiler. This tutorial will be using Unix Makefiles. Then click &amp;quot;Done&amp;quot; to perform the configuration step. &lt;br /&gt;
[[File:Cmake-generators-non-windows.png|700px]]&lt;br /&gt;
&amp;lt;br&amp;gt;You will see a list of targets scrolling by, and a number of new entries in the variable list at the top of the window, marked in red.&lt;br /&gt;
&lt;br /&gt;
===Choose Build Options===&lt;br /&gt;
Make sure the &amp;quot;Grouped&amp;quot; checkbox is checked, and configure the build by customizing values in the &amp;quot;BUILD&amp;quot; group, &amp;quot;EXTENSIONS&amp;quot; group,  and &amp;quot;USE&amp;quot; group. &lt;br /&gt;
[[File:Cmake-configured-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Generate Makefiles===&lt;br /&gt;
Then, click &amp;quot;Generate&amp;quot; to create build files. When CMake displays its &amp;quot;Generating done&amp;quot; message, your BCI2000 build directory will now contain a Makefile (or a project file for your compiler of chioce), as well as a number of additional CMake-generated files.&lt;br /&gt;
&lt;br /&gt;
[[File:Cmake-done-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
==Compile BCI2000==&lt;br /&gt;
===Open Terminal===&lt;br /&gt;
Open a new terminal window and navigate to your BCI2000 build directory.&lt;br /&gt;
&lt;br /&gt;
[[File:terminal-bulid-directory-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Build Makefiles===&lt;br /&gt;
Run:&lt;br /&gt;
 make&lt;br /&gt;
from your BCI2000 build directory. Once this is finished your BCI2000 prog directory will contain a number of executables, one for each module, plus a few helper executables. Not everything works the same or, in some cases, at all on non-windows platforms. See, [[Non-Windows Functionality]] for more information.&lt;br /&gt;
&lt;br /&gt;
[[File:Make-done-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
The build process is now complete. Run &lt;br /&gt;
 make&lt;br /&gt;
again to recompile. Or&lt;br /&gt;
 make &amp;lt;target&amp;gt;&lt;br /&gt;
to recompile only a specific target.&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:Manually_Build_BCI2000_on_Non-Windows_Platforms&amp;diff=10483</id>
		<title>Programming Howto:Manually Build BCI2000 on Non-Windows Platforms</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:Manually_Build_BCI2000_on_Non-Windows_Platforms&amp;diff=10483"/>
		<updated>2023-06-20T14:26:09Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: /* Choose Build Options */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Installing Dependencies==&lt;br /&gt;
There are three dependencies that need to be installed before you can compile BCI2000:&lt;br /&gt;
*ffmpeg (version 4.4.1, version 5 does not work with BCI2000)&lt;br /&gt;
*portaudio&lt;br /&gt;
*sdl2&lt;br /&gt;
These can be installed using the &lt;br /&gt;
 install_dependencies&lt;br /&gt;
script in the BCI2000 home directory. This will automatically detect your homebrew or it will download a portable version of homebrew in your BCI2000 directory. Then it will install the necessary dependencies. Alternatively, you can manually install them, and they will be automatically detected by CMake. If you have already installed homebrew, this can be done with&lt;br /&gt;
 brew install ffmpeg@4&lt;br /&gt;
 brew link ffmpeg@4&lt;br /&gt;
 brew install portaudio&lt;br /&gt;
 brew install sdl2&lt;br /&gt;
&lt;br /&gt;
==Configure BCI2000 for Compilation==&lt;br /&gt;
&lt;br /&gt;
===Run the CMake GUI===&lt;br /&gt;
Double-click &amp;quot;Configure.sh.cmd&amp;quot; in your BCI2000 build directory.&lt;br /&gt;
&lt;br /&gt;
[[File:Cmake-init-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Tell CMake which Qt installation to use===&lt;br /&gt;
Click &amp;quot;AddEntry&amp;quot; in the CMake window (&amp;lt;i&amp;gt;Note that checking off &amp;quot;Advanced&amp;quot; in Cmake is optional and does not impact the compilation&amp;lt;/i&amp;gt;) and enter the path to a Qt directory. If you installed Qt with homebrew, this can be found with&lt;br /&gt;
 brew list qt@5&lt;br /&gt;
The installation directory is only the part of the paths that are&lt;br /&gt;
 .../hombrew/Cellar/qt@5/&amp;lt;version&amp;gt;&lt;br /&gt;
Use everything up to the version and nothing past it.&lt;br /&gt;
Use CMAKE_PREFIX_PATH as the name for the new entry. Be aware that the entry&#039;s name is case sensitive. &amp;lt;b&amp;gt;Currently, on non-windows platform, Qt 5 is the only version that is supported.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Cmake-add-cache-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Configuration===&lt;br /&gt;
In the CMake window, click &amp;quot;Configure&amp;quot; and choose a generator that is consistent with your compiler. This tutorial will be using Unix Makefiles. Then click &amp;quot;Done&amp;quot; to perform the configuration step. &lt;br /&gt;
[[File:Cmake-generators-non-windows.png|700px]]&lt;br /&gt;
&amp;lt;br&amp;gt;You will see a list of targets scrolling by, and a number of new entries in the variable list at the top of the window, marked in red.&lt;br /&gt;
&lt;br /&gt;
===Choose Build Options===&lt;br /&gt;
Make sure the &amp;quot;Grouped&amp;quot; checkbox is checked, and configure the build by customizing values in the &amp;quot;BUILD&amp;quot; group, &amp;quot;EXTENSIONS&amp;quot; group,  and &amp;quot;USE&amp;quot; group. &lt;br /&gt;
[[File:Cmake-configured-non-windows.png|700px]]&lt;br /&gt;
If running on an ARM based apple machine, make sure that &lt;br /&gt;
 USE_MACOS_APPLICATION_BUNDLES&lt;br /&gt;
is disabled to ensure that the executables can be run.&lt;br /&gt;
&lt;br /&gt;
===Generate Makefiles===&lt;br /&gt;
Then, click &amp;quot;Generate&amp;quot; to create build files. When CMake displays its &amp;quot;Generating done&amp;quot; message, your BCI2000 build directory will now contain a Makefile (or a project file for your compiler of chioce), as well as a number of additional CMake-generated files.&lt;br /&gt;
&lt;br /&gt;
[[File:Cmake-done-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
==Compile BCI2000==&lt;br /&gt;
===Open Terminal===&lt;br /&gt;
Open a new terminal window and navigate to your BCI2000 build directory.&lt;br /&gt;
&lt;br /&gt;
[[File:terminal-bulid-directory-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Build Makefiles===&lt;br /&gt;
Run:&lt;br /&gt;
 make&lt;br /&gt;
from your BCI2000 build directory. Once this is finished your BCI2000 prog directory will contain a number of executables, one for each module, plus a few helper executables. Not everything works the same or, in some cases, at all on non-windows platforms. See, [[Non-Windows Functionality]] for more information.&lt;br /&gt;
&lt;br /&gt;
[[File:Make-done-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
The build process is now complete. Run &lt;br /&gt;
 make&lt;br /&gt;
again to recompile. Or&lt;br /&gt;
 make &amp;lt;target&amp;gt;&lt;br /&gt;
to recompile only a specific target.&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:Manually_Build_BCI2000_on_Non-Windows_Platforms&amp;diff=10482</id>
		<title>Programming Howto:Manually Build BCI2000 on Non-Windows Platforms</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:Manually_Build_BCI2000_on_Non-Windows_Platforms&amp;diff=10482"/>
		<updated>2023-06-20T14:25:35Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: /* Choose Build Options */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Installing Dependencies==&lt;br /&gt;
There are three dependencies that need to be installed before you can compile BCI2000:&lt;br /&gt;
*ffmpeg (version 4.4.1, version 5 does not work with BCI2000)&lt;br /&gt;
*portaudio&lt;br /&gt;
*sdl2&lt;br /&gt;
These can be installed using the &lt;br /&gt;
 install_dependencies&lt;br /&gt;
script in the BCI2000 home directory. This will automatically detect your homebrew or it will download a portable version of homebrew in your BCI2000 directory. Then it will install the necessary dependencies. Alternatively, you can manually install them, and they will be automatically detected by CMake. If you have already installed homebrew, this can be done with&lt;br /&gt;
 brew install ffmpeg@4&lt;br /&gt;
 brew link ffmpeg@4&lt;br /&gt;
 brew install portaudio&lt;br /&gt;
 brew install sdl2&lt;br /&gt;
&lt;br /&gt;
==Configure BCI2000 for Compilation==&lt;br /&gt;
&lt;br /&gt;
===Run the CMake GUI===&lt;br /&gt;
Double-click &amp;quot;Configure.sh.cmd&amp;quot; in your BCI2000 build directory.&lt;br /&gt;
&lt;br /&gt;
[[File:Cmake-init-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Tell CMake which Qt installation to use===&lt;br /&gt;
Click &amp;quot;AddEntry&amp;quot; in the CMake window (&amp;lt;i&amp;gt;Note that checking off &amp;quot;Advanced&amp;quot; in Cmake is optional and does not impact the compilation&amp;lt;/i&amp;gt;) and enter the path to a Qt directory. If you installed Qt with homebrew, this can be found with&lt;br /&gt;
 brew list qt@5&lt;br /&gt;
The installation directory is only the part of the paths that are&lt;br /&gt;
 .../hombrew/Cellar/qt@5/&amp;lt;version&amp;gt;&lt;br /&gt;
Use everything up to the version and nothing past it.&lt;br /&gt;
Use CMAKE_PREFIX_PATH as the name for the new entry. Be aware that the entry&#039;s name is case sensitive. &amp;lt;b&amp;gt;Currently, on non-windows platform, Qt 5 is the only version that is supported.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Cmake-add-cache-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Configuration===&lt;br /&gt;
In the CMake window, click &amp;quot;Configure&amp;quot; and choose a generator that is consistent with your compiler. This tutorial will be using Unix Makefiles. Then click &amp;quot;Done&amp;quot; to perform the configuration step. &lt;br /&gt;
[[File:Cmake-generators-non-windows.png|700px]]&lt;br /&gt;
&amp;lt;br&amp;gt;You will see a list of targets scrolling by, and a number of new entries in the variable list at the top of the window, marked in red.&lt;br /&gt;
&lt;br /&gt;
===Choose Build Options===&lt;br /&gt;
Make sure the &amp;quot;Grouped&amp;quot; checkbox is checked, and configure the build by customizing values in the &amp;quot;BUILD&amp;quot; group, &amp;quot;EXTENSIONS&amp;quot; group,  and &amp;quot;USE&amp;quot; group. &lt;br /&gt;
[[File:Cmake-configured-non-windows.png|700px]]&lt;br /&gt;
If running on an ARM based apple machine, make sure that &amp;quot;USE_MACOS_APPLICATION_BUNDLES&amp;quot; is disabled to ensure that the executables can be run.&lt;br /&gt;
&lt;br /&gt;
===Generate Makefiles===&lt;br /&gt;
Then, click &amp;quot;Generate&amp;quot; to create build files. When CMake displays its &amp;quot;Generating done&amp;quot; message, your BCI2000 build directory will now contain a Makefile (or a project file for your compiler of chioce), as well as a number of additional CMake-generated files.&lt;br /&gt;
&lt;br /&gt;
[[File:Cmake-done-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
==Compile BCI2000==&lt;br /&gt;
===Open Terminal===&lt;br /&gt;
Open a new terminal window and navigate to your BCI2000 build directory.&lt;br /&gt;
&lt;br /&gt;
[[File:terminal-bulid-directory-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Build Makefiles===&lt;br /&gt;
Run:&lt;br /&gt;
 make&lt;br /&gt;
from your BCI2000 build directory. Once this is finished your BCI2000 prog directory will contain a number of executables, one for each module, plus a few helper executables. Not everything works the same or, in some cases, at all on non-windows platforms. See, [[Non-Windows Functionality]] for more information.&lt;br /&gt;
&lt;br /&gt;
[[File:Make-done-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
The build process is now complete. Run &lt;br /&gt;
 make&lt;br /&gt;
again to recompile. Or&lt;br /&gt;
 make &amp;lt;target&amp;gt;&lt;br /&gt;
to recompile only a specific target.&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:Manually_Build_BCI2000_on_Non-Windows_Platforms&amp;diff=10481</id>
		<title>Programming Howto:Manually Build BCI2000 on Non-Windows Platforms</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:Manually_Build_BCI2000_on_Non-Windows_Platforms&amp;diff=10481"/>
		<updated>2023-06-20T14:23:47Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: /* Perform the configuration step */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Installing Dependencies==&lt;br /&gt;
There are three dependencies that need to be installed before you can compile BCI2000:&lt;br /&gt;
*ffmpeg (version 4.4.1, version 5 does not work with BCI2000)&lt;br /&gt;
*portaudio&lt;br /&gt;
*sdl2&lt;br /&gt;
These can be installed using the &lt;br /&gt;
 install_dependencies&lt;br /&gt;
script in the BCI2000 home directory. This will automatically detect your homebrew or it will download a portable version of homebrew in your BCI2000 directory. Then it will install the necessary dependencies. Alternatively, you can manually install them, and they will be automatically detected by CMake. If you have already installed homebrew, this can be done with&lt;br /&gt;
 brew install ffmpeg@4&lt;br /&gt;
 brew link ffmpeg@4&lt;br /&gt;
 brew install portaudio&lt;br /&gt;
 brew install sdl2&lt;br /&gt;
&lt;br /&gt;
==Configure BCI2000 for Compilation==&lt;br /&gt;
&lt;br /&gt;
===Run the CMake GUI===&lt;br /&gt;
Double-click &amp;quot;Configure.sh.cmd&amp;quot; in your BCI2000 build directory.&lt;br /&gt;
&lt;br /&gt;
[[File:Cmake-init-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Tell CMake which Qt installation to use===&lt;br /&gt;
Click &amp;quot;AddEntry&amp;quot; in the CMake window (&amp;lt;i&amp;gt;Note that checking off &amp;quot;Advanced&amp;quot; in Cmake is optional and does not impact the compilation&amp;lt;/i&amp;gt;) and enter the path to a Qt directory. If you installed Qt with homebrew, this can be found with&lt;br /&gt;
 brew list qt@5&lt;br /&gt;
The installation directory is only the part of the paths that are&lt;br /&gt;
 .../hombrew/Cellar/qt@5/&amp;lt;version&amp;gt;&lt;br /&gt;
Use everything up to the version and nothing past it.&lt;br /&gt;
Use CMAKE_PREFIX_PATH as the name for the new entry. Be aware that the entry&#039;s name is case sensitive. &amp;lt;b&amp;gt;Currently, on non-windows platform, Qt 5 is the only version that is supported.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Cmake-add-cache-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Configuration===&lt;br /&gt;
In the CMake window, click &amp;quot;Configure&amp;quot; and choose a generator that is consistent with your compiler. This tutorial will be using Unix Makefiles. Then click &amp;quot;Done&amp;quot; to perform the configuration step. &lt;br /&gt;
[[File:Cmake-generators-non-windows.png|700px]]&lt;br /&gt;
&amp;lt;br&amp;gt;You will see a list of targets scrolling by, and a number of new entries in the variable list at the top of the window, marked in red.&lt;br /&gt;
&lt;br /&gt;
===Choose Build Options===&lt;br /&gt;
Make sure the &amp;quot;Grouped&amp;quot; checkbox is checked, and configure the build by customizing values in the &amp;quot;BUILD&amp;quot; group, &amp;quot;EXTENSIONS&amp;quot; group,  and &amp;quot;USE&amp;quot; group. &lt;br /&gt;
[[File:Cmake-configured-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Generate Makefiles===&lt;br /&gt;
Then, click &amp;quot;Generate&amp;quot; to create build files. When CMake displays its &amp;quot;Generating done&amp;quot; message, your BCI2000 build directory will now contain a Makefile (or a project file for your compiler of chioce), as well as a number of additional CMake-generated files.&lt;br /&gt;
&lt;br /&gt;
[[File:Cmake-done-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
==Compile BCI2000==&lt;br /&gt;
===Open Terminal===&lt;br /&gt;
Open a new terminal window and navigate to your BCI2000 build directory.&lt;br /&gt;
&lt;br /&gt;
[[File:terminal-bulid-directory-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Build Makefiles===&lt;br /&gt;
Run:&lt;br /&gt;
 make&lt;br /&gt;
from your BCI2000 build directory. Once this is finished your BCI2000 prog directory will contain a number of executables, one for each module, plus a few helper executables. Not everything works the same or, in some cases, at all on non-windows platforms. See, [[Non-Windows Functionality]] for more information.&lt;br /&gt;
&lt;br /&gt;
[[File:Make-done-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
The build process is now complete. Run &lt;br /&gt;
 make&lt;br /&gt;
again to recompile. Or&lt;br /&gt;
 make &amp;lt;target&amp;gt;&lt;br /&gt;
to recompile only a specific target.&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=BCI2000_Hyperscanning&amp;diff=10448</id>
		<title>BCI2000 Hyperscanning</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=BCI2000_Hyperscanning&amp;diff=10448"/>
		<updated>2023-06-14T22:26:32Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;BCI2000 Hyperscanning is a multiplayer simulation, a program that is synchronized over multiple computers, that supports the connection of two or more clients, the computers that are involved in the simulation. BCI2000 Hyperscanning also has subjects, which are the people that are using the client computers.&lt;br /&gt;
&lt;br /&gt;
In a multiplayer simulation, each client involved must know the current state of the game. This game state allows each client to determine the output that is shown to the user. In order for each client to display the same game to each user, each client must have the same game state. The game state is stored as a collection of state variables in a state machine.&lt;br /&gt;
A state machine is a set of variables, or states, that correspond with values. In essence, it is a simple database. The data in the database describes the state of the game (see figure \ref{fig:gamestate}).&lt;br /&gt;
&lt;br /&gt;
BCI2000 Hyperscanning has a master state machine that is stored on a centralized back-end server and one state machine for each client. Each client is connected to the back-end server through a TCP socket to ensure that each connection is maintained and everything that is sent is received. The clients output a stimulus to the user based on their state machines, and update their state machines based on user inputs. When one client updates its state machine, the server saves the game state in its master state machine and updates the other clients (see figure \ref{fig:gamestateupdate}).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:GameStateFigure.png|center]]&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Game State.&#039;&#039;&#039; The game state shows synchrony between the master game state, which is stored on the server, and the client game states.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:GameStateUpdateFigure.png|center]]&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Game State Updates.&#039;&#039;&#039; The game state updates (bottom) show a typical interaction that would result in a game state update to the master game state and the ensuing update to the other client(s). In this example, the user clicks, indicating they would like to place a marker in the tic-tac-toe game, and this triggers a local game state update. This local game state update is sent to the server. The server saves the update and synchronizes the remaining client(s). After the interaction has concluded, each client is synchronized.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[File:StateUpdatesFigure.png|center]]&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Game State Update Scenarios.&#039;&#039;&#039; In scenario 1, the client updated its game state locally because of a user mouse press. This caused synchronization between it and the master game state to be lost. In this scenario, the client updates the master game state to match its game state. In scenario 2, a different client updated the master game state because of a user mouse press. This caused synchronization between the first client and the master game state to be lost. In this scenario, the server updates the first client to match its game state.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Server ==&lt;br /&gt;
The purpose of the server, or back-end, is to store, update, and distribute a master list of states. It synchronizes each of the client&#039;s state machines, so that each client displays the same game. &lt;br /&gt;
&lt;br /&gt;
At a given time, one of the clients may have a state variable set to a value that is different from the value that the server has that state set to. At this point there are two possibilities. If that state was changed based on user inputs, then the server will update its state machine to reflect that user input. Otherwise, if the client has an old value, one that has been changed by another client, then the server will update the client with the new value of the state, so that each client is synchronized (see figure \ref{fig:gamestateupdatescenarios}).&lt;br /&gt;
&lt;br /&gt;
In addition to synchronizing states between clients, the backend must also synchronize many initial parameters to ensure that the exact same experiment is being run for each subject, e.g. the order of stimulus images needs to be synchronized. To solve this, the server contains a BCI2000 parameter file that is sent to each client when it connects to the server. This also serves as a greeting message to ensure that the connection is functioning before the experiment begins.&lt;br /&gt;
&lt;br /&gt;
The server application can be run from any mac or linux computer, whether it is local to one of the clients or in the cloud, as long as it is configured to allow TCP traffic. It is a collection of c++ classes and methods that are implemented into an application file. This application file is then run on the server computer. The server is not an instance of BCI2000. Rather, it is a separate application that interacts with client instances of BCI2000. &lt;br /&gt;
&lt;br /&gt;
While the idea for this hyperscanning architecture propagated from one experimental design, we ensured that this technology was robust enough to be used reused for any experiment, even if it is radically different from our initial one. The core of the back-end is simple and abstracted. It is a state machine that can be updated from clients and will propagate those updates to other clients. This simplicity means that the central parts of the back-end will work for any experimental paradigm. The simplicity of the core also allows for a more specific framework to be built surrounding the core, should that be necessary for a specific application. &lt;br /&gt;
&lt;br /&gt;
For each paradigm, an application file is implemented on the server. This application file will always contain the basic backend framework, like connecting to clients and running the actual data exchange loop, but it can also contain more specific instructions. For example, if parameters need to be randomly generated and synchronized across clients the core design is flexible enough to allow that to be built. Parameters can be added to the previously mentioned parameter file through the application file to solve this particular example. If there is a paradigm requiring more complex changes to the standard backend, the core can also be broken down into its individual steps to allow that.  &lt;br /&gt;
&lt;br /&gt;
The backend runs in a continuous loop of data exchanges with the clients. This loop continues for as long as the experiment runs. The end to the session, and thus the loop, is singaled by one of the clients breaking its connection with the server. &lt;br /&gt;
&lt;br /&gt;
Even though a client disconnects, the experiment may not be concluded. There could have been a crash, internet issues, or the investigator may have wanted to pause the experiment, but the server cannot continue operating properly after a client has disconnected. To solve this issue, the application file can access the state machine after the loop has ended, and save any of the states that are necessary to redetermine the experimental state after a restart. These values can then be passed to BCI2000 as parameters when it is restarted. For example, the trial number can be saved and passed to BCI2000 as an initial trial number parameter (see figure \ref{fig:pause}).&lt;br /&gt;
&lt;br /&gt;
[[File:PauseFigure.png|center]]&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Example paradigm with pause feature.&#039;&#039;&#039; This is a stimulus presentation paradigm, with a progression of faces being shown to the subject. During the first recording session, the subject gets through the first two trials before the session ends. The current trial number is saved to the server. During the next recording session, the server sends the current trial number, three, to the client; the client begins the session at trial number three and completes the paradigm.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Server Loop ===&lt;br /&gt;
The loop has three main steps (see figure \ref{fig:serverloop}). First, the server updates any states changed by the clients. Second, the server reconciles all of the updated states. Third, the server sends updated states back to the clients. &lt;br /&gt;
&lt;br /&gt;
[[File:ReconcilliationFigure.png|center]]&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Progression of state updates over time.&#039;&#039;&#039; Each client sends state updates, indicated by black arrows, to the server-side-client state machines, indicated by pink arrows. The server side state machines send the state updates to the master state machine. These state updates include conflicting information; the master state machine saves the state update from client 1 and disregards the conflicting update from client 2. The server sends the changed states, indicated by triangular arrows and blue ovals, back to the server-side-client state machines. The server-side-client state machines send their changed states back to the clients.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==== Client Updates ====&lt;br /&gt;
&lt;br /&gt;
In this step, the server simply waits for at least one of the clients to send states that were changed locally. If a client has not sent any data, then the server will wait for 2ms before checking another client. The server saves the data sent by the client in a state machine that tracks the current values of the states on each client. These are the server-side-client state machines.&lt;br /&gt;
&lt;br /&gt;
==== Reconciliation ====&lt;br /&gt;
In this step, the server decides which states to save and prepares the updates to send to each client. After each client sends its updates, the server-side-client machines are different from the master state machine and from each other, but they are synchronized with their respective clients. The server has to synchronize all of these state machines by saving client changes to the master state machine and sending updates to the clients, but it is necessary to save only one version of each state and to send only updates with new information. If the server repeats state updates by sending the same update twice or by echoing a state change back to the client that sent it, that state will be changed at multiple times for that client, which can cause irregularities and bugs. %Tracker state machines, which track the changes when a state machine is updated, are used to ensure that only actual changes are sent to the clients. One tracker is used to determine all the changes to the master state machine from the client updates. These changes are then used to update the server-side-client state machines. The changes to the server-side-client state machines are only the updates from other clients that were saved as master states, so they are then used to update the actual client state machines.&lt;br /&gt;
&lt;br /&gt;
To solve this, each state must pass two tests to get sent to a client. First, it must have been saved to the master state machine. Second, it must have been sent by a different client. These tests are implemented using tracker state machines, which track the changes that occur when a state machine is updated. For the first test, the server updates the master state machine from the server-side-client state machines and tracks the changes. For the second test, the changes to the master state machine are used to update the server-side-client state machines, and the changes from this interaction are tracked. The changes to the server-side-client state machines pass both tests, because they were changed on the master state machine (they were saved to the master state machine) and one of the client state machines (they weren&#039;t sent by that client because, in that case, they would have already been updated). These changes can be sent to the clients.&lt;br /&gt;
&lt;br /&gt;
==== Update Clients ====&lt;br /&gt;
This final step is the opposite of the first step. The server sends the prepared states to the clients. After this step, the loop repeats, and the server waits for the client to send updates again. &lt;br /&gt;
&lt;br /&gt;
== Clients ==&lt;br /&gt;
The purpose of the clients is to display the stimulus to the subject. Additionally, it is responsible for actually calculating the values of the game states. Each client is a separate instance of BCI2000, which are run on separate computers. They can be next to each other or hundreds of miles apart depending on the needs of the experiment.&lt;br /&gt;
&lt;br /&gt;
Once again, the structure is designed to be robust and reusable. To this end, the client exists in two pieces. The true frontend, which is responsible for calculating state values and outputting the stimulus, and the network logger, which is responsible for communication with the server. The true frontend is designed as a typical BCI2000 experiment, and thus will be different for every experiment. The network logger contains everything that will be the exact same for every BCI2000 Hyperscanning experiment. Thus, the network logger can be reused, while the true frontend is redesigned for every new experiment.&lt;br /&gt;
&lt;br /&gt;
The network logger is a part of the hyperscanning application base, which is a c++ class that a hyperscanning paradigm can be built upon. The hyperscanning application base will connect the network logger to the application module. &lt;br /&gt;
&lt;br /&gt;
BCI2000 has its own built in state machine. The network logger seamlessly updates a predefined set of these BCI2000 states based on server activity and the activity of other clients. It translates server data into BCI2000 states. The list of states that are updated by the network logger is defined in a BCI2000 parameter called shared states that contains both the names and the sizes of each of the states that the designer wants to be synchronized amongst the clients. To ensure that the states are sent rapidly, only the necessary states should be sent between clients, so they must be defined in this parameter. Other BCI2000 states will not be synchronized.&lt;br /&gt;
&lt;br /&gt;
=== Client Loops ===&lt;br /&gt;
Much like the server, the network logger loops, however, in order to conform with BCI2000 two distinct loops are utilized. One of them is synchronous with the rest of BCI2000. BCI2000 only allows its states to be changed during specific phases, so one of the loops must be synchronized with BCI2000. %The limitations of BCI2000 states require that state changes occur only during a specific time period, which necessitates synchronizing the loop with BCI2000. &lt;br /&gt;
While BCI2000 has a type of state that can be written to asynchronously, called an event, they are added to a queue and changed at a later time. This means the network logger cannot differentiate changes it made from changes the frontend made, so it doesn&#039;t know which changes to send to the server. The other loop is asynchronous, and makes use of multi-threading and parallel processing to increase the speed that data transfers can be made at, ensuring the greatest possible synchronicity between clients.&lt;br /&gt;
&lt;br /&gt;
Because these loops are both operating on the same data, i.e. the states that need to be changed, there is the risk of data corruption if both try to operate at the same time. The data is stored in mutexed buffers to ensure that does not happen. Mutexed buffers can only be written to or read by a single source at a time. If multiple sources try to access a mutexed buffer, one of them must wait for the other to finish its operation.&lt;br /&gt;
&lt;br /&gt;
Two buffers are shared between the two loops (see figure \ref{fig:clientloops}). One is a state machine that contains the name and value of each shared state, along with whether or not the state has a change from the server that hasn&#039;t been updated to the BCI2000 states, and the other is a message for the server that contains the states that have been updated by the frontend.&lt;br /&gt;
&lt;br /&gt;
[[File:clientloopsfigure.png|center]]&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Synchronous and asynchronous client loops and their data exchanges.&#039;&#039;&#039; The client updates a state, e.g. they indicate their move in tic-tac-toe with a mouse click, and the synchronous client loop adds that change to the message for the server. The asynchronous loop sends the message to the server. The asynchronous loop continues looping until it gets a response from the server. When it gets a response from the server, e.g. the other client&#039;s move, it adds it to the changed states buffer. The synchronous loop saves the changes in the changed states buffer to the BCI2000 state machine.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==== Synchronous Loop ====&lt;br /&gt;
&lt;br /&gt;
The synchronous loop first updates all of the BCI2000 states that have been changed by the server. %to the value sent by the server. &lt;br /&gt;
The loop then determines if any of the states in the mutexed state machine are different from their BCI2000 counterpart. Because all of the states that were different from BCI2000 because of a server update were just updated, all of the remaining discrepancies must be due to a client change. These are then recorded in the message for the server. &lt;br /&gt;
&lt;br /&gt;
It is very important for analyzing the experiment that the investigator knows when states were changed in relation to the recorded data. This could be complicated when states are being sent over the internet with delays and lag, but the network logger and BCI2000 radically simplify it. The important timestamp to record is when the state had an effect on the actual stimulus, because this is when it can have an effect on the subject. The timestamp of BCI2000 states is recorded whenever they are changed, and it is the BCI2000 states that have an effect on the stimulus. It is also BCI2000 that is providing the timestamps for the recorded data, therefore those timestamps will provide an accurate comparison between state changes and recorded data.&lt;br /&gt;
&lt;br /&gt;
==== Asynchronous Loop ====&lt;br /&gt;
&lt;br /&gt;
The asynchronous loop first sends the mutexed message to the server. If the message is empty, it doesn&#039;t send anything. This is the message that the server waits for in section 2.1.1. The loop then waits for a message from the server with the changes other clients have made. It waits 2ms for the server before moving on. This is the message the server sends in section 2.1.3. The loop then records these changes in the mutexed state machine and flags that they have a change from the server.&lt;br /&gt;
&lt;br /&gt;
=== Client Initialization ===&lt;br /&gt;
&lt;br /&gt;
The client initializes its connection with the server during the AutoConfig phase of BCI2000. This occurs after the Set Config button is pressed. The client first ensures that it hasn&#039;t already established a connection with the server, then it connects to the server. It uses user defined parameters to determine the IP address and port of the server application. The port of the server is defined by the designer in the server application file. The client then waits for the server to send an initial message that contains a client number and initial parameters. The client number is an id for the client to use to differentiate itself from other clients. For example, if each subject plays a different role in the paradigm, then the client number can be used to differentiate between roles. The parameters are then used to set BCI2000&#039;s parameters.&lt;br /&gt;
&lt;br /&gt;
== Example Paradigm Design ==&lt;br /&gt;
A BCI2000 Hyperscanning paradigm is designed very similarly to a typical BCI2000 paradigm with a couple key differences. First, states we want to be shared with other clients must be stated in the batch file, either under the optional parameter SharedStates (for states we want to be shared that BCI2000 Hyperscanning will define for us) or the optional parameter PreDefinedSharedStates (for states we want to be shared that we will define ourselves). Second, instead of the regular BCI2000 methods, i.e. Publish, Preflight, Process, etc., we use Hyperscanning Application Base methods, which are prefixed with Shared, i.e. SharedPublish, SharedPreflight, SharedProcess, etc.. The BCI2000 Hyperscanning methods behave in the exact same way, except they also call the client loops which interact with the server.&lt;br /&gt;
&lt;br /&gt;
=== Turn Based Stimulus ===&lt;br /&gt;
&lt;br /&gt;
The well-known game Tic-Tac-Toe is an example of a turn based game. One player takes their turn, then the other player takes their turn. Each turn is taken after the previous one, with no overlap in timing. Here is our implementation of Tic-Tac-Toe to show how a turn based game works with BCI2000 hyperscanning:&lt;br /&gt;
&lt;br /&gt;
TicTacToe.cpp:&lt;br /&gt;
 #include &amp;quot;TicTacToe.h&amp;quot;&lt;br /&gt;
 #include &amp;quot;Shapes.h&amp;quot;&lt;br /&gt;
 #include &amp;quot;TextField.h&amp;quot;&lt;br /&gt;
 #include &amp;lt;limits&amp;gt;&lt;br /&gt;
 #include &amp;quot;BCIEvent.h&amp;quot;&lt;br /&gt;
 #include &amp;lt;string&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 //Shared States&lt;br /&gt;
 //grid, 32&lt;br /&gt;
 //turn, 8&lt;br /&gt;
 //x, 8&lt;br /&gt;
 //y, 8&lt;br /&gt;
 &lt;br /&gt;
 RegisterFilter( TicTacToe, 3 );&lt;br /&gt;
 &lt;br /&gt;
 TicTacToe::TicTacToe() : winText( NULL ), highlight( NULL ), tiles( NULL ), board( NULL ), mrDisplay( Window() ) {&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 void TicTacToe::SharedPublish() {&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 void TicTacToe::SharedPreflight( const SignalProperties&amp;amp; Input, SignalProperties&amp;amp; Output ) const {&lt;br /&gt;
 	State( &amp;quot;grid&amp;quot; );&lt;br /&gt;
 	State( &amp;quot;turn&amp;quot; );&lt;br /&gt;
 	State( &amp;quot;ClientNumber&amp;quot; );&lt;br /&gt;
 	State( &amp;quot;KeyDown&amp;quot; );&lt;br /&gt;
 	State( &amp;quot;x&amp;quot; );&lt;br /&gt;
 	State( &amp;quot;y&amp;quot; );&lt;br /&gt;
 &lt;br /&gt;
 	Parameter( &amp;quot;SampleBlockSize&amp;quot; );&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 void TicTacToe::SharedInitialize( const SignalProperties&amp;amp; Input, const SignalProperties&amp;amp; Output ) {&lt;br /&gt;
 	ApplicationBase::Initialize( Input, Output );&lt;br /&gt;
 &lt;br /&gt;
 	board = new ImageStimulus( mrDisplay );&lt;br /&gt;
 	board-&amp;gt;SetObjectRect( { 0.f, 0.f, 1.f, 1.f } );&lt;br /&gt;
 	board-&amp;gt;SetScalingMode( GUI::ScalingMode::AdjustHeight );&lt;br /&gt;
 	board-&amp;gt;SetRenderingMode( GUI::RenderingMode::Transparent );&lt;br /&gt;
 	board-&amp;gt;SetFile( &amp;quot;../tasks/hyperscanning_test/tictactoe.png&amp;quot; );&lt;br /&gt;
 	board-&amp;gt;SetZOrder( 12 );&lt;br /&gt;
 &lt;br /&gt;
 	winText = new TextField( mrDisplay );&lt;br /&gt;
 	winText-&amp;gt;SetVisible( true );&lt;br /&gt;
 	winText-&amp;gt;SetObjectRect( { 0.2f, 0.4f, 0.8f, 0.6f } );&lt;br /&gt;
 	board-&amp;gt;SetZOrder( 1 );&lt;br /&gt;
 &lt;br /&gt;
 	tiles = ( ImageStimulus** ) malloc( sizeof( ImageStimulus ) * 9 );&lt;br /&gt;
 	for ( int i = 0; i &amp;lt; 9; i++ ) {&lt;br /&gt;
 		tiles[ i ] = new ImageStimulus( mrDisplay );&lt;br /&gt;
 		int x = i % 3;&lt;br /&gt;
 		int y = i / 3;&lt;br /&gt;
 		tiles[ i ]-&amp;gt;SetObjectRect( { x / 3.f, y / 3.f, x / 3.f + 0.33f, y / 3.f + 0.33f } );&lt;br /&gt;
 		tiles[ i ]-&amp;gt;SetScalingMode( GUI::ScalingMode::AdjustBoth );&lt;br /&gt;
 		tiles[ i ]-&amp;gt;SetRenderingMode( GUI::RenderingMode::Opaque );&lt;br /&gt;
 		tiles[ i ]-&amp;gt;SetZOrder( i + 2 );&lt;br /&gt;
 	}&lt;br /&gt;
 &lt;br /&gt;
 	highlight = new ImageStimulus( mrDisplay );&lt;br /&gt;
 	highlight-&amp;gt;SetObjectRect( { 0.f, 0.f, 0.33f, 0.33f } );&lt;br /&gt;
 	highlight-&amp;gt;SetScalingMode( GUI::ScalingMode::AdjustBoth );&lt;br /&gt;
 	highlight-&amp;gt;SetRenderingMode( GUI::RenderingMode::Transparent );&lt;br /&gt;
 	highlight-&amp;gt;SetFile( &amp;quot;../tasks/hyperscanning_test/highlight.png&amp;quot; );&lt;br /&gt;
 	highlight-&amp;gt;SetZOrder( 11 );&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 void TicTacToe::SharedProcess( const GenericSignal&amp;amp; Input, GenericSignal&amp;amp; Output ) {&lt;br /&gt;
 	board-&amp;gt;Present();&lt;br /&gt;
 	highlight-&amp;gt;Present();&lt;br /&gt;
 	for ( int i = 0; i &amp;lt; 9; i++ ) {&lt;br /&gt;
 		tiles[ i ]-&amp;gt;Present();&lt;br /&gt;
 	}&lt;br /&gt;
 &lt;br /&gt;
 	if ( State( &amp;quot;turn&amp;quot; ) == 3 ) {&lt;br /&gt;
 		if ( CheckKeyPress( &amp;quot;KeyDown&amp;quot;, 32 ) ) { //Space&lt;br /&gt;
 			Reset();&lt;br /&gt;
 		}&lt;br /&gt;
 	}&lt;br /&gt;
 &lt;br /&gt;
 	if ( State( &amp;quot;ClientNumber&amp;quot; ) == State( &amp;quot;turn&amp;quot; ) ) {&lt;br /&gt;
 		if ( CheckKeyPress( &amp;quot;KeyDown&amp;quot;, 38 ) &amp;amp;&amp;amp; State( &amp;quot;y&amp;quot; ) &amp;gt;= 1 ) { //Up&lt;br /&gt;
 			State( &amp;quot;y&amp;quot; ) = State( &amp;quot;y&amp;quot; ) - 1;&lt;br /&gt;
 		}&lt;br /&gt;
 &lt;br /&gt;
 		if ( CheckKeyPress( &amp;quot;KeyDown&amp;quot;, 40 ) &amp;amp;&amp;amp; State( &amp;quot;y&amp;quot; ) &amp;lt;= 1 ) { //Down&lt;br /&gt;
 			State( &amp;quot;y&amp;quot; ) = State( &amp;quot;y&amp;quot; ) + 1;&lt;br /&gt;
 		}&lt;br /&gt;
 &lt;br /&gt;
 		if ( CheckKeyPress( &amp;quot;KeyDown&amp;quot;, 37 ) &amp;amp;&amp;amp; State( &amp;quot;x&amp;quot; ) &amp;gt;= 1 ) { //Left&lt;br /&gt;
 			State( &amp;quot;x&amp;quot; ) = State( &amp;quot;x&amp;quot; ) - 1;&lt;br /&gt;
 		}&lt;br /&gt;
 &lt;br /&gt;
 		if ( CheckKeyPress( &amp;quot;KeyDown&amp;quot;, 39 ) &amp;amp;&amp;amp; State( &amp;quot;x&amp;quot; ) &amp;lt;= 1 ) { //Right&lt;br /&gt;
 			State( &amp;quot;x&amp;quot; ) = State( &amp;quot;x&amp;quot; ) + 1;&lt;br /&gt;
 		}&lt;br /&gt;
 &lt;br /&gt;
 		if ( CheckKeyPress( &amp;quot;KeyDown&amp;quot;, 32 ) ) { //Space&lt;br /&gt;
 			long xflag = 1UL &amp;lt;&amp;lt; ( 2 * ( State( &amp;quot;y&amp;quot; ) * 3 + State( &amp;quot;x&amp;quot; ) ) );&lt;br /&gt;
 			long oflag = 1UL &amp;lt;&amp;lt; ( 2 * ( State( &amp;quot;y&amp;quot; ) * 3 + State( &amp;quot;x&amp;quot; ) ) + 1 );&lt;br /&gt;
 &lt;br /&gt;
 			if ( !( State( &amp;quot;grid&amp;quot; ) &amp;amp; xflag ) &amp;amp;&amp;amp; !( State( &amp;quot;grid&amp;quot; ) &amp;amp; oflag ) ) {&lt;br /&gt;
 				if ( State( &amp;quot;ClientNumber&amp;quot; ) == 0 ) {&lt;br /&gt;
 					State( &amp;quot;grid&amp;quot; ) = State( &amp;quot;grid&amp;quot; ) | xflag;&lt;br /&gt;
 					State( &amp;quot;turn&amp;quot; ) = 1;&lt;br /&gt;
 				}&lt;br /&gt;
 &lt;br /&gt;
 				else {&lt;br /&gt;
 					State( &amp;quot;grid&amp;quot; ) = State( &amp;quot;grid&amp;quot; ) | oflag;&lt;br /&gt;
 					State( &amp;quot;turn&amp;quot; ) = 0;&lt;br /&gt;
 				}&lt;br /&gt;
 			}&lt;br /&gt;
 		}&lt;br /&gt;
 	}&lt;br /&gt;
 &lt;br /&gt;
 	long flag = 1UL;&lt;br /&gt;
 	for ( int i = 0; i &amp;lt; 9; i++ ) {&lt;br /&gt;
 		if ( State( &amp;quot;grid&amp;quot; ) &amp;amp; flag ) {&lt;br /&gt;
 			tiles[ i ]-&amp;gt;SetFile( &amp;quot;../tasks/hyperscanning_test/x.png&amp;quot; );&lt;br /&gt;
 		}&lt;br /&gt;
 		flag &amp;lt;&amp;lt;= 1;&lt;br /&gt;
 		if ( State( &amp;quot;grid&amp;quot; ) &amp;amp; flag ) {&lt;br /&gt;
 			tiles[ i ]-&amp;gt;SetFile( &amp;quot;../tasks/hyperscanning_test/o.png&amp;quot; );&lt;br /&gt;
 		}&lt;br /&gt;
 		flag &amp;lt;&amp;lt;= 1;&lt;br /&gt;
 	}&lt;br /&gt;
 &lt;br /&gt;
 	long hwin = horizontal_win;&lt;br /&gt;
 	long vwin = vertical_win;&lt;br /&gt;
 	long dwin1 = diagonal_win_1;&lt;br /&gt;
 	long dwin2 = diagonal_win_2;&lt;br /&gt;
 &lt;br /&gt;
 	if ( ( State( &amp;quot;grid&amp;quot; ) &amp;amp; dwin1 ) == dwin1 || ( State( &amp;quot;grid&amp;quot; ) &amp;amp; dwin2 ) == dwin2 ) {&lt;br /&gt;
 		State( &amp;quot;turn&amp;quot; ) = 3;&lt;br /&gt;
 		winText-&amp;gt;SetText( &amp;quot;X Wins&amp;quot; );&lt;br /&gt;
 	}&lt;br /&gt;
 &lt;br /&gt;
 	dwin1 &amp;lt;&amp;lt;= 1;&lt;br /&gt;
 	dwin2 &amp;lt;&amp;lt;= 1;&lt;br /&gt;
 &lt;br /&gt;
 	if ( ( State( &amp;quot;grid&amp;quot; ) &amp;amp; dwin1 ) == dwin1 || ( State( &amp;quot;grid&amp;quot; ) &amp;amp; dwin2 ) == dwin2 ) {&lt;br /&gt;
 		State( &amp;quot;turn&amp;quot; ) = 3;&lt;br /&gt;
 		winText-&amp;gt;SetText( &amp;quot;O Wins&amp;quot; );&lt;br /&gt;
 	}&lt;br /&gt;
 &lt;br /&gt;
 	for ( int i = 0; i &amp;lt; 3; i++ ) {&lt;br /&gt;
 		if ( ( State( &amp;quot;grid&amp;quot; ) &amp;amp; hwin ) == hwin || ( State( &amp;quot;grid&amp;quot; ) &amp;amp; vwin ) == vwin ) {&lt;br /&gt;
 			State( &amp;quot;turn&amp;quot; ) = 3;&lt;br /&gt;
 			winText-&amp;gt;SetText( &amp;quot;X Wins&amp;quot; );&lt;br /&gt;
 		}&lt;br /&gt;
 &lt;br /&gt;
 		hwin &amp;lt;&amp;lt;= 1;&lt;br /&gt;
 		vwin &amp;lt;&amp;lt;= 1;&lt;br /&gt;
 &lt;br /&gt;
 		if ( ( State( &amp;quot;grid&amp;quot; ) &amp;amp; hwin ) == hwin || ( State( &amp;quot;grid&amp;quot; ) &amp;amp; vwin ) == vwin ) {&lt;br /&gt;
 			State( &amp;quot;turn&amp;quot; ) = 3;&lt;br /&gt;
 			winText-&amp;gt;SetText( &amp;quot;O Wins&amp;quot; );&lt;br /&gt;
 		}&lt;br /&gt;
 &lt;br /&gt;
 		hwin &amp;lt;&amp;lt;= 5;&lt;br /&gt;
 		vwin &amp;lt;&amp;lt;= 1;&lt;br /&gt;
 	}&lt;br /&gt;
 &lt;br /&gt;
 	highlight-&amp;gt;SetObjectRect( { State(&amp;quot;x&amp;quot;) / 3.f, State(&amp;quot;y&amp;quot;) / 3.f, (State(&amp;quot;x&amp;quot;) + 1) / 3.f, (State(&amp;quot;y&amp;quot;) + 1) / 3.f } );&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 bool TicTacToe::CheckKeyPress( std::string event_name, int value ) {&lt;br /&gt;
 	for ( unsigned int i = 0; i &amp;lt; Parameter( &amp;quot;SampleBlockSize&amp;quot; ); i++ ) {&lt;br /&gt;
 		if ( State( event_name )( i ) == value ) {&lt;br /&gt;
 			return true;&lt;br /&gt;
 		}&lt;br /&gt;
 	}&lt;br /&gt;
 	return false;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 void TicTacToe::Reset() {&lt;br /&gt;
 	State( &amp;quot;turn&amp;quot; ) = 0;&lt;br /&gt;
 	State( &amp;quot;grid&amp;quot; ) = 0;&lt;br /&gt;
 &lt;br /&gt;
 	delete board;&lt;br /&gt;
 	board = new ImageStimulus( mrDisplay );&lt;br /&gt;
 	board-&amp;gt;SetObjectRect( { 0.f, 0.f, 1.f, 1.f } );&lt;br /&gt;
 	board-&amp;gt;SetScalingMode( GUI::ScalingMode::AdjustHeight );&lt;br /&gt;
 	board-&amp;gt;SetRenderingMode( GUI::RenderingMode::Transparent );&lt;br /&gt;
 	board-&amp;gt;SetFile( &amp;quot;../tasks/hyperscanning_test/tictactoe.png&amp;quot; );&lt;br /&gt;
 	board-&amp;gt;SetZOrder( 12 );&lt;br /&gt;
 &lt;br /&gt;
 	delete winText;&lt;br /&gt;
 	winText = new TextField( mrDisplay );&lt;br /&gt;
 	winText-&amp;gt;SetVisible( true );&lt;br /&gt;
 	winText-&amp;gt;SetObjectRect( { 0.2f, 0.4f, 0.8f, 0.6f } );&lt;br /&gt;
 	board-&amp;gt;SetZOrder( 1 );&lt;br /&gt;
 &lt;br /&gt;
 	for ( int i = 0; i &amp;lt; 9; i++ ) {&lt;br /&gt;
 		delete tiles[ i ];&lt;br /&gt;
 	}&lt;br /&gt;
 	free( tiles );&lt;br /&gt;
 &lt;br /&gt;
 	tiles = ( ImageStimulus** ) malloc( sizeof( ImageStimulus ) * 9 );&lt;br /&gt;
 	for ( int i = 0; i &amp;lt; 9; i++ ) {&lt;br /&gt;
 		tiles[ i ] = new ImageStimulus( mrDisplay );&lt;br /&gt;
 		int x = i % 3;&lt;br /&gt;
 		int y = i / 3;&lt;br /&gt;
 		tiles[ i ]-&amp;gt;SetObjectRect( { x / 3.f, y / 3.f, x / 3.f + 0.33f, y / 3.f + 0.33f } );&lt;br /&gt;
 		tiles[ i ]-&amp;gt;SetScalingMode( GUI::ScalingMode::AdjustBoth );&lt;br /&gt;
 		tiles[ i ]-&amp;gt;SetRenderingMode( GUI::RenderingMode::Opaque );&lt;br /&gt;
 		tiles[ i ]-&amp;gt;SetZOrder( i + 2 );&lt;br /&gt;
 	}&lt;br /&gt;
 &lt;br /&gt;
 	delete highlight;&lt;br /&gt;
 &lt;br /&gt;
 	highlight = new ImageStimulus( mrDisplay );&lt;br /&gt;
 	highlight-&amp;gt;SetObjectRect( { 0.f, 0.f, 0.33f, 0.33f } );&lt;br /&gt;
 	highlight-&amp;gt;SetScalingMode( GUI::ScalingMode::AdjustBoth );&lt;br /&gt;
 	highlight-&amp;gt;SetRenderingMode( GUI::RenderingMode::Transparent );&lt;br /&gt;
 	highlight-&amp;gt;SetFile( &amp;quot;../tasks/hyperscanning_test/highlight.png&amp;quot; );&lt;br /&gt;
 	highlight-&amp;gt;SetZOrder( 11 );&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
TicTacToe.h&lt;br /&gt;
 #include &amp;quot;Shapes.h&amp;quot;&lt;br /&gt;
 #include &amp;quot;TextField.h&amp;quot;&lt;br /&gt;
 #include &amp;quot;ApplicationWindow.h&amp;quot;&lt;br /&gt;
 #include &amp;quot;ImageStimulus.h&amp;quot;&lt;br /&gt;
 #include &amp;quot;HyperscanningApplicationBase.h&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 class TicTacToe : public HyperscanningApplicationBase {&lt;br /&gt;
 	public:&lt;br /&gt;
 		TicTacToe();&lt;br /&gt;
 &lt;br /&gt;
 		void SharedPublish() override;&lt;br /&gt;
 &lt;br /&gt;
 		void SharedPreflight( const SignalProperties&amp;amp; Input, SignalProperties&amp;amp; Output ) const override;&lt;br /&gt;
 		void SharedInitialize( const SignalProperties&amp;amp; Input, const SignalProperties&amp;amp; Output ) override;&lt;br /&gt;
 		void SharedProcess( const GenericSignal&amp;amp; Input, GenericSignal&amp;amp; Output ) override;&lt;br /&gt;
 &lt;br /&gt;
 		bool CheckKeyPress( std::string, int );&lt;br /&gt;
 &lt;br /&gt;
 		void Reset();&lt;br /&gt;
 &lt;br /&gt;
 	private:&lt;br /&gt;
 		ApplicationWindow&amp;amp; mrDisplay;&lt;br /&gt;
 &lt;br /&gt;
 		ImageStimulus* board;&lt;br /&gt;
 		ImageStimulus** tiles;&lt;br /&gt;
 		ImageStimulus* highlight;&lt;br /&gt;
 &lt;br /&gt;
 		TextField* winText;&lt;br /&gt;
 &lt;br /&gt;
 		long horizontal_win = 21;&lt;br /&gt;
 		long vertical_win = 4161;&lt;br /&gt;
 		long diagonal_win_1 = 65793;&lt;br /&gt;
 		long diagonal_win_2 = 4368;&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
and TicTacToe.bat&lt;br /&gt;
 Change directory $BCI2000LAUNCHDIR&lt;br /&gt;
 Show window; Set title ${Extract file base $0}&lt;br /&gt;
 Reset system&lt;br /&gt;
 Startup system localhost&lt;br /&gt;
 Start executable SignalGenerator --local --LogKeyboard=1&lt;br /&gt;
 Start executable DummySignalProcessing --local&lt;br /&gt;
 Start executable TicTacToe --local --Port=1234 --IPAddress=192.168.1.102 --SharedStates=grid,32&amp;amp;turn,8&amp;amp;x,8&amp;amp;y,8&lt;br /&gt;
 Wait for Connected&lt;br /&gt;
 Load parameterfile &amp;quot;../parms/CommunicationTask/Communication_task_dual.prm&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Important Notes ==&lt;br /&gt;
The most are important sections to draw your attention to are:&lt;br /&gt;
&lt;br /&gt;
 if ( State( &amp;quot;ClientNumber&amp;quot; ) == State( &amp;quot;turn&amp;quot; ) ) {&lt;br /&gt;
&lt;br /&gt;
ClientNumber is a state that is automatically sent by the server. It is an id, between 0 and N, where N is the number of clients connected, that can be used to differentiate between each client without having to run a separate application on each. &amp;quot;turn&amp;quot; is a shared state between the clients. Shared states are accessed in the exact same way that a normal BCI2000 state is accessed. This way we can use shared states and the client number to determine which client should be placing their mark. &lt;br /&gt;
&lt;br /&gt;
 State( &amp;quot;turn&amp;quot; ) = 1;&lt;br /&gt;
&lt;br /&gt;
Shared states are also written to the exact same way as normal BCI2000 shared states. They will be automatically updated for the other clients.&lt;br /&gt;
&lt;br /&gt;
  Start executable TicTacToe --local --Port=1234 --IPAddress=192.168.1.102 --SharedStates=grid,32&amp;amp;turn,8&amp;amp;x,8&amp;amp;y,8&lt;br /&gt;
&lt;br /&gt;
This is where we define the states that we want to share with &amp;quot;--SharedStates=&amp;quot;. The format is:&lt;br /&gt;
 --SharedStates=&amp;lt;state-1&amp;gt;,&amp;lt;state-1-size&amp;gt;&amp;amp;&amp;lt;state-2&amp;gt;,&amp;lt;state-2-size&amp;gt;&amp;amp;&amp;lt;state-3&amp;gt;,&amp;lt;state-3-size&amp;gt;...&lt;br /&gt;
We can also define predefined shared states here in a similar way, but without the size (because the size is already defined), using:&lt;br /&gt;
 --PreDefinedSharedStates=&amp;lt;state-1&amp;gt;&amp;amp;&amp;lt;state-2&amp;gt;&amp;amp;&amp;lt;state-3&amp;gt;&lt;br /&gt;
&lt;br /&gt;
--Port and --IPAddress are additional parameters that tell the client where to find the server on the internet. All of these parameters can also be changed from the Config menu, and the client connects to the server after &amp;quot;Set Config&amp;quot; is pressed.&lt;br /&gt;
&lt;br /&gt;
=== Live Interaction Stimulus ===&lt;br /&gt;
&lt;br /&gt;
The classic video game pong is an example of live interaction. Both players can interact with the game simultaneously. There are no discrete turns. We implemented pong with BCI2000 hyperscanning to demonstrate a live interaction.&lt;br /&gt;
&lt;br /&gt;
pong.cpp&lt;br /&gt;
 #include &amp;quot;Pong.h&amp;quot;&lt;br /&gt;
 #include &amp;quot;Shapes.h&amp;quot;&lt;br /&gt;
 #include &amp;lt;limits&amp;gt;&lt;br /&gt;
 #include &amp;quot;BCIEvent.h&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 //Shared States&lt;br /&gt;
 //BallX 32&lt;br /&gt;
 //BallY 32&lt;br /&gt;
 //BallVX 8&lt;br /&gt;
 //BallVY 8&lt;br /&gt;
 //Player1Y 32&lt;br /&gt;
 //Player2Y 32&lt;br /&gt;
 //Player1Ready 1&lt;br /&gt;
 //Player2Ready 1&lt;br /&gt;
 //GamePhase 8&lt;br /&gt;
 //&lt;br /&gt;
 //Game Phases&lt;br /&gt;
 //0 : Instruction&lt;br /&gt;
 //1 : Game&lt;br /&gt;
 //2 : Between Rounds&lt;br /&gt;
 &lt;br /&gt;
 RegisterFilter( Pong, 3 );&lt;br /&gt;
 &lt;br /&gt;
 Pong::Pong() : player1Paddle( NULL ), player2Paddle( NULL ), ball( NULL ), mrDisplay( Window() ) {&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 void Pong::SharedPublish() {&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 void Pong::SharedPreflight( const SignalProperties&amp;amp; Input, SignalProperties&amp;amp; Output ) const {&lt;br /&gt;
 	State( &amp;quot;BallX&amp;quot; );&lt;br /&gt;
 	State( &amp;quot;BallY&amp;quot; );&lt;br /&gt;
 	State( &amp;quot;BallVX&amp;quot; );&lt;br /&gt;
 	State( &amp;quot;BallVY&amp;quot; );&lt;br /&gt;
 	State( &amp;quot;Player1Y&amp;quot; );&lt;br /&gt;
 	State( &amp;quot;Player2Y&amp;quot; );&lt;br /&gt;
 	State( &amp;quot;Player1Ready&amp;quot; );&lt;br /&gt;
 	State( &amp;quot;Player2Ready&amp;quot; );&lt;br /&gt;
 	State( &amp;quot;GamePhase&amp;quot; );&lt;br /&gt;
 	State(&amp;quot;ClientNumber&amp;quot;);&lt;br /&gt;
 //	State( &amp;quot;KeyDown&amp;quot; );&lt;br /&gt;
 	Parameter( &amp;quot;SampleBlockSize&amp;quot; );&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 void Pong::SharedInitialize( const SignalProperties&amp;amp; Input, const SignalProperties&amp;amp; Output ) {&lt;br /&gt;
 	player1Paddle = new RectangularShape( mrDisplay );&lt;br /&gt;
 	player1Paddle-&amp;gt;SetFillColor( RGBColor::Teal );&lt;br /&gt;
 	player1Paddle-&amp;gt;SetVisible( true );&lt;br /&gt;
 &lt;br /&gt;
 	player2Paddle = new RectangularShape( mrDisplay );&lt;br /&gt;
 	player2Paddle-&amp;gt;SetFillColor( RGBColor::Red );&lt;br /&gt;
 	player2Paddle-&amp;gt;SetVisible( true );&lt;br /&gt;
 &lt;br /&gt;
 	ball = new RectangularShape( mrDisplay );&lt;br /&gt;
 	ball-&amp;gt;SetFillColor( RGBColor::Black );&lt;br /&gt;
 	ball-&amp;gt;SetVisible( true );&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 void Pong::SharedStartRun() {&lt;br /&gt;
 	State( &amp;quot;BallX&amp;quot; ) = 500;&lt;br /&gt;
 	State( &amp;quot;BallY&amp;quot; ) = 500;&lt;br /&gt;
 	State( &amp;quot;Player1Y&amp;quot; ) = 200;&lt;br /&gt;
 	State( &amp;quot;Player2Y&amp;quot; ) = 800;&lt;br /&gt;
 	State( &amp;quot;BallVX&amp;quot; ) = 493;&lt;br /&gt;
 	State( &amp;quot;BallVY&amp;quot; ) = 497;&lt;br /&gt;
 	State( &amp;quot;GamePhase&amp;quot; ) = 2;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 void Pong::SharedProcess( const GenericSignal&amp;amp; Input, GenericSignal&amp;amp; Output ) {&lt;br /&gt;
 	if ( State( &amp;quot;GamePhase&amp;quot; ) == 1 ) {&lt;br /&gt;
 		if ( State( &amp;quot;ClientNumber&amp;quot; ) == 0 ) {&lt;br /&gt;
 			State( &amp;quot;BallX&amp;quot; ) = State( &amp;quot;BallX&amp;quot; ) + State( &amp;quot;BallVX&amp;quot; ) - 500;&lt;br /&gt;
 			State( &amp;quot;BallY&amp;quot; ) = State( &amp;quot;BallY&amp;quot; ) + State( &amp;quot;BallVY&amp;quot; ) - 500;&lt;br /&gt;
 &lt;br /&gt;
 			if ( State( &amp;quot;BallY&amp;quot; ) &amp;gt; 950 || State( &amp;quot;BallY&amp;quot; ) &amp;lt; 50 ) {&lt;br /&gt;
 				State( &amp;quot;BallVY&amp;quot; ) = 1000 - State( &amp;quot;BallVY&amp;quot; );&lt;br /&gt;
 			}&lt;br /&gt;
 &lt;br /&gt;
 			if ( State( &amp;quot;BallX&amp;quot; ) + 50 &amp;gt; 875 &amp;amp;&amp;amp; State( &amp;quot;BallX&amp;quot; ) - 50 &amp;lt; 925 &amp;amp;&amp;amp; State( &amp;quot;BallY&amp;quot; ) + 50 &amp;gt; State( &amp;quot;Player2Y&amp;quot; ) - 100 &amp;amp;&amp;amp; State( &amp;quot;BallY&amp;quot; ) - 50 &amp;lt; State( &amp;quot;Player2Y&amp;quot; ) + 100 ) {&lt;br /&gt;
 				State( &amp;quot;BallVX&amp;quot; ) = 1000 - State( &amp;quot;BallVX&amp;quot; );&lt;br /&gt;
 				State( &amp;quot;BallX&amp;quot; ) = 875 - 50;&lt;br /&gt;
 			}&lt;br /&gt;
 &lt;br /&gt;
 			if ( State( &amp;quot;BallX&amp;quot; ) + 50 &amp;gt; 75  &amp;amp;&amp;amp; State( &amp;quot;BallX&amp;quot; ) - 50 &amp;lt; 125 &amp;amp;&amp;amp; State( &amp;quot;BallY&amp;quot; ) + 50 &amp;gt; State( &amp;quot;Player1Y&amp;quot; ) - 100 &amp;amp;&amp;amp; State( &amp;quot;BallY&amp;quot; ) - 50 &amp;lt; State( &amp;quot;Player1Y&amp;quot; ) + 100 ) {&lt;br /&gt;
 				State( &amp;quot;BallVX&amp;quot; ) = 1000 - State( &amp;quot;BallVX&amp;quot; );&lt;br /&gt;
 				State( &amp;quot;BallX&amp;quot; ) = 125 + 50;&lt;br /&gt;
 			}&lt;br /&gt;
 &lt;br /&gt;
 			if ( State( &amp;quot;BallX&amp;quot; ) + 50 &amp;gt; 1000 || State( &amp;quot;BallX&amp;quot; ) - 50 &amp;lt; 0 ) {&lt;br /&gt;
 				State( &amp;quot;BallX&amp;quot; ) = 500;&lt;br /&gt;
 				State( &amp;quot;BallVY&amp;quot; ) = State( &amp;quot;BallVY&amp;quot; ) + 1;&lt;br /&gt;
 				State( &amp;quot;GamePhase&amp;quot; ) = 2;&lt;br /&gt;
 			}&lt;br /&gt;
 		}&lt;br /&gt;
 &lt;br /&gt;
 		if ( CheckKeyPress( &amp;quot;KeyDown&amp;quot;, 38 ) ) { //Up&lt;br /&gt;
 			if ( State( &amp;quot;ClientNumber&amp;quot; ) == 0 )&lt;br /&gt;
 				State( &amp;quot;Player1Y&amp;quot; ) = State( &amp;quot;Player1Y&amp;quot; ) - 30;&lt;br /&gt;
 			else &lt;br /&gt;
 				State( &amp;quot;Player2Y&amp;quot; ) = State( &amp;quot;Player2Y&amp;quot; ) - 30;&lt;br /&gt;
 		}&lt;br /&gt;
 &lt;br /&gt;
 		if ( CheckKeyPress( &amp;quot;KeyDown&amp;quot;, 40 ) ) { //Down&lt;br /&gt;
 			if ( State( &amp;quot;ClientNumber&amp;quot; ) == 0 )&lt;br /&gt;
 				State( &amp;quot;Player1Y&amp;quot; ) = State( &amp;quot;Player1Y&amp;quot; ) + 30;&lt;br /&gt;
 			else &lt;br /&gt;
 				State( &amp;quot;Player2Y&amp;quot; ) = State( &amp;quot;Player2Y&amp;quot; ) + 30;&lt;br /&gt;
 		}&lt;br /&gt;
 	}&lt;br /&gt;
 &lt;br /&gt;
 	if ( State( &amp;quot;GamePhase&amp;quot; ) == 2 ) {&lt;br /&gt;
 		if ( CheckKeyPress( &amp;quot;KeyDown&amp;quot;, 32 ) == 0 ) { //Space&lt;br /&gt;
 			if ( State( &amp;quot;ClientNumber&amp;quot; ) == 0 )&lt;br /&gt;
 				State( &amp;quot;Player1Ready&amp;quot; ) = 1;&lt;br /&gt;
 			else&lt;br /&gt;
 				State( &amp;quot;Player2Ready&amp;quot; ) = 1;&lt;br /&gt;
 		}&lt;br /&gt;
 &lt;br /&gt;
 		if ( State( &amp;quot;Player1Ready&amp;quot; ) == 1 &amp;amp;&amp;amp; State( &amp;quot;Player2Ready&amp;quot; ) == 1 ) {&lt;br /&gt;
 			State( &amp;quot;GamePhase&amp;quot; ) = 1;&lt;br /&gt;
 			State( &amp;quot;Player1Ready&amp;quot; ) = 0;&lt;br /&gt;
 			State( &amp;quot;Player2Ready&amp;quot; ) = 0;&lt;br /&gt;
 		}&lt;br /&gt;
 	}&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 	bciout &amp;lt;&amp;lt; &amp;quot;Ball: (&amp;quot; &amp;lt;&amp;lt; State(&amp;quot;BallX&amp;quot;) &amp;lt;&amp;lt; &amp;quot;, &amp;quot; &amp;lt;&amp;lt; State(&amp;quot;BallY&amp;quot;) &amp;lt;&amp;lt; &amp;quot;)&amp;quot;;&lt;br /&gt;
 	bciout &amp;lt;&amp;lt; &amp;quot;Player1: &amp;quot; &amp;lt;&amp;lt; State(&amp;quot;Player1Y&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 	GUI::Rect rect = { ( State( &amp;quot;BallX&amp;quot; ) / 1000.f ) - 0.05, ( State( &amp;quot;BallY&amp;quot; ) / 1000.f ) - 0.05, ( State( &amp;quot;BallX&amp;quot; ) / 1000.f ) + 0.05, ( State( &amp;quot;BallY&amp;quot; ) / 1000.f ) + 0.05 };&lt;br /&gt;
 	ball-&amp;gt;SetObjectRect( rect );&lt;br /&gt;
 &lt;br /&gt;
 	rect = { 0.075f, ( State( &amp;quot;Player1Y&amp;quot; ) / 1000.f ) - 0.1f, 0.125f, ( State( &amp;quot;Player1Y&amp;quot; ) / 1000.f ) + 0.1f };&lt;br /&gt;
 	player1Paddle-&amp;gt;SetObjectRect( rect );&lt;br /&gt;
 &lt;br /&gt;
 	rect = { 0.875f, ( State( &amp;quot;Player2Y&amp;quot; ) / 1000.f ) - 0.1f, 0.925f, ( State( &amp;quot;Player2Y&amp;quot; ) / 1000.f ) + 0.1f };&lt;br /&gt;
 	player2Paddle-&amp;gt;SetObjectRect( rect );&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 bool Pong::CheckKeyPress( std::string event_name, int value ) {&lt;br /&gt;
 	for ( unsigned int i = 0; i &amp;lt; Parameter( &amp;quot;SampleBlockSize&amp;quot; ); i++ ) {&lt;br /&gt;
 		if ( State( event_name )( i ) == value ) {&lt;br /&gt;
 			return true;&lt;br /&gt;
 		}&lt;br /&gt;
 	}&lt;br /&gt;
 	return false;&lt;br /&gt;
 }&lt;br /&gt;
pong.h&lt;br /&gt;
 #include &amp;quot;Shapes.h&amp;quot;&lt;br /&gt;
 #include &amp;quot;ApplicationWindow.h&amp;quot;&lt;br /&gt;
 #include &amp;quot;HyperscanningApplicationBase.h&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 class Pong : public HyperscanningApplicationBase {&lt;br /&gt;
 	public:&lt;br /&gt;
 		Pong();&lt;br /&gt;
 &lt;br /&gt;
 		void SharedPublish() override;&lt;br /&gt;
 &lt;br /&gt;
 		void SharedPreflight( const SignalProperties&amp;amp; Input, SignalProperties&amp;amp; Output ) const override;&lt;br /&gt;
 		void SharedInitialize( const SignalProperties&amp;amp; Input, const SignalProperties&amp;amp; Output ) override;&lt;br /&gt;
 		void SharedProcess( const GenericSignal&amp;amp; Input, GenericSignal&amp;amp; Output ) override;&lt;br /&gt;
 		void SharedStartRun() override;&lt;br /&gt;
 &lt;br /&gt;
 		bool CheckKeyPress( std::string event_name, int value );&lt;br /&gt;
 &lt;br /&gt;
 	private:&lt;br /&gt;
 		ApplicationWindow&amp;amp; mrDisplay;&lt;br /&gt;
 		RectangularShape* player1Paddle;&lt;br /&gt;
 		RectangularShape* player2Paddle;&lt;br /&gt;
 		RectangularShape* ball;&lt;br /&gt;
 };&lt;br /&gt;
and pong.bat&lt;br /&gt;
 Change directory $BCI2000LAUNCHDIR&lt;br /&gt;
 Show window; Set title ${Extract file base $0}&lt;br /&gt;
 Reset system&lt;br /&gt;
 Startup system localhost&lt;br /&gt;
 Start executable SignalGenerator --local --LogKeyboard=1&lt;br /&gt;
 Start executable DummySignalProcessing --local&lt;br /&gt;
 Start executable Pong --local --Port=1234 --IPAddress=192.168.1.102 --SharedStates=BallX,32&amp;amp;BallY,32&amp;amp;Player1Y,32&amp;amp;Player2Y,32&amp;amp;BallVX,32&amp;amp;BallVY,32&amp;amp;Player1Ready,8&amp;amp;Player2Ready,8&amp;amp;GamePhase,8&amp;amp;Player1Score,8&amp;amp;Player2Score,8&lt;br /&gt;
 Wait for Connected&lt;br /&gt;
 Load parameterfile &amp;quot;../parms/CommunicationTask/Communication_task_dual.prm&amp;quot;&lt;br /&gt;
&lt;br /&gt;
This behaves very similarly to the tic-tac-toe example, with the key difference being both clients can interact with states simultaneously, whereas in tic-tac-toe only one client was changing states at a time.&lt;br /&gt;
&lt;br /&gt;
Any processing of game states, for example changing the position of the ball in pong, can occur on either the clients or the server depending on the wants and needs of each implementation. If they are placed on the client side, only one of clients should be responsible for actually processing the data because otherwise there could be multiple versions of the same state that are equally correct, because they were each accurately calculated by a different client, so the server would have to choose one state to save to the master state machine and discard the other versions. This could lead to jumpiness when displaying the state or bugs. Because only one client is processing data, only that client will have a greater load than the others. If the overhead of the game is too significant, this could become problematic. If the processing is done on the server, there will not be an issue with one client running slower, but it will be more tedious to implement, because a custom installation will have to be designed instead of a premade backend application, and a more powerful server will be required.&lt;br /&gt;
&lt;br /&gt;
For turn based games, this is a non-issue because each client can process the game state for their own turn. It only becomes an issue when a game state needs to be calculated that isn&#039;t based on client inputs, once again like the movement of the ball in pong, as opposed to the movement of the paddles in pong.&lt;br /&gt;
&lt;br /&gt;
=== Example Server Application ===&lt;br /&gt;
application.cpp&lt;br /&gt;
 #include &amp;quot;statemachine.h&amp;quot;&lt;br /&gt;
 #include &amp;quot;game.h&amp;quot;&lt;br /&gt;
 #include &amp;quot;port.h&amp;quot;&lt;br /&gt;
 #include &amp;quot;client.h&amp;quot;&lt;br /&gt;
 #include &amp;quot;statemachine.h&amp;quot;&lt;br /&gt;
 #include &amp;lt;iostream&amp;gt;&lt;br /&gt;
 #include &amp;lt;thread&amp;gt;&lt;br /&gt;
 #include &amp;lt;chrono&amp;gt;&lt;br /&gt;
 #include &amp;lt;fstream&amp;gt;&lt;br /&gt;
 #include &amp;lt;algorithm&amp;gt;&lt;br /&gt;
 #include &amp;lt;random&amp;gt;&lt;br /&gt;
 #include &amp;quot;params.h&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 int main() {&lt;br /&gt;
 &lt;br /&gt;
Here we load a general parameter file to ensure that the experiment is the same on each client. We also load a parameter file for an existing game, so we can resume where we left off. We will write to the existing game file in the final section of the application file. If this is the first session, then we will randomly generate a stimuli sequence.&lt;br /&gt;
&lt;br /&gt;
 	// Load Parameter File&lt;br /&gt;
 	Params params = Params( &amp;quot;Parameters.prm&amp;quot; );&lt;br /&gt;
 &lt;br /&gt;
 	// Load previous parameters&lt;br /&gt;
 	Params existing = Params( &amp;quot;ExistingGame.prm&amp;quot; );&lt;br /&gt;
 &lt;br /&gt;
 	std::string stimuliSequence;&lt;br /&gt;
        &lt;br /&gt;
        // Check if saved parameters from previous game are populated&lt;br /&gt;
 	if ( existing.contents.size() &amp;gt; 0 ) {&lt;br /&gt;
 		params.contents += existing.contents;&lt;br /&gt;
 &lt;br /&gt;
 		stimuliSequence = existing.GetParam( &amp;quot;StimuliSequence&amp;quot; )-&amp;gt;line;&lt;br /&gt;
 	} // If they are not then generate them, and they will be saved when this game finishes&lt;br /&gt;
 	else {&lt;br /&gt;
 		// Generate Random Sequence&lt;br /&gt;
 &lt;br /&gt;
 		Param* stimmat = params.GetParam( &amp;quot;StimuliMatrix&amp;quot; );&lt;br /&gt;
 &lt;br /&gt;
 		std::vector&amp;lt;int&amp;gt; order = std::vector&amp;lt;int&amp;gt;( stimmat-&amp;gt;width );&lt;br /&gt;
 		for ( int i = 0; i &amp;lt; stimmat-&amp;gt;width; i++ )&lt;br /&gt;
 			order[ i ] = i;&lt;br /&gt;
 &lt;br /&gt;
 		std::random_device rd;&lt;br /&gt;
 		auto rng = std::default_random_engine( rd() );&lt;br /&gt;
 		std::shuffle( std::begin( order ), std::end( order ), rng );&lt;br /&gt;
 &lt;br /&gt;
 		stimuliSequence = &amp;quot;\nApplication:Sequence intlist StimuliSequence= &amp;quot;;&lt;br /&gt;
 		stimuliSequence += std::to_string( stimmat-&amp;gt;width );&lt;br /&gt;
 		stimuliSequence += &amp;quot; &amp;quot;;&lt;br /&gt;
 		for ( int i = 0; i &amp;lt; stimmat-&amp;gt;width; i++ ) {&lt;br /&gt;
 			stimuliSequence += std::to_string( order[ i ] );&lt;br /&gt;
 			stimuliSequence += &amp;quot; &amp;quot;;&lt;br /&gt;
 		}&lt;br /&gt;
 		stimuliSequence += &amp;quot;% % % //Random Stimuli Sequence&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 		params.AddParam( stimuliSequence );&lt;br /&gt;
 &lt;br /&gt;
 		params.AddParam( &amp;quot;Application int InitialTrialNumber= 0 % % % // trial number&amp;quot; );&lt;br /&gt;
 	}&lt;br /&gt;
 &lt;br /&gt;
 	params.contents.push_back( 0 );&lt;br /&gt;
&lt;br /&gt;
This is the only necessary part of the main function. Here we open the port for listening, connect to the clients, and start the loop. &lt;br /&gt;
        //Open the port for listening&lt;br /&gt;
 	Port port( 1234, 100 );&lt;br /&gt;
 	if ( !port.open )&lt;br /&gt;
 		return 0;&lt;br /&gt;
 	std::cout &amp;lt;&amp;lt; &amp;quot;Connected to port &amp;quot; &amp;lt;&amp;lt; 1234 &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
 &lt;br /&gt;
        // Initialize Game class&lt;br /&gt;
 	Game game = Game( port, params.contents );&lt;br /&gt;
 &lt;br /&gt;
 	std::cout &amp;lt;&amp;lt; &amp;quot;Waiting for clients&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
        &lt;br /&gt;
        // Wait for a client to open a socket connection then connect them to the game&lt;br /&gt;
 	Client* client1 = port.WaitForClient();&lt;br /&gt;
 	game.Connect( client1 );&lt;br /&gt;
 &lt;br /&gt;
 	std::cout &amp;lt;&amp;lt; &amp;quot;Connected to first client&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
 	std::cout &amp;lt;&amp;lt; &amp;quot;Waiting for second client&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
 &lt;br /&gt;
        // Do the same for a second client&lt;br /&gt;
 	game.Connect( port.WaitForClient() );&lt;br /&gt;
 &lt;br /&gt;
 	std::cout &amp;lt;&amp;lt; &amp;quot;Connected to second client&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
        &lt;br /&gt;
        // Run the server loop and save the final states&lt;br /&gt;
 	StateMachine out_states = game.Loop();&lt;br /&gt;
&lt;br /&gt;
Here we take data from the master state machine and save it to the existing game parameter file, so we can use it when we restart the paradigm.&lt;br /&gt;
 &lt;br /&gt;
        // Save the trial number from when the paradigm was ended&lt;br /&gt;
 	std::string InitialTrialNumber = out_states.GetState( &amp;quot;TrialNumber&amp;quot; );&lt;br /&gt;
 	std::cout &amp;lt;&amp;lt; &amp;quot;Trial Number: &amp;quot; &amp;lt;&amp;lt; InitialTrialNumber &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
        &lt;br /&gt;
        // Make sure that the trial number is populated and subtract one to repeat the unfinished trial&lt;br /&gt;
 	if ( InitialTrialNumber.size() == 0 ) InitialTrialNumber = &amp;quot;\1&amp;quot;;&lt;br /&gt;
 	std::cout &amp;lt;&amp;lt; &amp;quot;Saving Trial Number: &amp;quot; &amp;lt;&amp;lt; ( int ) *InitialTrialNumber.c_str() - 1 &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
 &lt;br /&gt;
 	// Save Initial Trial Number and random stimuli sequence&lt;br /&gt;
 	std::ofstream egof( &amp;quot;ExistingGame.prm&amp;quot; );&lt;br /&gt;
 	egof &amp;lt;&amp;lt; &amp;quot;Application int InitialTrialNumber= &amp;quot; &amp;lt;&amp;lt; ( int )*InitialTrialNumber.c_str() - 1 &amp;lt;&amp;lt; &amp;quot; % % % // trial number&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
 	egof &amp;lt;&amp;lt; stimuliSequence &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
 &lt;br /&gt;
        // All Done!&lt;br /&gt;
 	std::cout &amp;lt;&amp;lt; &amp;quot;All done!&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== Important Notes ==&lt;br /&gt;
The server must be configured to allow inbound TCP traffic. Most only server services, like AWS or Azure, will allow you to do this easily. &lt;br /&gt;
&lt;br /&gt;
In AWS:&lt;br /&gt;
# Select an instance&lt;br /&gt;
# Go to the &amp;quot;Security&amp;quot; tab&lt;br /&gt;
# Select one of the security groups&lt;br /&gt;
# With one of the security groups selected, go to the &amp;quot;inbound rules&amp;quot; tab&lt;br /&gt;
# Press &amp;quot;edit inbound rules&amp;quot;&lt;br /&gt;
# Press &amp;quot;Add Rule&amp;quot;&lt;br /&gt;
# Set &amp;quot;Type&amp;quot; to &amp;quot;Any TCP&amp;quot;&lt;br /&gt;
# Set &amp;quot;Source&amp;quot; to the IP Addresses of each of your clients or to &amp;quot;Anywhere IPv4&amp;quot;&lt;br /&gt;
# Press &amp;quot;Save Rules&amp;quot;&lt;br /&gt;
&lt;br /&gt;
To create an instance in AWS:&lt;br /&gt;
# Go to [aws.amazon.com/ec2|AWS] and create an account or log in&lt;br /&gt;
# Press &amp;quot;Launch Instance&amp;quot;&lt;br /&gt;
# Give your instance a name&lt;br /&gt;
# Select &amp;quot;Amazon Linux&amp;quot; or any other non-windows operating system of your choice&lt;br /&gt;
# Select the tier of server you would like. If you are doing the processing on the clients then the free-tier or cheapest option will suffice with no performance penalties. If you followed the example server application, then you are doing the processing on the clients. If you are doing processing on the server, then select whichever performance tier is necessary to run your application at an acceptable speed.&lt;br /&gt;
# Under Key Pair, press &amp;quot;Create New Key Pair&amp;quot;&lt;br /&gt;
# Name is whatever you would like&lt;br /&gt;
# Select RSA for key pair type&lt;br /&gt;
# Select .pem for private key file format&lt;br /&gt;
# Press create key pair and remember where you save it to. We will need to use this to connect to the server.&lt;br /&gt;
# Now press &amp;quot;Launch Instance&amp;quot;&lt;br /&gt;
&lt;br /&gt;
To configure and run your aws instance (if it isn&#039;t an aws instance the same applies, except instead of &amp;quot;ec2-user&amp;quot; you will use the username for your server or if it is local ignore the ssh step):&lt;br /&gt;
Open a terminal or shell&lt;br /&gt;
Enter the command&lt;br /&gt;
 ssh -i &amp;lt;/path/key-pair-name.pem&amp;gt; ec2-user@&amp;lt;public-IPv4-address&amp;gt;&lt;br /&gt;
The public IPv4 address can be found by selecting the instance in the instance dashboard. If you do not see one, ensure that the instance is running.&lt;br /&gt;
If prompted with&lt;br /&gt;
 The authenticity of host &#039;ec2-198-51-100-1.compute-1.amazonaws.com (198-51-100-1)&#039; can&#039;t be established.&lt;br /&gt;
 ECDSA key fingerprint is l4UB/neBad9tvkgJf1QZWxheQmR59WgrgzEimCG6kZY.&lt;br /&gt;
 Are you sure you want to continue connecting (yes/no)?&lt;br /&gt;
Type&lt;br /&gt;
 yes&lt;br /&gt;
Clone the github repository with&lt;br /&gt;
 git clone https://github.com/MaxwellMarcus/hyperscanning-backend&lt;br /&gt;
Go to the directory&lt;br /&gt;
 cd hyperscanning-backend&lt;br /&gt;
Edit or create an application in the file application.cpp, if you aren&#039;t using the default tutorial application file&lt;br /&gt;
Build the application with&lt;br /&gt;
 make&lt;br /&gt;
Run the application with&lt;br /&gt;
 ./application&lt;br /&gt;
The application will only run as long as the experiment and will have to be restarted.&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=BCI2000_Hyperscanning&amp;diff=10444</id>
		<title>BCI2000 Hyperscanning</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=BCI2000_Hyperscanning&amp;diff=10444"/>
		<updated>2023-06-14T21:36:33Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;BCI2000 Hyperscanning is a multiplayer simulation, a program that is synchronized over multiple computers, that supports the connection of two or more clients, the computers that are involved in the simulation. BCI2000 Hyperscanning also has subjects, which are the people that are using the client computers.&lt;br /&gt;
&lt;br /&gt;
In a multiplayer simulation, each client involved must know the current state of the game. This game state allows each client to determine the output that is shown to the user. In order for each client to display the same game to each user, each client must have the same game state. The game state is stored as a collection of state variables in a state machine.&lt;br /&gt;
A state machine is a set of variables, or states, that correspond with values. In essence, it is a simple database. The data in the database describes the state of the game (see figure \ref{fig:gamestate}).&lt;br /&gt;
&lt;br /&gt;
BCI2000 Hyperscanning has a master state machine that is stored on a centralized back-end server and one state machine for each client. Each client is connected to the back-end server through a TCP socket to ensure that each connection is maintained and everything that is sent is received. The clients output a stimulus to the user based on their state machines, and update their state machines based on user inputs. When one client updates its state machine, the server saves the game state in its master state machine and updates the other clients (see figure \ref{fig:gamestateupdate}).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:GameStateFigure.png|center]]&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Game State.&#039;&#039;&#039; The game state shows synchrony between the master game state, which is stored on the server, and the client game states.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:GameStateUpdateFigure.png|center]]&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Game State Updates.&#039;&#039;&#039; The game state updates (bottom) show a typical interaction that would result in a game state update to the master game state and the ensuing update to the other client(s). In this example, the user clicks, indicating they would like to place a marker in the tic-tac-toe game, and this triggers a local game state update. This local game state update is sent to the server. The server saves the update and synchronizes the remaining client(s). After the interaction has concluded, each client is synchronized.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[File:StateUpdatesFigure.png|center]]&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Game State Update Scenarios.&#039;&#039;&#039; In scenario 1, the client updated its game state locally because of a user mouse press. This caused synchronization between it and the master game state to be lost. In this scenario, the client updates the master game state to match its game state. In scenario 2, a different client updated the master game state because of a user mouse press. This caused synchronization between the first client and the master game state to be lost. In this scenario, the server updates the first client to match its game state.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Server ==&lt;br /&gt;
The purpose of the server, or back-end, is to store, update, and distribute a master list of states. It synchronizes each of the client&#039;s state machines, so that each client displays the same game. &lt;br /&gt;
&lt;br /&gt;
At a given time, one of the clients may have a state variable set to a value that is different from the value that the server has that state set to. At this point there are two possibilities. If that state was changed based on user inputs, then the server will update its state machine to reflect that user input. Otherwise, if the client has an old value, one that has been changed by another client, then the server will update the client with the new value of the state, so that each client is synchronized (see figure \ref{fig:gamestateupdatescenarios}).&lt;br /&gt;
&lt;br /&gt;
In addition to synchronizing states between clients, the backend must also synchronize many initial parameters to ensure that the exact same experiment is being run for each subject, e.g. the order of stimulus images needs to be synchronized. To solve this, the server contains a BCI2000 parameter file that is sent to each client when it connects to the server. This also serves as a greeting message to ensure that the connection is functioning before the experiment begins.&lt;br /&gt;
&lt;br /&gt;
The server application can be run from any mac or linux computer, whether it is local to one of the clients or in the cloud, as long as it is configured to allow TCP traffic. It is a collection of c++ classes and methods that are implemented into an application file. This application file is then run on the server computer. The server is not an instance of BCI2000. Rather, it is a separate application that interacts with client instances of BCI2000. &lt;br /&gt;
&lt;br /&gt;
While the idea for this hyperscanning architecture propagated from one experimental design, we ensured that this technology was robust enough to be used reused for any experiment, even if it is radically different from our initial one. The core of the back-end is simple and abstracted. It is a state machine that can be updated from clients and will propagate those updates to other clients. This simplicity means that the central parts of the back-end will work for any experimental paradigm. The simplicity of the core also allows for a more specific framework to be built surrounding the core, should that be necessary for a specific application. &lt;br /&gt;
&lt;br /&gt;
For each paradigm, an application file is implemented on the server. This application file will always contain the basic backend framework, like connecting to clients and running the actual data exchange loop, but it can also contain more specific instructions. For example, if parameters need to be randomly generated and synchronized across clients the core design is flexible enough to allow that to be built. Parameters can be added to the previously mentioned parameter file through the application file to solve this particular example. If there is a paradigm requiring more complex changes to the standard backend, the core can also be broken down into its individual steps to allow that.  &lt;br /&gt;
&lt;br /&gt;
The backend runs in a continuous loop of data exchanges with the clients. This loop continues for as long as the experiment runs. The end to the session, and thus the loop, is singaled by one of the clients breaking its connection with the server. &lt;br /&gt;
&lt;br /&gt;
Even though a client disconnects, the experiment may not be concluded. There could have been a crash, internet issues, or the investigator may have wanted to pause the experiment, but the server cannot continue operating properly after a client has disconnected. To solve this issue, the application file can access the state machine after the loop has ended, and save any of the states that are necessary to redetermine the experimental state after a restart. These values can then be passed to BCI2000 as parameters when it is restarted. For example, the trial number can be saved and passed to BCI2000 as an initial trial number parameter (see figure \ref{fig:pause}).&lt;br /&gt;
&lt;br /&gt;
[[File:PauseFigure.png|center]]&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Example paradigm with pause feature.&#039;&#039;&#039; This is a stimulus presentation paradigm, with a progression of faces being shown to the subject. During the first recording session, the subject gets through the first two trials before the session ends. The current trial number is saved to the server. During the next recording session, the server sends the current trial number, three, to the client; the client begins the session at trial number three and completes the paradigm.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Server Loop ===&lt;br /&gt;
The loop has three main steps (see figure \ref{fig:serverloop}). First, the server updates any states changed by the clients. Second, the server reconciles all of the updated states. Third, the server sends updated states back to the clients. &lt;br /&gt;
&lt;br /&gt;
[[File:ReconcilliationFigure.png|center]]&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Progression of state updates over time.&#039;&#039;&#039; Each client sends state updates, indicated by black arrows, to the server-side-client state machines, indicated by pink arrows. The server side state machines send the state updates to the master state machine. These state updates include conflicting information; the master state machine saves the state update from client 1 and disregards the conflicting update from client 2. The server sends the changed states, indicated by triangular arrows and blue ovals, back to the server-side-client state machines. The server-side-client state machines send their changed states back to the clients.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==== Client Updates ====&lt;br /&gt;
&lt;br /&gt;
In this step, the server simply waits for at least one of the clients to send states that were changed locally. If a client has not sent any data, then the server will wait for 2ms before checking another client. The server saves the data sent by the client in a state machine that tracks the current values of the states on each client. These are the server-side-client state machines.&lt;br /&gt;
&lt;br /&gt;
==== Reconciliation ====&lt;br /&gt;
In this step, the server decides which states to save and prepares the updates to send to each client. After each client sends its updates, the server-side-client machines are different from the master state machine and from each other, but they are synchronized with their respective clients. The server has to synchronize all of these state machines by saving client changes to the master state machine and sending updates to the clients, but it is necessary to save only one version of each state and to send only updates with new information. If the server repeats state updates by sending the same update twice or by echoing a state change back to the client that sent it, that state will be changed at multiple times for that client, which can cause irregularities and bugs. %Tracker state machines, which track the changes when a state machine is updated, are used to ensure that only actual changes are sent to the clients. One tracker is used to determine all the changes to the master state machine from the client updates. These changes are then used to update the server-side-client state machines. The changes to the server-side-client state machines are only the updates from other clients that were saved as master states, so they are then used to update the actual client state machines.&lt;br /&gt;
&lt;br /&gt;
To solve this, each state must pass two tests to get sent to a client. First, it must have been saved to the master state machine. Second, it must have been sent by a different client. These tests are implemented using tracker state machines, which track the changes that occur when a state machine is updated. For the first test, the server updates the master state machine from the server-side-client state machines and tracks the changes. For the second test, the changes to the master state machine are used to update the server-side-client state machines, and the changes from this interaction are tracked. The changes to the server-side-client state machines pass both tests, because they were changed on the master state machine (they were saved to the master state machine) and one of the client state machines (they weren&#039;t sent by that client because, in that case, they would have already been updated). These changes can be sent to the clients.&lt;br /&gt;
&lt;br /&gt;
==== Update Clients ====&lt;br /&gt;
This final step is the opposite of the first step. The server sends the prepared states to the clients. After this step, the loop repeats, and the server waits for the client to send updates again. &lt;br /&gt;
&lt;br /&gt;
== Clients ==&lt;br /&gt;
The purpose of the clients is to display the stimulus to the subject. Additionally, it is responsible for actually calculating the values of the game states. Each client is a separate instance of BCI2000, which are run on separate computers. They can be next to each other or hundreds of miles apart depending on the needs of the experiment.&lt;br /&gt;
&lt;br /&gt;
Once again, the structure is designed to be robust and reusable. To this end, the client exists in two pieces. The true frontend, which is responsible for calculating state values and outputting the stimulus, and the network logger, which is responsible for communication with the server. The true frontend is designed as a typical BCI2000 experiment, and thus will be different for every experiment. The network logger contains everything that will be the exact same for every BCI2000 Hyperscanning experiment. Thus, the network logger can be reused, while the true frontend is redesigned for every new experiment.&lt;br /&gt;
&lt;br /&gt;
The network logger is a part of the hyperscanning application base, which is a c++ class that a hyperscanning paradigm can be built upon. The hyperscanning application base will connect the network logger to the application module. &lt;br /&gt;
&lt;br /&gt;
BCI2000 has its own built in state machine. The network logger seamlessly updates a predefined set of these BCI2000 states based on server activity and the activity of other clients. It translates server data into BCI2000 states. The list of states that are updated by the network logger is defined in a BCI2000 parameter called shared states that contains both the names and the sizes of each of the states that the designer wants to be synchronized amongst the clients. To ensure that the states are sent rapidly, only the necessary states should be sent between clients, so they must be defined in this parameter. Other BCI2000 states will not be synchronized.&lt;br /&gt;
&lt;br /&gt;
=== Client Loops ===&lt;br /&gt;
Much like the server, the network logger loops, however, in order to conform with BCI2000 two distinct loops are utilized. One of them is synchronous with the rest of BCI2000. BCI2000 only allows its states to be changed during specific phases, so one of the loops must be synchronized with BCI2000. %The limitations of BCI2000 states require that state changes occur only during a specific time period, which necessitates synchronizing the loop with BCI2000. &lt;br /&gt;
While BCI2000 has a type of state that can be written to asynchronously, called an event, they are added to a queue and changed at a later time. This means the network logger cannot differentiate changes it made from changes the frontend made, so it doesn&#039;t know which changes to send to the server. The other loop is asynchronous, and makes use of multi-threading and parallel processing to increase the speed that data transfers can be made at, ensuring the greatest possible synchronicity between clients.&lt;br /&gt;
&lt;br /&gt;
Because these loops are both operating on the same data, i.e. the states that need to be changed, there is the risk of data corruption if both try to operate at the same time. The data is stored in mutexed buffers to ensure that does not happen. Mutexed buffers can only be written to or read by a single source at a time. If multiple sources try to access a mutexed buffer, one of them must wait for the other to finish its operation.&lt;br /&gt;
&lt;br /&gt;
Two buffers are shared between the two loops (see figure \ref{fig:clientloops}). One is a state machine that contains the name and value of each shared state, along with whether or not the state has a change from the server that hasn&#039;t been updated to the BCI2000 states, and the other is a message for the server that contains the states that have been updated by the frontend.&lt;br /&gt;
&lt;br /&gt;
[[File:clientloopsfigure.png|center]]&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Synchronous and asynchronous client loops and their data exchanges.&#039;&#039;&#039; The client updates a state, e.g. they indicate their move in tic-tac-toe with a mouse click, and the synchronous client loop adds that change to the message for the server. The asynchronous loop sends the message to the server. The asynchronous loop continues looping until it gets a response from the server. When it gets a response from the server, e.g. the other client&#039;s move, it adds it to the changed states buffer. The synchronous loop saves the changes in the changed states buffer to the BCI2000 state machine.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==== Synchronous Loop ====&lt;br /&gt;
&lt;br /&gt;
The synchronous loop first updates all of the BCI2000 states that have been changed by the server. %to the value sent by the server. &lt;br /&gt;
The loop then determines if any of the states in the mutexed state machine are different from their BCI2000 counterpart. Because all of the states that were different from BCI2000 because of a server update were just updated, all of the remaining discrepancies must be due to a client change. These are then recorded in the message for the server. &lt;br /&gt;
&lt;br /&gt;
It is very important for analyzing the experiment that the investigator knows when states were changed in relation to the recorded data. This could be complicated when states are being sent over the internet with delays and lag, but the network logger and BCI2000 radically simplify it. The important timestamp to record is when the state had an effect on the actual stimulus, because this is when it can have an effect on the subject. The timestamp of BCI2000 states is recorded whenever they are changed, and it is the BCI2000 states that have an effect on the stimulus. It is also BCI2000 that is providing the timestamps for the recorded data, therefore those timestamps will provide an accurate comparison between state changes and recorded data.&lt;br /&gt;
&lt;br /&gt;
==== Asynchronous Loop ====&lt;br /&gt;
&lt;br /&gt;
The asynchronous loop first sends the mutexed message to the server. If the message is empty, it doesn&#039;t send anything. This is the message that the server waits for in section 2.1.1. The loop then waits for a message from the server with the changes other clients have made. It waits 2ms for the server before moving on. This is the message the server sends in section 2.1.3. The loop then records these changes in the mutexed state machine and flags that they have a change from the server.&lt;br /&gt;
&lt;br /&gt;
=== Client Initialization ===&lt;br /&gt;
&lt;br /&gt;
The client initializes its connection with the server during the AutoConfig phase of BCI2000. This occurs after the Set Config button is pressed. The client first ensures that it hasn&#039;t already established a connection with the server, then it connects to the server. It uses user defined parameters to determine the IP address and port of the server application. The port of the server is defined by the designer in the server application file. The client then waits for the server to send an initial message that contains a client number and initial parameters. The client number is an id for the client to use to differentiate itself from other clients. For example, if each subject plays a different role in the paradigm, then the client number can be used to differentiate between roles. The parameters are then used to set BCI2000&#039;s parameters.&lt;br /&gt;
&lt;br /&gt;
== Example Paradigm Design ==&lt;br /&gt;
A BCI2000 Hyperscanning paradigm is designed very similarly to a typical BCI2000 paradigm with a couple key differences. First, states we want to be shared with other clients must be stated in the batch file, either under the optional parameter SharedStates (for states we want to be shared that BCI2000 Hyperscanning will define for us) or the optional parameter PreDefinedSharedStates (for states we want to be shared that we will define ourselves). Second, instead of the regular BCI2000 methods, i.e. Publish, Preflight, Process, etc., we use Hyperscanning Application Base methods, which are prefixed with Shared, i.e. SharedPublish, SharedPreflight, SharedProcess, etc.. The BCI2000 Hyperscanning methods behave in the exact same way, except they also call the client loops which interact with the server.&lt;br /&gt;
&lt;br /&gt;
=== Turn Based Stimulus ===&lt;br /&gt;
&lt;br /&gt;
The well-known game Tic-Tac-Toe is an example of a turn based game. One player takes their turn, then the other player takes their turn. Each turn is taken after the previous one, with no overlap in timing. Here is our implementation of Tic-Tac-Toe to show how a turn based game works with BCI2000 hyperscanning:&lt;br /&gt;
&lt;br /&gt;
TicTacToe.cpp:&lt;br /&gt;
 #include &amp;quot;TicTacToe.h&amp;quot;&lt;br /&gt;
 #include &amp;quot;Shapes.h&amp;quot;&lt;br /&gt;
 #include &amp;quot;TextField.h&amp;quot;&lt;br /&gt;
 #include &amp;lt;limits&amp;gt;&lt;br /&gt;
 #include &amp;quot;BCIEvent.h&amp;quot;&lt;br /&gt;
 #include &amp;lt;string&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 //Shared States&lt;br /&gt;
 //grid, 32&lt;br /&gt;
 //turn, 8&lt;br /&gt;
 //x, 8&lt;br /&gt;
 //y, 8&lt;br /&gt;
 &lt;br /&gt;
 RegisterFilter( TicTacToe, 3 );&lt;br /&gt;
 &lt;br /&gt;
 TicTacToe::TicTacToe() : winText( NULL ), highlight( NULL ), tiles( NULL ), board( NULL ), mrDisplay( Window() ) {&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 void TicTacToe::SharedPublish() {&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 void TicTacToe::SharedPreflight( const SignalProperties&amp;amp; Input, SignalProperties&amp;amp; Output ) const {&lt;br /&gt;
 	State( &amp;quot;grid&amp;quot; );&lt;br /&gt;
 	State( &amp;quot;turn&amp;quot; );&lt;br /&gt;
 	State( &amp;quot;ClientNumber&amp;quot; );&lt;br /&gt;
 	State( &amp;quot;KeyDown&amp;quot; );&lt;br /&gt;
 	State( &amp;quot;x&amp;quot; );&lt;br /&gt;
 	State( &amp;quot;y&amp;quot; );&lt;br /&gt;
 &lt;br /&gt;
 	Parameter( &amp;quot;SampleBlockSize&amp;quot; );&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 void TicTacToe::SharedInitialize( const SignalProperties&amp;amp; Input, const SignalProperties&amp;amp; Output ) {&lt;br /&gt;
 	ApplicationBase::Initialize( Input, Output );&lt;br /&gt;
 &lt;br /&gt;
 	board = new ImageStimulus( mrDisplay );&lt;br /&gt;
 	board-&amp;gt;SetObjectRect( { 0.f, 0.f, 1.f, 1.f } );&lt;br /&gt;
 	board-&amp;gt;SetScalingMode( GUI::ScalingMode::AdjustHeight );&lt;br /&gt;
 	board-&amp;gt;SetRenderingMode( GUI::RenderingMode::Transparent );&lt;br /&gt;
 	board-&amp;gt;SetFile( &amp;quot;../tasks/hyperscanning_test/tictactoe.png&amp;quot; );&lt;br /&gt;
 	board-&amp;gt;SetZOrder( 12 );&lt;br /&gt;
 &lt;br /&gt;
 	winText = new TextField( mrDisplay );&lt;br /&gt;
 	winText-&amp;gt;SetVisible( true );&lt;br /&gt;
 	winText-&amp;gt;SetObjectRect( { 0.2f, 0.4f, 0.8f, 0.6f } );&lt;br /&gt;
 	board-&amp;gt;SetZOrder( 1 );&lt;br /&gt;
 &lt;br /&gt;
 	tiles = ( ImageStimulus** ) malloc( sizeof( ImageStimulus ) * 9 );&lt;br /&gt;
 	for ( int i = 0; i &amp;lt; 9; i++ ) {&lt;br /&gt;
 		tiles[ i ] = new ImageStimulus( mrDisplay );&lt;br /&gt;
 		int x = i % 3;&lt;br /&gt;
 		int y = i / 3;&lt;br /&gt;
 		tiles[ i ]-&amp;gt;SetObjectRect( { x / 3.f, y / 3.f, x / 3.f + 0.33f, y / 3.f + 0.33f } );&lt;br /&gt;
 		tiles[ i ]-&amp;gt;SetScalingMode( GUI::ScalingMode::AdjustBoth );&lt;br /&gt;
 		tiles[ i ]-&amp;gt;SetRenderingMode( GUI::RenderingMode::Opaque );&lt;br /&gt;
 		tiles[ i ]-&amp;gt;SetZOrder( i + 2 );&lt;br /&gt;
 	}&lt;br /&gt;
 &lt;br /&gt;
 	highlight = new ImageStimulus( mrDisplay );&lt;br /&gt;
 	highlight-&amp;gt;SetObjectRect( { 0.f, 0.f, 0.33f, 0.33f } );&lt;br /&gt;
 	highlight-&amp;gt;SetScalingMode( GUI::ScalingMode::AdjustBoth );&lt;br /&gt;
 	highlight-&amp;gt;SetRenderingMode( GUI::RenderingMode::Transparent );&lt;br /&gt;
 	highlight-&amp;gt;SetFile( &amp;quot;../tasks/hyperscanning_test/highlight.png&amp;quot; );&lt;br /&gt;
 	highlight-&amp;gt;SetZOrder( 11 );&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 void TicTacToe::SharedProcess( const GenericSignal&amp;amp; Input, GenericSignal&amp;amp; Output ) {&lt;br /&gt;
 	board-&amp;gt;Present();&lt;br /&gt;
 	highlight-&amp;gt;Present();&lt;br /&gt;
 	for ( int i = 0; i &amp;lt; 9; i++ ) {&lt;br /&gt;
 		tiles[ i ]-&amp;gt;Present();&lt;br /&gt;
 	}&lt;br /&gt;
 &lt;br /&gt;
 	if ( State( &amp;quot;turn&amp;quot; ) == 3 ) {&lt;br /&gt;
 		if ( CheckKeyPress( &amp;quot;KeyDown&amp;quot;, 32 ) ) { //Space&lt;br /&gt;
 			Reset();&lt;br /&gt;
 		}&lt;br /&gt;
 	}&lt;br /&gt;
 &lt;br /&gt;
 	if ( State( &amp;quot;ClientNumber&amp;quot; ) == State( &amp;quot;turn&amp;quot; ) ) {&lt;br /&gt;
 		if ( CheckKeyPress( &amp;quot;KeyDown&amp;quot;, 38 ) &amp;amp;&amp;amp; State( &amp;quot;y&amp;quot; ) &amp;gt;= 1 ) { //Up&lt;br /&gt;
 			State( &amp;quot;y&amp;quot; ) = State( &amp;quot;y&amp;quot; ) - 1;&lt;br /&gt;
 		}&lt;br /&gt;
 &lt;br /&gt;
 		if ( CheckKeyPress( &amp;quot;KeyDown&amp;quot;, 40 ) &amp;amp;&amp;amp; State( &amp;quot;y&amp;quot; ) &amp;lt;= 1 ) { //Down&lt;br /&gt;
 			State( &amp;quot;y&amp;quot; ) = State( &amp;quot;y&amp;quot; ) + 1;&lt;br /&gt;
 		}&lt;br /&gt;
 &lt;br /&gt;
 		if ( CheckKeyPress( &amp;quot;KeyDown&amp;quot;, 37 ) &amp;amp;&amp;amp; State( &amp;quot;x&amp;quot; ) &amp;gt;= 1 ) { //Left&lt;br /&gt;
 			State( &amp;quot;x&amp;quot; ) = State( &amp;quot;x&amp;quot; ) - 1;&lt;br /&gt;
 		}&lt;br /&gt;
 &lt;br /&gt;
 		if ( CheckKeyPress( &amp;quot;KeyDown&amp;quot;, 39 ) &amp;amp;&amp;amp; State( &amp;quot;x&amp;quot; ) &amp;lt;= 1 ) { //Right&lt;br /&gt;
 			State( &amp;quot;x&amp;quot; ) = State( &amp;quot;x&amp;quot; ) + 1;&lt;br /&gt;
 		}&lt;br /&gt;
 &lt;br /&gt;
 		if ( CheckKeyPress( &amp;quot;KeyDown&amp;quot;, 32 ) ) { //Space&lt;br /&gt;
 			long xflag = 1UL &amp;lt;&amp;lt; ( 2 * ( State( &amp;quot;y&amp;quot; ) * 3 + State( &amp;quot;x&amp;quot; ) ) );&lt;br /&gt;
 			long oflag = 1UL &amp;lt;&amp;lt; ( 2 * ( State( &amp;quot;y&amp;quot; ) * 3 + State( &amp;quot;x&amp;quot; ) ) + 1 );&lt;br /&gt;
 &lt;br /&gt;
 			if ( !( State( &amp;quot;grid&amp;quot; ) &amp;amp; xflag ) &amp;amp;&amp;amp; !( State( &amp;quot;grid&amp;quot; ) &amp;amp; oflag ) ) {&lt;br /&gt;
 				if ( State( &amp;quot;ClientNumber&amp;quot; ) == 0 ) {&lt;br /&gt;
 					State( &amp;quot;grid&amp;quot; ) = State( &amp;quot;grid&amp;quot; ) | xflag;&lt;br /&gt;
 					State( &amp;quot;turn&amp;quot; ) = 1;&lt;br /&gt;
 				}&lt;br /&gt;
 &lt;br /&gt;
 				else {&lt;br /&gt;
 					State( &amp;quot;grid&amp;quot; ) = State( &amp;quot;grid&amp;quot; ) | oflag;&lt;br /&gt;
 					State( &amp;quot;turn&amp;quot; ) = 0;&lt;br /&gt;
 				}&lt;br /&gt;
 			}&lt;br /&gt;
 		}&lt;br /&gt;
 	}&lt;br /&gt;
 &lt;br /&gt;
 	long flag = 1UL;&lt;br /&gt;
 	for ( int i = 0; i &amp;lt; 9; i++ ) {&lt;br /&gt;
 		if ( State( &amp;quot;grid&amp;quot; ) &amp;amp; flag ) {&lt;br /&gt;
 			tiles[ i ]-&amp;gt;SetFile( &amp;quot;../tasks/hyperscanning_test/x.png&amp;quot; );&lt;br /&gt;
 		}&lt;br /&gt;
 		flag &amp;lt;&amp;lt;= 1;&lt;br /&gt;
 		if ( State( &amp;quot;grid&amp;quot; ) &amp;amp; flag ) {&lt;br /&gt;
 			tiles[ i ]-&amp;gt;SetFile( &amp;quot;../tasks/hyperscanning_test/o.png&amp;quot; );&lt;br /&gt;
 		}&lt;br /&gt;
 		flag &amp;lt;&amp;lt;= 1;&lt;br /&gt;
 	}&lt;br /&gt;
 &lt;br /&gt;
 	long hwin = horizontal_win;&lt;br /&gt;
 	long vwin = vertical_win;&lt;br /&gt;
 	long dwin1 = diagonal_win_1;&lt;br /&gt;
 	long dwin2 = diagonal_win_2;&lt;br /&gt;
 &lt;br /&gt;
 	if ( ( State( &amp;quot;grid&amp;quot; ) &amp;amp; dwin1 ) == dwin1 || ( State( &amp;quot;grid&amp;quot; ) &amp;amp; dwin2 ) == dwin2 ) {&lt;br /&gt;
 		State( &amp;quot;turn&amp;quot; ) = 3;&lt;br /&gt;
 		winText-&amp;gt;SetText( &amp;quot;X Wins&amp;quot; );&lt;br /&gt;
 	}&lt;br /&gt;
 &lt;br /&gt;
 	dwin1 &amp;lt;&amp;lt;= 1;&lt;br /&gt;
 	dwin2 &amp;lt;&amp;lt;= 1;&lt;br /&gt;
 &lt;br /&gt;
 	if ( ( State( &amp;quot;grid&amp;quot; ) &amp;amp; dwin1 ) == dwin1 || ( State( &amp;quot;grid&amp;quot; ) &amp;amp; dwin2 ) == dwin2 ) {&lt;br /&gt;
 		State( &amp;quot;turn&amp;quot; ) = 3;&lt;br /&gt;
 		winText-&amp;gt;SetText( &amp;quot;O Wins&amp;quot; );&lt;br /&gt;
 	}&lt;br /&gt;
 &lt;br /&gt;
 	for ( int i = 0; i &amp;lt; 3; i++ ) {&lt;br /&gt;
 		if ( ( State( &amp;quot;grid&amp;quot; ) &amp;amp; hwin ) == hwin || ( State( &amp;quot;grid&amp;quot; ) &amp;amp; vwin ) == vwin ) {&lt;br /&gt;
 			State( &amp;quot;turn&amp;quot; ) = 3;&lt;br /&gt;
 			winText-&amp;gt;SetText( &amp;quot;X Wins&amp;quot; );&lt;br /&gt;
 		}&lt;br /&gt;
 &lt;br /&gt;
 		hwin &amp;lt;&amp;lt;= 1;&lt;br /&gt;
 		vwin &amp;lt;&amp;lt;= 1;&lt;br /&gt;
 &lt;br /&gt;
 		if ( ( State( &amp;quot;grid&amp;quot; ) &amp;amp; hwin ) == hwin || ( State( &amp;quot;grid&amp;quot; ) &amp;amp; vwin ) == vwin ) {&lt;br /&gt;
 			State( &amp;quot;turn&amp;quot; ) = 3;&lt;br /&gt;
 			winText-&amp;gt;SetText( &amp;quot;O Wins&amp;quot; );&lt;br /&gt;
 		}&lt;br /&gt;
 &lt;br /&gt;
 		hwin &amp;lt;&amp;lt;= 5;&lt;br /&gt;
 		vwin &amp;lt;&amp;lt;= 1;&lt;br /&gt;
 	}&lt;br /&gt;
 &lt;br /&gt;
 	highlight-&amp;gt;SetObjectRect( { State(&amp;quot;x&amp;quot;) / 3.f, State(&amp;quot;y&amp;quot;) / 3.f, (State(&amp;quot;x&amp;quot;) + 1) / 3.f, (State(&amp;quot;y&amp;quot;) + 1) / 3.f } );&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 bool TicTacToe::CheckKeyPress( std::string event_name, int value ) {&lt;br /&gt;
 	for ( unsigned int i = 0; i &amp;lt; Parameter( &amp;quot;SampleBlockSize&amp;quot; ); i++ ) {&lt;br /&gt;
 		if ( State( event_name )( i ) == value ) {&lt;br /&gt;
 			return true;&lt;br /&gt;
 		}&lt;br /&gt;
 	}&lt;br /&gt;
 	return false;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 void TicTacToe::Reset() {&lt;br /&gt;
 	State( &amp;quot;turn&amp;quot; ) = 0;&lt;br /&gt;
 	State( &amp;quot;grid&amp;quot; ) = 0;&lt;br /&gt;
 &lt;br /&gt;
 	delete board;&lt;br /&gt;
 	board = new ImageStimulus( mrDisplay );&lt;br /&gt;
 	board-&amp;gt;SetObjectRect( { 0.f, 0.f, 1.f, 1.f } );&lt;br /&gt;
 	board-&amp;gt;SetScalingMode( GUI::ScalingMode::AdjustHeight );&lt;br /&gt;
 	board-&amp;gt;SetRenderingMode( GUI::RenderingMode::Transparent );&lt;br /&gt;
 	board-&amp;gt;SetFile( &amp;quot;../tasks/hyperscanning_test/tictactoe.png&amp;quot; );&lt;br /&gt;
 	board-&amp;gt;SetZOrder( 12 );&lt;br /&gt;
 &lt;br /&gt;
 	delete winText;&lt;br /&gt;
 	winText = new TextField( mrDisplay );&lt;br /&gt;
 	winText-&amp;gt;SetVisible( true );&lt;br /&gt;
 	winText-&amp;gt;SetObjectRect( { 0.2f, 0.4f, 0.8f, 0.6f } );&lt;br /&gt;
 	board-&amp;gt;SetZOrder( 1 );&lt;br /&gt;
 &lt;br /&gt;
 	for ( int i = 0; i &amp;lt; 9; i++ ) {&lt;br /&gt;
 		delete tiles[ i ];&lt;br /&gt;
 	}&lt;br /&gt;
 	free( tiles );&lt;br /&gt;
 &lt;br /&gt;
 	tiles = ( ImageStimulus** ) malloc( sizeof( ImageStimulus ) * 9 );&lt;br /&gt;
 	for ( int i = 0; i &amp;lt; 9; i++ ) {&lt;br /&gt;
 		tiles[ i ] = new ImageStimulus( mrDisplay );&lt;br /&gt;
 		int x = i % 3;&lt;br /&gt;
 		int y = i / 3;&lt;br /&gt;
 		tiles[ i ]-&amp;gt;SetObjectRect( { x / 3.f, y / 3.f, x / 3.f + 0.33f, y / 3.f + 0.33f } );&lt;br /&gt;
 		tiles[ i ]-&amp;gt;SetScalingMode( GUI::ScalingMode::AdjustBoth );&lt;br /&gt;
 		tiles[ i ]-&amp;gt;SetRenderingMode( GUI::RenderingMode::Opaque );&lt;br /&gt;
 		tiles[ i ]-&amp;gt;SetZOrder( i + 2 );&lt;br /&gt;
 	}&lt;br /&gt;
 &lt;br /&gt;
 	delete highlight;&lt;br /&gt;
 &lt;br /&gt;
 	highlight = new ImageStimulus( mrDisplay );&lt;br /&gt;
 	highlight-&amp;gt;SetObjectRect( { 0.f, 0.f, 0.33f, 0.33f } );&lt;br /&gt;
 	highlight-&amp;gt;SetScalingMode( GUI::ScalingMode::AdjustBoth );&lt;br /&gt;
 	highlight-&amp;gt;SetRenderingMode( GUI::RenderingMode::Transparent );&lt;br /&gt;
 	highlight-&amp;gt;SetFile( &amp;quot;../tasks/hyperscanning_test/highlight.png&amp;quot; );&lt;br /&gt;
 	highlight-&amp;gt;SetZOrder( 11 );&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
TicTacToe.h&lt;br /&gt;
 #include &amp;quot;Shapes.h&amp;quot;&lt;br /&gt;
 #include &amp;quot;TextField.h&amp;quot;&lt;br /&gt;
 #include &amp;quot;ApplicationWindow.h&amp;quot;&lt;br /&gt;
 #include &amp;quot;ImageStimulus.h&amp;quot;&lt;br /&gt;
 #include &amp;quot;HyperscanningApplicationBase.h&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 class TicTacToe : public HyperscanningApplicationBase {&lt;br /&gt;
 	public:&lt;br /&gt;
 		TicTacToe();&lt;br /&gt;
 &lt;br /&gt;
 		void SharedPublish() override;&lt;br /&gt;
 &lt;br /&gt;
 		void SharedPreflight( const SignalProperties&amp;amp; Input, SignalProperties&amp;amp; Output ) const override;&lt;br /&gt;
 		void SharedInitialize( const SignalProperties&amp;amp; Input, const SignalProperties&amp;amp; Output ) override;&lt;br /&gt;
 		void SharedProcess( const GenericSignal&amp;amp; Input, GenericSignal&amp;amp; Output ) override;&lt;br /&gt;
 &lt;br /&gt;
 		bool CheckKeyPress( std::string, int );&lt;br /&gt;
 &lt;br /&gt;
 		void Reset();&lt;br /&gt;
 &lt;br /&gt;
 	private:&lt;br /&gt;
 		ApplicationWindow&amp;amp; mrDisplay;&lt;br /&gt;
 &lt;br /&gt;
 		ImageStimulus* board;&lt;br /&gt;
 		ImageStimulus** tiles;&lt;br /&gt;
 		ImageStimulus* highlight;&lt;br /&gt;
 &lt;br /&gt;
 		TextField* winText;&lt;br /&gt;
 &lt;br /&gt;
 		long horizontal_win = 21;&lt;br /&gt;
 		long vertical_win = 4161;&lt;br /&gt;
 		long diagonal_win_1 = 65793;&lt;br /&gt;
 		long diagonal_win_2 = 4368;&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
and TicTacToe.bat&lt;br /&gt;
 Change directory $BCI2000LAUNCHDIR&lt;br /&gt;
 Show window; Set title ${Extract file base $0}&lt;br /&gt;
 Reset system&lt;br /&gt;
 Startup system localhost&lt;br /&gt;
 Start executable SignalGenerator --local --LogKeyboard=1&lt;br /&gt;
 Start executable DummySignalProcessing --local&lt;br /&gt;
 Start executable TicTacToe --local --Port=1234 --IPAddress=192.168.1.102 --SharedStates=grid,32&amp;amp;turn,8&amp;amp;x,8&amp;amp;y,8&lt;br /&gt;
 Wait for Connected&lt;br /&gt;
 Load parameterfile &amp;quot;../parms/CommunicationTask/Communication_task_dual.prm&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The most are important sections to draw your attention to are:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 if ( State( &amp;quot;ClientNumber&amp;quot; ) == State( &amp;quot;turn&amp;quot; ) ) {&lt;br /&gt;
&lt;br /&gt;
ClientNumber is a state that is automatically sent by the server. It is an id, between 0 and N, where N is the number of clients connected, that can be used to differentiate between each client without having to run a separate application on each. &amp;quot;turn&amp;quot; is a shared state between the clients. Shared states are accessed in the exact same way that a normal BCI2000 state is accessed. This way we can use shared states and the client number to determine which client should be placing their mark. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 State( &amp;quot;turn&amp;quot; ) = 1;&lt;br /&gt;
&lt;br /&gt;
Shared states are also written to the exact same way as normal BCI2000 shared states. They will be automatically updated for the other clients.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  Start executable TicTacToe --local --Port=1234 --IPAddress=192.168.1.102 --SharedStates=grid,32&amp;amp;turn,8&amp;amp;x,8&amp;amp;y,8&lt;br /&gt;
&lt;br /&gt;
This is where we define the states that we want to share with &amp;quot;--SharedStates=&amp;quot;. The format is:&lt;br /&gt;
 --SharedStates=&amp;lt;state-1&amp;gt;,&amp;lt;state-1-size&amp;gt;&amp;amp;&amp;lt;state-2&amp;gt;,&amp;lt;state-2-size&amp;gt;&amp;amp;&amp;lt;state-3&amp;gt;,&amp;lt;state-3-size&amp;gt;...&lt;br /&gt;
We can also define predefined shared states here in a similar way, but without the size (because the size is already defined), using:&lt;br /&gt;
 --PreDefinedSharedStates=&amp;lt;state-1&amp;gt;&amp;amp;&amp;lt;state-2&amp;gt;&amp;amp;&amp;lt;state-3&amp;gt;&lt;br /&gt;
&lt;br /&gt;
--Port and --IPAddress are additional parameters that tell the client where to find the server on the internet. All of these parameters can also be changed from the Config menu, and the client connects to the server after &amp;quot;Set Config&amp;quot; is pressed.&lt;br /&gt;
&lt;br /&gt;
=== Live Interaction Stimulus ===&lt;br /&gt;
&lt;br /&gt;
The classic video game pong is an example of live interaction. Both players can interact with the game simultaneously. There are no discrete turns. We implemented pong with BCI2000 hyperscanning to demonstrate a live interaction.&lt;br /&gt;
&lt;br /&gt;
pong.cpp&lt;br /&gt;
 #include &amp;quot;Pong.h&amp;quot;&lt;br /&gt;
 #include &amp;quot;Shapes.h&amp;quot;&lt;br /&gt;
 #include &amp;lt;limits&amp;gt;&lt;br /&gt;
 #include &amp;quot;BCIEvent.h&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 //Shared States&lt;br /&gt;
 //BallX 32&lt;br /&gt;
 //BallY 32&lt;br /&gt;
 //BallVX 8&lt;br /&gt;
 //BallVY 8&lt;br /&gt;
 //Player1Y 32&lt;br /&gt;
 //Player2Y 32&lt;br /&gt;
 //Player1Ready 1&lt;br /&gt;
 //Player2Ready 1&lt;br /&gt;
 //GamePhase 8&lt;br /&gt;
 //&lt;br /&gt;
 //Game Phases&lt;br /&gt;
 //0 : Instruction&lt;br /&gt;
 //1 : Game&lt;br /&gt;
 //2 : Between Rounds&lt;br /&gt;
 &lt;br /&gt;
 RegisterFilter( Pong, 3 );&lt;br /&gt;
 &lt;br /&gt;
 Pong::Pong() : player1Paddle( NULL ), player2Paddle( NULL ), ball( NULL ), mrDisplay( Window() ) {&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 void Pong::SharedPublish() {&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 void Pong::SharedPreflight( const SignalProperties&amp;amp; Input, SignalProperties&amp;amp; Output ) const {&lt;br /&gt;
 	State( &amp;quot;BallX&amp;quot; );&lt;br /&gt;
 	State( &amp;quot;BallY&amp;quot; );&lt;br /&gt;
 	State( &amp;quot;BallVX&amp;quot; );&lt;br /&gt;
 	State( &amp;quot;BallVY&amp;quot; );&lt;br /&gt;
 	State( &amp;quot;Player1Y&amp;quot; );&lt;br /&gt;
 	State( &amp;quot;Player2Y&amp;quot; );&lt;br /&gt;
 	State( &amp;quot;Player1Ready&amp;quot; );&lt;br /&gt;
 	State( &amp;quot;Player2Ready&amp;quot; );&lt;br /&gt;
 	State( &amp;quot;GamePhase&amp;quot; );&lt;br /&gt;
 	State(&amp;quot;ClientNumber&amp;quot;);&lt;br /&gt;
 //	State( &amp;quot;KeyDown&amp;quot; );&lt;br /&gt;
 	Parameter( &amp;quot;SampleBlockSize&amp;quot; );&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 void Pong::SharedInitialize( const SignalProperties&amp;amp; Input, const SignalProperties&amp;amp; Output ) {&lt;br /&gt;
 	player1Paddle = new RectangularShape( mrDisplay );&lt;br /&gt;
 	player1Paddle-&amp;gt;SetFillColor( RGBColor::Teal );&lt;br /&gt;
 	player1Paddle-&amp;gt;SetVisible( true );&lt;br /&gt;
 &lt;br /&gt;
 	player2Paddle = new RectangularShape( mrDisplay );&lt;br /&gt;
 	player2Paddle-&amp;gt;SetFillColor( RGBColor::Red );&lt;br /&gt;
 	player2Paddle-&amp;gt;SetVisible( true );&lt;br /&gt;
 &lt;br /&gt;
 	ball = new RectangularShape( mrDisplay );&lt;br /&gt;
 	ball-&amp;gt;SetFillColor( RGBColor::Black );&lt;br /&gt;
 	ball-&amp;gt;SetVisible( true );&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 void Pong::SharedStartRun() {&lt;br /&gt;
 	State( &amp;quot;BallX&amp;quot; ) = 500;&lt;br /&gt;
 	State( &amp;quot;BallY&amp;quot; ) = 500;&lt;br /&gt;
 	State( &amp;quot;Player1Y&amp;quot; ) = 200;&lt;br /&gt;
 	State( &amp;quot;Player2Y&amp;quot; ) = 800;&lt;br /&gt;
 	State( &amp;quot;BallVX&amp;quot; ) = 493;&lt;br /&gt;
 	State( &amp;quot;BallVY&amp;quot; ) = 497;&lt;br /&gt;
 	State( &amp;quot;GamePhase&amp;quot; ) = 2;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 void Pong::SharedProcess( const GenericSignal&amp;amp; Input, GenericSignal&amp;amp; Output ) {&lt;br /&gt;
 	if ( State( &amp;quot;GamePhase&amp;quot; ) == 1 ) {&lt;br /&gt;
 		if ( State( &amp;quot;ClientNumber&amp;quot; ) == 0 ) {&lt;br /&gt;
 			State( &amp;quot;BallX&amp;quot; ) = State( &amp;quot;BallX&amp;quot; ) + State( &amp;quot;BallVX&amp;quot; ) - 500;&lt;br /&gt;
 			State( &amp;quot;BallY&amp;quot; ) = State( &amp;quot;BallY&amp;quot; ) + State( &amp;quot;BallVY&amp;quot; ) - 500;&lt;br /&gt;
 &lt;br /&gt;
 			if ( State( &amp;quot;BallY&amp;quot; ) &amp;gt; 950 || State( &amp;quot;BallY&amp;quot; ) &amp;lt; 50 ) {&lt;br /&gt;
 				State( &amp;quot;BallVY&amp;quot; ) = 1000 - State( &amp;quot;BallVY&amp;quot; );&lt;br /&gt;
 			}&lt;br /&gt;
 &lt;br /&gt;
 			if ( State( &amp;quot;BallX&amp;quot; ) + 50 &amp;gt; 875 &amp;amp;&amp;amp; State( &amp;quot;BallX&amp;quot; ) - 50 &amp;lt; 925 &amp;amp;&amp;amp; State( &amp;quot;BallY&amp;quot; ) + 50 &amp;gt; State( &amp;quot;Player2Y&amp;quot; ) - 100 &amp;amp;&amp;amp; State( &amp;quot;BallY&amp;quot; ) - 50 &amp;lt; State( &amp;quot;Player2Y&amp;quot; ) + 100 ) {&lt;br /&gt;
 				State( &amp;quot;BallVX&amp;quot; ) = 1000 - State( &amp;quot;BallVX&amp;quot; );&lt;br /&gt;
 				State( &amp;quot;BallX&amp;quot; ) = 875 - 50;&lt;br /&gt;
 			}&lt;br /&gt;
 &lt;br /&gt;
 			if ( State( &amp;quot;BallX&amp;quot; ) + 50 &amp;gt; 75  &amp;amp;&amp;amp; State( &amp;quot;BallX&amp;quot; ) - 50 &amp;lt; 125 &amp;amp;&amp;amp; State( &amp;quot;BallY&amp;quot; ) + 50 &amp;gt; State( &amp;quot;Player1Y&amp;quot; ) - 100 &amp;amp;&amp;amp; State( &amp;quot;BallY&amp;quot; ) - 50 &amp;lt; State( &amp;quot;Player1Y&amp;quot; ) + 100 ) {&lt;br /&gt;
 				State( &amp;quot;BallVX&amp;quot; ) = 1000 - State( &amp;quot;BallVX&amp;quot; );&lt;br /&gt;
 				State( &amp;quot;BallX&amp;quot; ) = 125 + 50;&lt;br /&gt;
 			}&lt;br /&gt;
 &lt;br /&gt;
 			if ( State( &amp;quot;BallX&amp;quot; ) + 50 &amp;gt; 1000 || State( &amp;quot;BallX&amp;quot; ) - 50 &amp;lt; 0 ) {&lt;br /&gt;
 				State( &amp;quot;BallX&amp;quot; ) = 500;&lt;br /&gt;
 				State( &amp;quot;BallVY&amp;quot; ) = State( &amp;quot;BallVY&amp;quot; ) + 1;&lt;br /&gt;
 				State( &amp;quot;GamePhase&amp;quot; ) = 2;&lt;br /&gt;
 			}&lt;br /&gt;
 		}&lt;br /&gt;
 &lt;br /&gt;
 		if ( CheckKeyPress( &amp;quot;KeyDown&amp;quot;, 38 ) ) { //Up&lt;br /&gt;
 			if ( State( &amp;quot;ClientNumber&amp;quot; ) == 0 )&lt;br /&gt;
 				State( &amp;quot;Player1Y&amp;quot; ) = State( &amp;quot;Player1Y&amp;quot; ) - 30;&lt;br /&gt;
 			else &lt;br /&gt;
 				State( &amp;quot;Player2Y&amp;quot; ) = State( &amp;quot;Player2Y&amp;quot; ) - 30;&lt;br /&gt;
 		}&lt;br /&gt;
 &lt;br /&gt;
 		if ( CheckKeyPress( &amp;quot;KeyDown&amp;quot;, 40 ) ) { //Down&lt;br /&gt;
 			if ( State( &amp;quot;ClientNumber&amp;quot; ) == 0 )&lt;br /&gt;
 				State( &amp;quot;Player1Y&amp;quot; ) = State( &amp;quot;Player1Y&amp;quot; ) + 30;&lt;br /&gt;
 			else &lt;br /&gt;
 				State( &amp;quot;Player2Y&amp;quot; ) = State( &amp;quot;Player2Y&amp;quot; ) + 30;&lt;br /&gt;
 		}&lt;br /&gt;
 	}&lt;br /&gt;
 &lt;br /&gt;
 	if ( State( &amp;quot;GamePhase&amp;quot; ) == 2 ) {&lt;br /&gt;
 		if ( CheckKeyPress( &amp;quot;KeyDown&amp;quot;, 32 ) == 0 ) { //Space&lt;br /&gt;
 			if ( State( &amp;quot;ClientNumber&amp;quot; ) == 0 )&lt;br /&gt;
 				State( &amp;quot;Player1Ready&amp;quot; ) = 1;&lt;br /&gt;
 			else&lt;br /&gt;
 				State( &amp;quot;Player2Ready&amp;quot; ) = 1;&lt;br /&gt;
 		}&lt;br /&gt;
 &lt;br /&gt;
 		if ( State( &amp;quot;Player1Ready&amp;quot; ) == 1 &amp;amp;&amp;amp; State( &amp;quot;Player2Ready&amp;quot; ) == 1 ) {&lt;br /&gt;
 			State( &amp;quot;GamePhase&amp;quot; ) = 1;&lt;br /&gt;
 			State( &amp;quot;Player1Ready&amp;quot; ) = 0;&lt;br /&gt;
 			State( &amp;quot;Player2Ready&amp;quot; ) = 0;&lt;br /&gt;
 		}&lt;br /&gt;
 	}&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 	bciout &amp;lt;&amp;lt; &amp;quot;Ball: (&amp;quot; &amp;lt;&amp;lt; State(&amp;quot;BallX&amp;quot;) &amp;lt;&amp;lt; &amp;quot;, &amp;quot; &amp;lt;&amp;lt; State(&amp;quot;BallY&amp;quot;) &amp;lt;&amp;lt; &amp;quot;)&amp;quot;;&lt;br /&gt;
 	bciout &amp;lt;&amp;lt; &amp;quot;Player1: &amp;quot; &amp;lt;&amp;lt; State(&amp;quot;Player1Y&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 	GUI::Rect rect = { ( State( &amp;quot;BallX&amp;quot; ) / 1000.f ) - 0.05, ( State( &amp;quot;BallY&amp;quot; ) / 1000.f ) - 0.05, ( State( &amp;quot;BallX&amp;quot; ) / 1000.f ) + 0.05, ( State( &amp;quot;BallY&amp;quot; ) / 1000.f ) + 0.05 };&lt;br /&gt;
 	ball-&amp;gt;SetObjectRect( rect );&lt;br /&gt;
 &lt;br /&gt;
 	rect = { 0.075f, ( State( &amp;quot;Player1Y&amp;quot; ) / 1000.f ) - 0.1f, 0.125f, ( State( &amp;quot;Player1Y&amp;quot; ) / 1000.f ) + 0.1f };&lt;br /&gt;
 	player1Paddle-&amp;gt;SetObjectRect( rect );&lt;br /&gt;
 &lt;br /&gt;
 	rect = { 0.875f, ( State( &amp;quot;Player2Y&amp;quot; ) / 1000.f ) - 0.1f, 0.925f, ( State( &amp;quot;Player2Y&amp;quot; ) / 1000.f ) + 0.1f };&lt;br /&gt;
 	player2Paddle-&amp;gt;SetObjectRect( rect );&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 bool Pong::CheckKeyPress( std::string event_name, int value ) {&lt;br /&gt;
 	for ( unsigned int i = 0; i &amp;lt; Parameter( &amp;quot;SampleBlockSize&amp;quot; ); i++ ) {&lt;br /&gt;
 		if ( State( event_name )( i ) == value ) {&lt;br /&gt;
 			return true;&lt;br /&gt;
 		}&lt;br /&gt;
 	}&lt;br /&gt;
 	return false;&lt;br /&gt;
 }&lt;br /&gt;
pong.h&lt;br /&gt;
 #include &amp;quot;Shapes.h&amp;quot;&lt;br /&gt;
 #include &amp;quot;ApplicationWindow.h&amp;quot;&lt;br /&gt;
 #include &amp;quot;HyperscanningApplicationBase.h&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 class Pong : public HyperscanningApplicationBase {&lt;br /&gt;
 	public:&lt;br /&gt;
 		Pong();&lt;br /&gt;
 &lt;br /&gt;
 		void SharedPublish() override;&lt;br /&gt;
 &lt;br /&gt;
 		void SharedPreflight( const SignalProperties&amp;amp; Input, SignalProperties&amp;amp; Output ) const override;&lt;br /&gt;
 		void SharedInitialize( const SignalProperties&amp;amp; Input, const SignalProperties&amp;amp; Output ) override;&lt;br /&gt;
 		void SharedProcess( const GenericSignal&amp;amp; Input, GenericSignal&amp;amp; Output ) override;&lt;br /&gt;
 		void SharedStartRun() override;&lt;br /&gt;
 &lt;br /&gt;
 		bool CheckKeyPress( std::string event_name, int value );&lt;br /&gt;
 &lt;br /&gt;
 	private:&lt;br /&gt;
 		ApplicationWindow&amp;amp; mrDisplay;&lt;br /&gt;
 		RectangularShape* player1Paddle;&lt;br /&gt;
 		RectangularShape* player2Paddle;&lt;br /&gt;
 		RectangularShape* ball;&lt;br /&gt;
 };&lt;br /&gt;
and pong.bat&lt;br /&gt;
 Change directory $BCI2000LAUNCHDIR&lt;br /&gt;
 Show window; Set title ${Extract file base $0}&lt;br /&gt;
 Reset system&lt;br /&gt;
 Startup system localhost&lt;br /&gt;
 Start executable SignalGenerator --local --LogKeyboard=1&lt;br /&gt;
 Start executable DummySignalProcessing --local&lt;br /&gt;
 Start executable Pong --local --Port=1234 --IPAddress=192.168.1.102 --SharedStates=BallX,32&amp;amp;BallY,32&amp;amp;Player1Y,32&amp;amp;Player2Y,32&amp;amp;BallVX,32&amp;amp;BallVY,32&amp;amp;Player1Ready,8&amp;amp;Player2Ready,8&amp;amp;GamePhase,8&amp;amp;Player1Score,8&amp;amp;Player2Score,8&lt;br /&gt;
 Wait for Connected&lt;br /&gt;
 Load parameterfile &amp;quot;../parms/CommunicationTask/Communication_task_dual.prm&amp;quot;&lt;br /&gt;
&lt;br /&gt;
This behaves very similarly to the tic-tac-toe example, with the key difference being both clients can interact with states simultaneously, whereas in tic-tac-toe only one client was changing states at a time.&lt;br /&gt;
&lt;br /&gt;
Any processing of game states, for example changing the position of the ball in pong, can occur on either the clients or the server depending on the wants and needs of each implementation. If they are placed on the client side, only one of clients should be responsible for actually processing the data because otherwise there could be multiple versions of the same state that are equally correct, because they were each accurately calculated by a different client, so the server would have to choose one state to save to the master state machine and discard the other versions. This could lead to jumpiness when displaying the state or bugs. Because only one client is processing data, only that client will have a greater load than the others. If the overhead of the game is too significant, this could become problematic. If the processing is done on the server, there will not be an issue with one client running slower, but it will be more tedious to implement, because a custom installation will have to be designed instead of a premade backend application, and a more powerful server will be required.&lt;br /&gt;
&lt;br /&gt;
For turn based games, this is a non-issue because each client can process the game state for their own turn. It only becomes an issue when a game state needs to be calculated that isn&#039;t based on client inputs, once again like the movement of the ball in pong, as opposed to the movement of the paddles in pong.&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=File:GameStateFigure.png&amp;diff=10442</id>
		<title>File:GameStateFigure.png</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=File:GameStateFigure.png&amp;diff=10442"/>
		<updated>2023-06-14T20:23:01Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: Mmarcus uploaded a new version of File:GameStateFigure.png&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=File:StateUpdatesFigure.png&amp;diff=10441</id>
		<title>File:StateUpdatesFigure.png</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=File:StateUpdatesFigure.png&amp;diff=10441"/>
		<updated>2023-06-14T20:12:20Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=File:ReconcilliationFigure.png&amp;diff=10440</id>
		<title>File:ReconcilliationFigure.png</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=File:ReconcilliationFigure.png&amp;diff=10440"/>
		<updated>2023-06-14T20:12:03Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=File:PauseFigure.png&amp;diff=10439</id>
		<title>File:PauseFigure.png</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=File:PauseFigure.png&amp;diff=10439"/>
		<updated>2023-06-14T20:11:46Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=File:GameStateUpdateFigure.png&amp;diff=10438</id>
		<title>File:GameStateUpdateFigure.png</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=File:GameStateUpdateFigure.png&amp;diff=10438"/>
		<updated>2023-06-14T20:11:29Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=File:GameStateFigure.png&amp;diff=10437</id>
		<title>File:GameStateFigure.png</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=File:GameStateFigure.png&amp;diff=10437"/>
		<updated>2023-06-14T20:11:15Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=File:Clientloopsfigure.png&amp;diff=10436</id>
		<title>File:Clientloopsfigure.png</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=File:Clientloopsfigure.png&amp;diff=10436"/>
		<updated>2023-06-14T20:10:54Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=BCI2000_Hyperscanning&amp;diff=10435</id>
		<title>BCI2000 Hyperscanning</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=BCI2000_Hyperscanning&amp;diff=10435"/>
		<updated>2023-06-14T20:02:52Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: BCI2000 Hyperscanning Documentation Page Creation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;BCI2000 Hyperscanning is a multiplayer simulation, a program that is synchronized over multiple computers, that supports the connection of two or more clients, the computers that are involved in the simulation. BCI2000 Hyperscanning also has subjects, which are the people that are using the client computers.&lt;br /&gt;
&lt;br /&gt;
In a multiplayer simulation, each client involved must know the current state of the game. This game state allows each client to determine the output that is shown to the user. In order for each client to display the same game to each user, each client must have the same game state. The game state is stored as a collection of state variables in a state machine.&lt;br /&gt;
A state machine is a set of variables, or states, that correspond with values. In essence, it is a simple database. The data in the database describes the state of the game (see figure \ref{fig:gamestate}).&lt;br /&gt;
&lt;br /&gt;
BCI2000 Hyperscanning has a master state machine that is stored on a centralized back-end server and one state machine for each client. Each client is connected to the back-end server through a TCP socket to ensure that each connection is maintained and everything that is sent is received. The clients output a stimulus to the user based on their state machines, and update their state machines based on user inputs. When one client updates its state machine, the server saves the game state in its master state machine and updates the other clients (see figure \ref{fig:gamestateupdate}).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    \includegraphics[width=\textwidth,height=\textheight,keepaspectratio]{Figures/GameStateFigure.pdf}&lt;br /&gt;
    \caption{Game State}&lt;br /&gt;
&lt;br /&gt;
    \includegraphics[width=\textwidth,height=\textheight,keepaspectratio]{Figures/GameStateUpdateFigure.pdf}&lt;br /&gt;
    \caption{Game State Update}&lt;br /&gt;
&lt;br /&gt;
    \includegraphics[width=0.995\textwidth,height=\textheight,keepaspectratio]{Figures/StateUpdatesFigure.pdf}&lt;br /&gt;
    \caption{Game State Update Scenarios}&lt;br /&gt;
&lt;br /&gt;
\caption{Game state overview. \textbf{(A)} The game state shows synchrony between the master game state, which is stored on the server, and the client game states. \textbf{(B)} The game state updates (bottom) show a typical interaction that would result in a game state update to the master game state and the ensuing update to the other client(s). In this example, the user clicks, indicating they would like to place a marker in the tic-tac-toe game, and this triggers a local game state update. This local game state update is sent to the server. The server saves the update and synchronizes the remaining client(s). After the interaction has concluded, each client is synchronized. \textbf{(C)} In scenario 1, the client updated its game state locally because of a user mouse press. This caused synchronization between it and the master game state to be lost. In this scenario, the client updates the master game state to match its game state. In scenario 2, a different client updated the master game state because of a user mouse press. This caused synchronization between the first client and the master game state to be lost. In this scenario, the server updates the first client to match its game state. }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Server ==&lt;br /&gt;
The purpose of the server, or back-end, is to store, update, and distribute a master list of states. It synchronizes each of the client&#039;s state machines, so that each client displays the same game. &lt;br /&gt;
&lt;br /&gt;
At a given time, one of the clients may have a state variable set to a value that is different from the value that the server has that state set to. At this point there are two possibilities. If that state was changed based on user inputs, then the server will update its state machine to reflect that user input. Otherwise, if the client has an old value, one that has been changed by another client, then the server will update the client with the new value of the state, so that each client is synchronized (see figure \ref{fig:gamestateupdatescenarios}).&lt;br /&gt;
&lt;br /&gt;
In addition to synchronizing states between clients, the backend must also synchronize many initial parameters to ensure that the exact same experiment is being run for each subject, e.g. the order of stimulus images needs to be synchronized. To solve this, the server contains a BCI2000 parameter file that is sent to each client when it connects to the server. This also serves as a greeting message to ensure that the connection is functioning before the experiment begins.&lt;br /&gt;
&lt;br /&gt;
The server application can be run from any mac or linux computer, whether it is local to one of the clients or in the cloud, as long as it is configured to allow TCP traffic. It is a collection of c++ classes and methods that are implemented into an application file. This application file is then run on the server computer. The server is not an instance of BCI2000. Rather, it is a separate application that interacts with client instances of BCI2000. &lt;br /&gt;
&lt;br /&gt;
While the idea for this hyperscanning architecture propagated from one experimental design, we ensured that this technology was robust enough to be used reused for any experiment, even if it is radically different from our initial one. The core of the back-end is simple and abstracted. It is a state machine that can be updated from clients and will propagate those updates to other clients. This simplicity means that the central parts of the back-end will work for any experimental paradigm. The simplicity of the core also allows for a more specific framework to be built surrounding the core, should that be necessary for a specific application. &lt;br /&gt;
&lt;br /&gt;
For each paradigm, an application file is implemented on the server. This application file will always contain the basic backend framework, like connecting to clients and running the actual data exchange loop, but it can also contain more specific instructions. For example, if parameters need to be randomly generated and synchronized across clients the core design is flexible enough to allow that to be built. Parameters can be added to the previously mentioned parameter file through the application file to solve this particular example. If there is a paradigm requiring more complex changes to the standard backend, the core can also be broken down into its individual steps to allow that.  &lt;br /&gt;
&lt;br /&gt;
The backend runs in a continuous loop of data exchanges with the clients. This loop continues for as long as the experiment runs. The end to the session, and thus the loop, is singaled by one of the clients breaking its connection with the server. &lt;br /&gt;
&lt;br /&gt;
Even though a client disconnects, the experiment may not be concluded. There could have been a crash, internet issues, or the investigator may have wanted to pause the experiment, but the server cannot continue operating properly after a client has disconnected. To solve this issue, the application file can access the state machine after the loop has ended, and save any of the states that are necessary to redetermine the experimental state after a restart. These values can then be passed to BCI2000 as parameters when it is restarted. For example, the trial number can be saved and passed to BCI2000 as an initial trial number parameter (see figure \ref{fig:pause}).&lt;br /&gt;
&lt;br /&gt;
    \includegraphics[width=\textwidth,height=\textheight,keepaspectratio]{Figures/PauseFigure.pdf}&lt;br /&gt;
    \caption{(is this unclear because it is only a single client?) Example paradigm with pause feature. This is a stimulus presentation paradigm, with a progression of faces being shown to the subject. During the first recording session, the subject gets through the first two trials before the session ends. The current trial number is saved to the server. During the next recording session, the server sends the current trial number, three, to the client; the client begins the session at trial number three and completes the paradigm. }&lt;br /&gt;
&lt;br /&gt;
=== Server Loop ===&lt;br /&gt;
The loop has three main steps (see figure \ref{fig:serverloop}). First, the server updates any states changed by the clients. Second, the server reconciles all of the updated states. Third, the server sends updated states back to the clients. &lt;br /&gt;
&lt;br /&gt;
    \includegraphics[width=\textwidth,height=\textheight,keepaspectratio]{Figures/ReconcilliationFigure.pdf}&lt;br /&gt;
    \caption{(consider giving an example of other test) Progression of state updates over time. Each client sends state updates, indicated by black arrows, to the server-side-client state machines, indicated by pink arrows. The server side state machines send the state updates to the master state machine. These state updates include conflicting information; the master state machine saves the state update from client 1 and disregards the conflicting update from client 2. The server sends the changed states, indicated by triangular arrows and blue ovals, back to the server-side-client state machines. The server-side-client state machines send their changed states back to the clients. }&lt;br /&gt;
&lt;br /&gt;
==== Client Updates ====&lt;br /&gt;
&lt;br /&gt;
In this step, the server simply waits for at least one of the clients to send states that were changed locally. If a client has not sent any data, then the server will wait for 2ms before checking another client. The server saves the data sent by the client in a state machine that tracks the current values of the states on each client. These are the server-side-client state machines.&lt;br /&gt;
&lt;br /&gt;
==== Reconciliation ====&lt;br /&gt;
In this step, the server decides which states to save and prepares the updates to send to each client. After each client sends its updates, the server-side-client machines are different from the master state machine and from each other, but they are synchronized with their respective clients. The server has to synchronize all of these state machines by saving client changes to the master state machine and sending updates to the clients, but it is necessary to save only one version of each state and to send only updates with new information. If the server repeats state updates by sending the same update twice or by echoing a state change back to the client that sent it, that state will be changed at multiple times for that client, which can cause irregularities and bugs. %Tracker state machines, which track the changes when a state machine is updated, are used to ensure that only actual changes are sent to the clients. One tracker is used to determine all the changes to the master state machine from the client updates. These changes are then used to update the server-side-client state machines. The changes to the server-side-client state machines are only the updates from other clients that were saved as master states, so they are then used to update the actual client state machines.&lt;br /&gt;
&lt;br /&gt;
To solve this, each state must pass two tests to get sent to a client. First, it must have been saved to the master state machine. Second, it must have been sent by a different client. These tests are implemented using tracker state machines, which track the changes that occur when a state machine is updated. For the first test, the server updates the master state machine from the server-side-client state machines and tracks the changes. For the second test, the changes to the master state machine are used to update the server-side-client state machines, and the changes from this interaction are tracked. The changes to the server-side-client state machines pass both tests, because they were changed on the master state machine (they were saved to the master state machine) and one of the client state machines (they weren&#039;t sent by that client because, in that case, they would have already been updated). These changes can be sent to the clients.&lt;br /&gt;
&lt;br /&gt;
==== Update Clients ====&lt;br /&gt;
This final step is the opposite of the first step. The server sends the prepared states to the clients. After this step, the loop repeats, and the server waits for the client to send updates again. &lt;br /&gt;
&lt;br /&gt;
== Clients ==&lt;br /&gt;
The purpose of the clients is to display the stimulus to the subject. Additionally, it is responsible for actually calculating the values of the game states. Each client is a separate instance of BCI2000, which are run on separate computers. They can be next to each other or hundreds of miles apart depending on the needs of the experiment.&lt;br /&gt;
&lt;br /&gt;
Once again, the structure is designed to be robust and reusable. To this end, the client exists in two pieces. The true frontend, which is responsible for calculating state values and outputting the stimulus, and the network logger, which is responsible for communication with the server. The true frontend is designed as a typical BCI2000 experiment, and thus will be different for every experiment. The network logger contains everything that will be the exact same for every BCI2000 Hyperscanning experiment. Thus, the network logger can be reused, while the true frontend is redesigned for every new experiment.&lt;br /&gt;
&lt;br /&gt;
The network logger is a part of the hyperscanning application base, which is a c++ class that a hyperscanning paradigm can be built upon. The hyperscanning application base will connect the network logger to the application module. &lt;br /&gt;
&lt;br /&gt;
BCI2000 has its own built in state machine. The network logger seamlessly updates a predefined set of these BCI2000 states based on server activity and the activity of other clients. It translates server data into BCI2000 states. The list of states that are updated by the network logger is defined in a BCI2000 parameter called shared states that contains both the names and the sizes of each of the states that the designer wants to be synchronized amongst the clients. To ensure that the states are sent rapidly, only the necessary states should be sent between clients, so they must be defined in this parameter. Other BCI2000 states will not be synchronized.&lt;br /&gt;
&lt;br /&gt;
=== Client Loops ===&lt;br /&gt;
Much like the server, the network logger loops, however, in order to conform with BCI2000 two distinct loops are utilized. One of them is synchronous with the rest of BCI2000. BCI2000 only allows its states to be changed during specific phases, so one of the loops must be synchronized with BCI2000. %The limitations of BCI2000 states require that state changes occur only during a specific time period, which necessitates synchronizing the loop with BCI2000. &lt;br /&gt;
While BCI2000 has a type of state that can be written to asynchronously, called an event, they are added to a queue and changed at a later time. This means the network logger cannot differentiate changes it made from changes the frontend made, so it doesn&#039;t know which changes to send to the server. The other loop is asynchronous, and makes use of multi-threading and parallel processing to increase the speed that data transfers can be made at, ensuring the greatest possible synchronicity between clients.&lt;br /&gt;
&lt;br /&gt;
Because these loops are both operating on the same data, i.e. the states that need to be changed, there is the risk of data corruption if both try to operate at the same time. The data is stored in mutexed buffers to ensure that does not happen. Mutexed buffers can only be written to or read by a single source at a time. If multiple sources try to access a mutexed buffer, one of them must wait for the other to finish its operation.&lt;br /&gt;
&lt;br /&gt;
Two buffers are shared between the two loops (see figure \ref{fig:clientloops}). One is a state machine that contains the name and value of each shared state, along with whether or not the state has a change from the server that hasn&#039;t been updated to the BCI2000 states, and the other is a message for the server that contains the states that have been updated by the frontend.&lt;br /&gt;
&lt;br /&gt;
    \includegraphics[width=\textwidth,height=\textheight,keepaspectratio]{Figures/clientloopsfigure.pdf}&lt;br /&gt;
    \caption{Synchronous and asynchronous client loops and their data exchanges. The client updates a state, e.g. they indicate their move in tic-tac-toe with a mouse click, and the synchronous client loop adds that change to the message for the server. The asynchronous loop sends the message to the server. The asynchronous loop continues looping until it gets a response from the server. When it gets a response from the server, e.g. the other client&#039;s move, it adds it to the changed states buffer. The synchronous loop saves the changes in the changed states buffer to the BCI2000 state machine.}&lt;br /&gt;
&lt;br /&gt;
==== Synchronous Loop ====&lt;br /&gt;
&lt;br /&gt;
The synchronous loop first updates all of the BCI2000 states that have been changed by the server. %to the value sent by the server. &lt;br /&gt;
The loop then determines if any of the states in the mutexed state machine are different from their BCI2000 counterpart. Because all of the states that were different from BCI2000 because of a server update were just updated, all of the remaining discrepancies must be due to a client change. These are then recorded in the message for the server. &lt;br /&gt;
&lt;br /&gt;
It is very important for analyzing the experiment that the investigator knows when states were changed in relation to the recorded data. This could be complicated when states are being sent over the internet with delays and lag, but the network logger and BCI2000 radically simplify it. The important timestamp to record is when the state had an effect on the actual stimulus, because this is when it can have an effect on the subject. The timestamp of BCI2000 states is recorded whenever they are changed, and it is the BCI2000 states that have an effect on the stimulus. It is also BCI2000 that is providing the timestamps for the recorded data, therefore those timestamps will provide an accurate comparison between state changes and recorded data.&lt;br /&gt;
&lt;br /&gt;
==== Asynchronous Loop ====&lt;br /&gt;
&lt;br /&gt;
The asynchronous loop first sends the mutexed message to the server. If the message is empty, it doesn&#039;t send anything. This is the message that the server waits for in section 2.1.1. The loop then waits for a message from the server with the changes other clients have made. It waits 2ms for the server before moving on. This is the message the server sends in section 2.1.3. The loop then records these changes in the mutexed state machine and flags that they have a change from the server.&lt;br /&gt;
&lt;br /&gt;
=== Client Initialization ===&lt;br /&gt;
&lt;br /&gt;
The client initializes its connection with the server during the AutoConfig phase of BCI2000. This occurs after the Set Config button is pressed. The client first ensures that it hasn&#039;t already established a connection with the server, then it connects to the server. It uses user defined parameters to determine the IP address and port of the server application. The port of the server is defined by the designer in the server application file. The client then waits for the server to send an initial message that contains a client number and initial parameters. The client number is an id for the client to use to differentiate itself from other clients. For example, if each subject plays a different role in the paradigm, then the client number can be used to differentiate between roles. The parameters are then used to set BCI2000&#039;s parameters.&lt;br /&gt;
&lt;br /&gt;
== Example Paradigm Design ==&lt;br /&gt;
To exemplify and test this method of hyperscanning, we created three example paradigms. One of them is used for testing, and the other two are two different types of games, which can both be implemented with BCI2000 Hyperscanning.&lt;br /&gt;
&lt;br /&gt;
=== Testing ===&lt;br /&gt;
&lt;br /&gt;
For testing the timing and latency of the system, we designed a simple photo diode test stimulus (see figure \ref{fig:test-paradigm}). One client changes a state and flashes the screen white. When the other client receives the state change, it flashes its screen white. This is then repeated after a delay, starting with the second client changing the state. That echoing process is repeated for the duration of the test. The photo diodes must be on the same clock to ensure accuracy, so one of the clients has a photo diode attached to each client&#039;s screen. The photo diodes are connected to a g.TrigBox, which records flashes of light in BCI2000.&lt;br /&gt;
&lt;br /&gt;
    \includegraphics[width=\textwidth,height=\textheight,keepaspectratio]{Figures/TestParadigm.pdf}&lt;br /&gt;
    \caption{(Remove first black square) Photodiode testing paradigm. Client 1 flashes the screen white and sends a game state update to the server. The server sends the game state update to client 2. client 2 flashes the screen. The elapsed time is one server tick, which is the amount of time for a state update from one client to reach the second client. This is the latency of the system that we want to determine. After 20 BCI2000 blocks, the sequence is repeated, but initiated by client 2. Client 2 flashes the screen and updates the server, which updates client 1. Client 1 flashes its screen. This sequence is repeated for the duration of the session.}&lt;br /&gt;
&lt;br /&gt;
=== Turn Based Stimulus ===&lt;br /&gt;
&lt;br /&gt;
The well-known game Tic-Tac-Toe is an example of a turn based game. One player takes their turn, then the other player takes their turn. Each turn is taken after the previous one, with no overlap in timing. We implemented Tic-Tac-Toe to show how a turn based game works with BCI2000 hyperscanning.&lt;br /&gt;
&lt;br /&gt;
=== Live Interaction Stimulus ===&lt;br /&gt;
&lt;br /&gt;
The classic video game pong is an example of live interaction. Both players can interact with the game simultaneously. There are no discrete turns. We implemented pong with BCI2000 hyperscanning to demonstrate a live interaction.&lt;br /&gt;
&lt;br /&gt;
Any processing of game states, for example changing the position of the ball in pong, can occur on either the clients or the server depending on the wants and needs of each implementation. If they are placed on the client side, only one of clients should be responsible for actually processing the data because otherwise there could be multiple versions of the same state that are equally correct, because they were each accurately calculated by a different client, so the server would have to choose one state to save to the master state machine and discard the other versions. This could lead to jumpiness when displaying the state or bugs. Because only one client is processing data, only that client will have a greater load than the others. If the overhead of the game is too significant, this could become problematic. If the processing is done on the server, there will not be an issue with one client running slower, but it will be more tedious to implement, because a custom installation will have to be designed instead of a premade backend application, and a more powerful server will be required.&lt;br /&gt;
&lt;br /&gt;
For turn based games, this is a non-issue because each client can process the game state for their own turn. It only becomes an issue when a game state needs to be calculated that isn&#039;t based on client inputs, once again like the movement of the ball in pong, as opposed to the movement of the paddles in pong.&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=File:GameStateFigure.pdf&amp;diff=10434</id>
		<title>File:GameStateFigure.pdf</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=File:GameStateFigure.pdf&amp;diff=10434"/>
		<updated>2023-06-14T19:59:28Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:Automatically_Build_BCI2000_on_Non-Windows_Platforms&amp;diff=9933</id>
		<title>Programming Howto:Automatically Build BCI2000 on Non-Windows Platforms</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:Automatically_Build_BCI2000_on_Non-Windows_Platforms&amp;diff=9933"/>
		<updated>2022-09-16T00:59:53Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: /* Run Install Script */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=[[Programming Howto:Building_and_Customizing_BCI2000_on_Non-Windows_Platforms|Back]]=&lt;br /&gt;
[[Programming Howto:Building_and_Customizing_BCI2000_on_Non-Windows_Platforms|to the overview page]]&lt;br /&gt;
=Navigate to BCI2000 Directory=&lt;br /&gt;
Navigate to the BCI2000 &amp;quot;trunk&amp;quot; directory in a finder window.&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:Trunk-directory-non-windows.png|700px]]&lt;br /&gt;
=Run Install Script=&lt;br /&gt;
Double click on the script named &amp;quot;install.&amp;quot; It will begin the installation process in a new terminal window. First, it will prompt you for your Qt installation directory. If you installed Qt with homebrew this will be /opt/homebrew/Cellar/qt@5/5.15.5_1/ on apple silicon or /usr/homebrew/Cellar/qt@5/5.15.5_1/ otherwise. If neither of these locations exist and you installed Qt with homebrew, this can be found by running&lt;br /&gt;
 brew list qt@5&lt;br /&gt;
in a terminal window. The installation directory is only the part of the paths that are&lt;br /&gt;
 .../hombrew/Cellar/qt@5/&amp;lt;version&amp;gt;&lt;br /&gt;
Use everything up to the version and nothing past it. Drag this folder onto the window and press Enter. After you press Enter, the installation will continue without any additional user input.&lt;br /&gt;
[[File:Automatic-compile-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
Once this script finishes running, your BCI2000 will be built!&lt;br /&gt;
&lt;br /&gt;
[[File:Screen Shot 2022-08-12 at 3.55.18 PM.png|700px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
And the &amp;quot;prog&amp;quot; directory in your BCI2000 trunk will have been populated with executables.&lt;br /&gt;
&lt;br /&gt;
[[File:Prog-folder-non-windows.png|700px]]&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:Manually_Build_BCI2000_on_Non-Windows_Platforms&amp;diff=9932</id>
		<title>Programming Howto:Manually Build BCI2000 on Non-Windows Platforms</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:Manually_Build_BCI2000_on_Non-Windows_Platforms&amp;diff=9932"/>
		<updated>2022-09-16T00:57:13Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: /* Tell CMake which Qt installation to use */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Installing Dependencies==&lt;br /&gt;
There are three dependencies that need to be installed before you can compile BCI2000:&lt;br /&gt;
*ffmpeg (version 4.4.1, version 5 does not work with BCI2000)&lt;br /&gt;
*portaudio&lt;br /&gt;
*sdl2&lt;br /&gt;
These can be installed using the &lt;br /&gt;
 install_dependencies&lt;br /&gt;
script in the BCI2000 home directory. This will automatically detect your homebrew or it will download a portable version of homebrew in your BCI2000 directory. Then it will install the necessary dependencies. Alternatively, you can manually install them, and they will be automatically detected by CMake. If you have already installed homebrew, this can be done with&lt;br /&gt;
 brew install ffmpeg@4&lt;br /&gt;
 brew link ffmpeg@4&lt;br /&gt;
 brew install portaudio&lt;br /&gt;
 brew install sdl2&lt;br /&gt;
&lt;br /&gt;
==Configure BCI2000 for Compilation==&lt;br /&gt;
&lt;br /&gt;
===Run the CMake GUI===&lt;br /&gt;
Double-click &amp;quot;Configure.sh.cmd&amp;quot; in your BCI2000 build directory.&lt;br /&gt;
&lt;br /&gt;
[[File:Cmake-init-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Tell CMake which Qt installation to use===&lt;br /&gt;
Click &amp;quot;AddEntry&amp;quot; in the CMake window (&amp;lt;i&amp;gt;Note that checking off &amp;quot;Advanced&amp;quot; in Cmake is optional and does not impact the compilation&amp;lt;/i&amp;gt;) and enter the path to a Qt directory. If you installed Qt with homebrew, this can be found with&lt;br /&gt;
 brew list qt@5&lt;br /&gt;
The installation directory is only the part of the paths that are&lt;br /&gt;
 .../hombrew/Cellar/qt@5/&amp;lt;version&amp;gt;&lt;br /&gt;
Use everything up to the version and nothing past it.&lt;br /&gt;
Use CMAKE_PREFIX_PATH as the name for the new entry. Be aware that the entry&#039;s name is case sensitive. &amp;lt;b&amp;gt;Currently, on non-windows platform, Qt 5 is the only version that is supported.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Cmake-add-cache-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Perform the configuration step===&lt;br /&gt;
In the CMake window, click &amp;quot;Configure&amp;quot; and choose a generator that is consistent with your compiler. This tutorial will be using Unix Makefiles. Then click &amp;quot;Done&amp;quot; to perform the configuration step. &lt;br /&gt;
[[File:Cmake-generators-non-windows.png|700px]]&lt;br /&gt;
&amp;lt;br&amp;gt;You will see a list of targets scrolling by, and a number of new entries in the variable list at the top of the window, marked in red.&lt;br /&gt;
&lt;br /&gt;
===Choose Build Options===&lt;br /&gt;
Make sure the &amp;quot;Grouped&amp;quot; checkbox is checked, and configure the build by customizing values in the &amp;quot;BUILD&amp;quot; group, &amp;quot;EXTENSIONS&amp;quot; group,  and &amp;quot;USE&amp;quot; group. &lt;br /&gt;
[[File:Cmake-configured-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Generate Makefiles===&lt;br /&gt;
Then, click &amp;quot;Generate&amp;quot; to create build files. When CMake displays its &amp;quot;Generating done&amp;quot; message, your BCI2000 build directory will now contain a Makefile (or a project file for your compiler of chioce), as well as a number of additional CMake-generated files.&lt;br /&gt;
&lt;br /&gt;
[[File:Cmake-done-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
==Compile BCI2000==&lt;br /&gt;
===Open Terminal===&lt;br /&gt;
Open a new terminal window and navigate to your BCI2000 build directory.&lt;br /&gt;
&lt;br /&gt;
[[File:terminal-bulid-directory-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Build Makefiles===&lt;br /&gt;
Run:&lt;br /&gt;
 make&lt;br /&gt;
from your BCI2000 build directory. Once this is finished your BCI2000 prog directory will contain a number of executables, one for each module, plus a few helper executables. Not everything works the same or, in some cases, at all on non-windows platforms. See, [[Non-Windows Functionality]] for more information.&lt;br /&gt;
&lt;br /&gt;
[[File:Make-done-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
The build process is now complete. Run &lt;br /&gt;
 make&lt;br /&gt;
again to recompile. Or&lt;br /&gt;
 make &amp;lt;target&amp;gt;&lt;br /&gt;
to recompile only a specific target.&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:Manually_Build_BCI2000_on_Non-Windows_Platforms&amp;diff=9931</id>
		<title>Programming Howto:Manually Build BCI2000 on Non-Windows Platforms</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:Manually_Build_BCI2000_on_Non-Windows_Platforms&amp;diff=9931"/>
		<updated>2022-09-16T00:54:23Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: /* Build Makefiles */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Installing Dependencies==&lt;br /&gt;
There are three dependencies that need to be installed before you can compile BCI2000:&lt;br /&gt;
*ffmpeg (version 4.4.1, version 5 does not work with BCI2000)&lt;br /&gt;
*portaudio&lt;br /&gt;
*sdl2&lt;br /&gt;
These can be installed using the &lt;br /&gt;
 install_dependencies&lt;br /&gt;
script in the BCI2000 home directory. This will automatically detect your homebrew or it will download a portable version of homebrew in your BCI2000 directory. Then it will install the necessary dependencies. Alternatively, you can manually install them, and they will be automatically detected by CMake. If you have already installed homebrew, this can be done with&lt;br /&gt;
 brew install ffmpeg@4&lt;br /&gt;
 brew link ffmpeg@4&lt;br /&gt;
 brew install portaudio&lt;br /&gt;
 brew install sdl2&lt;br /&gt;
&lt;br /&gt;
==Configure BCI2000 for Compilation==&lt;br /&gt;
&lt;br /&gt;
===Run the CMake GUI===&lt;br /&gt;
Double-click &amp;quot;Configure.sh.cmd&amp;quot; in your BCI2000 build directory.&lt;br /&gt;
&lt;br /&gt;
[[File:Cmake-init-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Tell CMake which Qt installation to use===&lt;br /&gt;
Click &amp;quot;AddEntry&amp;quot; in the CMake window (&amp;lt;i&amp;gt;Note that checking off &amp;quot;Advanced&amp;quot; in Cmake is optional and does not impact the compilation&amp;lt;/i&amp;gt;) and enter the path to a Qt directory. If you installed Qt with homebrew this will be /opt/homebrew/Cellar/qt@5/5.15.5_1/ on apple silicon or /usr/homebrew/Cellar/qt@5/5.15.5_1/ otherwise. Use CMAKE_PREFIX_PATH as the name for the new entry. Be aware that the entry&#039;s name is case sensitive. &amp;lt;b&amp;gt;Currently, on non-windows platform, Qt 5 is the only version that is supported.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Cmake-add-cache-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Perform the configuration step===&lt;br /&gt;
In the CMake window, click &amp;quot;Configure&amp;quot; and choose a generator that is consistent with your compiler. This tutorial will be using Unix Makefiles. Then click &amp;quot;Done&amp;quot; to perform the configuration step. &lt;br /&gt;
[[File:Cmake-generators-non-windows.png|700px]]&lt;br /&gt;
&amp;lt;br&amp;gt;You will see a list of targets scrolling by, and a number of new entries in the variable list at the top of the window, marked in red.&lt;br /&gt;
&lt;br /&gt;
===Choose Build Options===&lt;br /&gt;
Make sure the &amp;quot;Grouped&amp;quot; checkbox is checked, and configure the build by customizing values in the &amp;quot;BUILD&amp;quot; group, &amp;quot;EXTENSIONS&amp;quot; group,  and &amp;quot;USE&amp;quot; group. &lt;br /&gt;
[[File:Cmake-configured-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Generate Makefiles===&lt;br /&gt;
Then, click &amp;quot;Generate&amp;quot; to create build files. When CMake displays its &amp;quot;Generating done&amp;quot; message, your BCI2000 build directory will now contain a Makefile (or a project file for your compiler of chioce), as well as a number of additional CMake-generated files.&lt;br /&gt;
&lt;br /&gt;
[[File:Cmake-done-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
==Compile BCI2000==&lt;br /&gt;
===Open Terminal===&lt;br /&gt;
Open a new terminal window and navigate to your BCI2000 build directory.&lt;br /&gt;
&lt;br /&gt;
[[File:terminal-bulid-directory-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Build Makefiles===&lt;br /&gt;
Run:&lt;br /&gt;
 make&lt;br /&gt;
from your BCI2000 build directory. Once this is finished your BCI2000 prog directory will contain a number of executables, one for each module, plus a few helper executables. Not everything works the same or, in some cases, at all on non-windows platforms. See, [[Non-Windows Functionality]] for more information.&lt;br /&gt;
&lt;br /&gt;
[[File:Make-done-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
The build process is now complete. Run &lt;br /&gt;
 make&lt;br /&gt;
again to recompile. Or&lt;br /&gt;
 make &amp;lt;target&amp;gt;&lt;br /&gt;
to recompile only a specific target.&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:Manually_Build_BCI2000_on_Non-Windows_Platforms&amp;diff=9930</id>
		<title>Programming Howto:Manually Build BCI2000 on Non-Windows Platforms</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:Manually_Build_BCI2000_on_Non-Windows_Platforms&amp;diff=9930"/>
		<updated>2022-09-16T00:54:13Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: /* Open Terminal */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Installing Dependencies==&lt;br /&gt;
There are three dependencies that need to be installed before you can compile BCI2000:&lt;br /&gt;
*ffmpeg (version 4.4.1, version 5 does not work with BCI2000)&lt;br /&gt;
*portaudio&lt;br /&gt;
*sdl2&lt;br /&gt;
These can be installed using the &lt;br /&gt;
 install_dependencies&lt;br /&gt;
script in the BCI2000 home directory. This will automatically detect your homebrew or it will download a portable version of homebrew in your BCI2000 directory. Then it will install the necessary dependencies. Alternatively, you can manually install them, and they will be automatically detected by CMake. If you have already installed homebrew, this can be done with&lt;br /&gt;
 brew install ffmpeg@4&lt;br /&gt;
 brew link ffmpeg@4&lt;br /&gt;
 brew install portaudio&lt;br /&gt;
 brew install sdl2&lt;br /&gt;
&lt;br /&gt;
==Configure BCI2000 for Compilation==&lt;br /&gt;
&lt;br /&gt;
===Run the CMake GUI===&lt;br /&gt;
Double-click &amp;quot;Configure.sh.cmd&amp;quot; in your BCI2000 build directory.&lt;br /&gt;
&lt;br /&gt;
[[File:Cmake-init-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Tell CMake which Qt installation to use===&lt;br /&gt;
Click &amp;quot;AddEntry&amp;quot; in the CMake window (&amp;lt;i&amp;gt;Note that checking off &amp;quot;Advanced&amp;quot; in Cmake is optional and does not impact the compilation&amp;lt;/i&amp;gt;) and enter the path to a Qt directory. If you installed Qt with homebrew this will be /opt/homebrew/Cellar/qt@5/5.15.5_1/ on apple silicon or /usr/homebrew/Cellar/qt@5/5.15.5_1/ otherwise. Use CMAKE_PREFIX_PATH as the name for the new entry. Be aware that the entry&#039;s name is case sensitive. &amp;lt;b&amp;gt;Currently, on non-windows platform, Qt 5 is the only version that is supported.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Cmake-add-cache-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Perform the configuration step===&lt;br /&gt;
In the CMake window, click &amp;quot;Configure&amp;quot; and choose a generator that is consistent with your compiler. This tutorial will be using Unix Makefiles. Then click &amp;quot;Done&amp;quot; to perform the configuration step. &lt;br /&gt;
[[File:Cmake-generators-non-windows.png|700px]]&lt;br /&gt;
&amp;lt;br&amp;gt;You will see a list of targets scrolling by, and a number of new entries in the variable list at the top of the window, marked in red.&lt;br /&gt;
&lt;br /&gt;
===Choose Build Options===&lt;br /&gt;
Make sure the &amp;quot;Grouped&amp;quot; checkbox is checked, and configure the build by customizing values in the &amp;quot;BUILD&amp;quot; group, &amp;quot;EXTENSIONS&amp;quot; group,  and &amp;quot;USE&amp;quot; group. &lt;br /&gt;
[[File:Cmake-configured-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Generate Makefiles===&lt;br /&gt;
Then, click &amp;quot;Generate&amp;quot; to create build files. When CMake displays its &amp;quot;Generating done&amp;quot; message, your BCI2000 build directory will now contain a Makefile (or a project file for your compiler of chioce), as well as a number of additional CMake-generated files.&lt;br /&gt;
&lt;br /&gt;
[[File:Cmake-done-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
==Compile BCI2000==&lt;br /&gt;
===Open Terminal===&lt;br /&gt;
Open a new terminal window and navigate to your BCI2000 build directory.&lt;br /&gt;
&lt;br /&gt;
[[File:terminal-bulid-directory-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Build Makefiles===&lt;br /&gt;
Run:&lt;br /&gt;
 make&lt;br /&gt;
from your BCI2000 build directory. Once this is finished your BCI2000 prog directory will contain a number of executables, one for each module, plus a few helper executables. Not everything works the same or, in some cases, at all on non-windows platforms. See, [[Non-Windows Functionality]] for more information.&lt;br /&gt;
[[File:Make-done-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
The build process is now complete. Run &lt;br /&gt;
 make&lt;br /&gt;
again to recompile. Or&lt;br /&gt;
 make &amp;lt;target&amp;gt;&lt;br /&gt;
to recompile only a specific target.&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:Manually_Build_BCI2000_on_Non-Windows_Platforms&amp;diff=9929</id>
		<title>Programming Howto:Manually Build BCI2000 on Non-Windows Platforms</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:Manually_Build_BCI2000_on_Non-Windows_Platforms&amp;diff=9929"/>
		<updated>2022-09-16T00:54:06Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: /* Generate Makefiles */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Installing Dependencies==&lt;br /&gt;
There are three dependencies that need to be installed before you can compile BCI2000:&lt;br /&gt;
*ffmpeg (version 4.4.1, version 5 does not work with BCI2000)&lt;br /&gt;
*portaudio&lt;br /&gt;
*sdl2&lt;br /&gt;
These can be installed using the &lt;br /&gt;
 install_dependencies&lt;br /&gt;
script in the BCI2000 home directory. This will automatically detect your homebrew or it will download a portable version of homebrew in your BCI2000 directory. Then it will install the necessary dependencies. Alternatively, you can manually install them, and they will be automatically detected by CMake. If you have already installed homebrew, this can be done with&lt;br /&gt;
 brew install ffmpeg@4&lt;br /&gt;
 brew link ffmpeg@4&lt;br /&gt;
 brew install portaudio&lt;br /&gt;
 brew install sdl2&lt;br /&gt;
&lt;br /&gt;
==Configure BCI2000 for Compilation==&lt;br /&gt;
&lt;br /&gt;
===Run the CMake GUI===&lt;br /&gt;
Double-click &amp;quot;Configure.sh.cmd&amp;quot; in your BCI2000 build directory.&lt;br /&gt;
&lt;br /&gt;
[[File:Cmake-init-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Tell CMake which Qt installation to use===&lt;br /&gt;
Click &amp;quot;AddEntry&amp;quot; in the CMake window (&amp;lt;i&amp;gt;Note that checking off &amp;quot;Advanced&amp;quot; in Cmake is optional and does not impact the compilation&amp;lt;/i&amp;gt;) and enter the path to a Qt directory. If you installed Qt with homebrew this will be /opt/homebrew/Cellar/qt@5/5.15.5_1/ on apple silicon or /usr/homebrew/Cellar/qt@5/5.15.5_1/ otherwise. Use CMAKE_PREFIX_PATH as the name for the new entry. Be aware that the entry&#039;s name is case sensitive. &amp;lt;b&amp;gt;Currently, on non-windows platform, Qt 5 is the only version that is supported.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Cmake-add-cache-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Perform the configuration step===&lt;br /&gt;
In the CMake window, click &amp;quot;Configure&amp;quot; and choose a generator that is consistent with your compiler. This tutorial will be using Unix Makefiles. Then click &amp;quot;Done&amp;quot; to perform the configuration step. &lt;br /&gt;
[[File:Cmake-generators-non-windows.png|700px]]&lt;br /&gt;
&amp;lt;br&amp;gt;You will see a list of targets scrolling by, and a number of new entries in the variable list at the top of the window, marked in red.&lt;br /&gt;
&lt;br /&gt;
===Choose Build Options===&lt;br /&gt;
Make sure the &amp;quot;Grouped&amp;quot; checkbox is checked, and configure the build by customizing values in the &amp;quot;BUILD&amp;quot; group, &amp;quot;EXTENSIONS&amp;quot; group,  and &amp;quot;USE&amp;quot; group. &lt;br /&gt;
[[File:Cmake-configured-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Generate Makefiles===&lt;br /&gt;
Then, click &amp;quot;Generate&amp;quot; to create build files. When CMake displays its &amp;quot;Generating done&amp;quot; message, your BCI2000 build directory will now contain a Makefile (or a project file for your compiler of chioce), as well as a number of additional CMake-generated files.&lt;br /&gt;
&lt;br /&gt;
[[File:Cmake-done-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
==Compile BCI2000==&lt;br /&gt;
===Open Terminal===&lt;br /&gt;
Open a new terminal window and navigate to your BCI2000 build directory.&lt;br /&gt;
[[File:terminal-bulid-directory-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Build Makefiles===&lt;br /&gt;
Run:&lt;br /&gt;
 make&lt;br /&gt;
from your BCI2000 build directory. Once this is finished your BCI2000 prog directory will contain a number of executables, one for each module, plus a few helper executables. Not everything works the same or, in some cases, at all on non-windows platforms. See, [[Non-Windows Functionality]] for more information.&lt;br /&gt;
[[File:Make-done-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
The build process is now complete. Run &lt;br /&gt;
 make&lt;br /&gt;
again to recompile. Or&lt;br /&gt;
 make &amp;lt;target&amp;gt;&lt;br /&gt;
to recompile only a specific target.&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:Manually_Build_BCI2000_on_Non-Windows_Platforms&amp;diff=9928</id>
		<title>Programming Howto:Manually Build BCI2000 on Non-Windows Platforms</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:Manually_Build_BCI2000_on_Non-Windows_Platforms&amp;diff=9928"/>
		<updated>2022-09-16T00:53:53Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: /* Tell CMake which Qt installation to use */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Installing Dependencies==&lt;br /&gt;
There are three dependencies that need to be installed before you can compile BCI2000:&lt;br /&gt;
*ffmpeg (version 4.4.1, version 5 does not work with BCI2000)&lt;br /&gt;
*portaudio&lt;br /&gt;
*sdl2&lt;br /&gt;
These can be installed using the &lt;br /&gt;
 install_dependencies&lt;br /&gt;
script in the BCI2000 home directory. This will automatically detect your homebrew or it will download a portable version of homebrew in your BCI2000 directory. Then it will install the necessary dependencies. Alternatively, you can manually install them, and they will be automatically detected by CMake. If you have already installed homebrew, this can be done with&lt;br /&gt;
 brew install ffmpeg@4&lt;br /&gt;
 brew link ffmpeg@4&lt;br /&gt;
 brew install portaudio&lt;br /&gt;
 brew install sdl2&lt;br /&gt;
&lt;br /&gt;
==Configure BCI2000 for Compilation==&lt;br /&gt;
&lt;br /&gt;
===Run the CMake GUI===&lt;br /&gt;
Double-click &amp;quot;Configure.sh.cmd&amp;quot; in your BCI2000 build directory.&lt;br /&gt;
&lt;br /&gt;
[[File:Cmake-init-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Tell CMake which Qt installation to use===&lt;br /&gt;
Click &amp;quot;AddEntry&amp;quot; in the CMake window (&amp;lt;i&amp;gt;Note that checking off &amp;quot;Advanced&amp;quot; in Cmake is optional and does not impact the compilation&amp;lt;/i&amp;gt;) and enter the path to a Qt directory. If you installed Qt with homebrew this will be /opt/homebrew/Cellar/qt@5/5.15.5_1/ on apple silicon or /usr/homebrew/Cellar/qt@5/5.15.5_1/ otherwise. Use CMAKE_PREFIX_PATH as the name for the new entry. Be aware that the entry&#039;s name is case sensitive. &amp;lt;b&amp;gt;Currently, on non-windows platform, Qt 5 is the only version that is supported.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Cmake-add-cache-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Perform the configuration step===&lt;br /&gt;
In the CMake window, click &amp;quot;Configure&amp;quot; and choose a generator that is consistent with your compiler. This tutorial will be using Unix Makefiles. Then click &amp;quot;Done&amp;quot; to perform the configuration step. &lt;br /&gt;
[[File:Cmake-generators-non-windows.png|700px]]&lt;br /&gt;
&amp;lt;br&amp;gt;You will see a list of targets scrolling by, and a number of new entries in the variable list at the top of the window, marked in red.&lt;br /&gt;
&lt;br /&gt;
===Choose Build Options===&lt;br /&gt;
Make sure the &amp;quot;Grouped&amp;quot; checkbox is checked, and configure the build by customizing values in the &amp;quot;BUILD&amp;quot; group, &amp;quot;EXTENSIONS&amp;quot; group,  and &amp;quot;USE&amp;quot; group. &lt;br /&gt;
[[File:Cmake-configured-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Generate Makefiles===&lt;br /&gt;
Then, click &amp;quot;Generate&amp;quot; to create build files. When CMake displays its &amp;quot;Generating done&amp;quot; message, your BCI2000 build directory will now contain a Makefile (or a project file for your compiler of chioce), as well as a number of additional CMake-generated files.&lt;br /&gt;
[[File:Cmake-done-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
==Compile BCI2000==&lt;br /&gt;
===Open Terminal===&lt;br /&gt;
Open a new terminal window and navigate to your BCI2000 build directory.&lt;br /&gt;
[[File:terminal-bulid-directory-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Build Makefiles===&lt;br /&gt;
Run:&lt;br /&gt;
 make&lt;br /&gt;
from your BCI2000 build directory. Once this is finished your BCI2000 prog directory will contain a number of executables, one for each module, plus a few helper executables. Not everything works the same or, in some cases, at all on non-windows platforms. See, [[Non-Windows Functionality]] for more information.&lt;br /&gt;
[[File:Make-done-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
The build process is now complete. Run &lt;br /&gt;
 make&lt;br /&gt;
again to recompile. Or&lt;br /&gt;
 make &amp;lt;target&amp;gt;&lt;br /&gt;
to recompile only a specific target.&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:Manually_Build_BCI2000_on_Non-Windows_Platforms&amp;diff=9927</id>
		<title>Programming Howto:Manually Build BCI2000 on Non-Windows Platforms</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:Manually_Build_BCI2000_on_Non-Windows_Platforms&amp;diff=9927"/>
		<updated>2022-09-16T00:52:39Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: /* Run the CMake GUI */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Installing Dependencies==&lt;br /&gt;
There are three dependencies that need to be installed before you can compile BCI2000:&lt;br /&gt;
*ffmpeg (version 4.4.1, version 5 does not work with BCI2000)&lt;br /&gt;
*portaudio&lt;br /&gt;
*sdl2&lt;br /&gt;
These can be installed using the &lt;br /&gt;
 install_dependencies&lt;br /&gt;
script in the BCI2000 home directory. This will automatically detect your homebrew or it will download a portable version of homebrew in your BCI2000 directory. Then it will install the necessary dependencies. Alternatively, you can manually install them, and they will be automatically detected by CMake. If you have already installed homebrew, this can be done with&lt;br /&gt;
 brew install ffmpeg@4&lt;br /&gt;
 brew link ffmpeg@4&lt;br /&gt;
 brew install portaudio&lt;br /&gt;
 brew install sdl2&lt;br /&gt;
&lt;br /&gt;
==Configure BCI2000 for Compilation==&lt;br /&gt;
&lt;br /&gt;
===Run the CMake GUI===&lt;br /&gt;
Double-click &amp;quot;Configure.sh.cmd&amp;quot; in your BCI2000 build directory.&lt;br /&gt;
&lt;br /&gt;
[[File:Cmake-init-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Tell CMake which Qt installation to use===&lt;br /&gt;
Click &amp;quot;AddEntry&amp;quot; in the CMake window (&amp;lt;i&amp;gt;Note that checking off &amp;quot;Advanced&amp;quot; in Cmake is optional and does not impact the compilation&amp;lt;/i&amp;gt;) and enter the path to a Qt directory. If you installed Qt with homebrew this will be /opt/homebrew/Cellar/qt@5/5.15.5_1/ on apple silicon or /usr/homebrew/Cellar/qt@5/5.15.5_1/ otherwise. Use CMAKE_PREFIX_PATH as the name for the new entry. Be aware that the entry&#039;s name is case sensitive. &amp;lt;b&amp;gt;Currently, on non-windows platform, Qt 5 is the only version that is supported.&amp;lt;/b&amp;gt;&lt;br /&gt;
[[File:Cmake-add-cache-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Perform the configuration step===&lt;br /&gt;
In the CMake window, click &amp;quot;Configure&amp;quot; and choose a generator that is consistent with your compiler. This tutorial will be using Unix Makefiles. Then click &amp;quot;Done&amp;quot; to perform the configuration step. &lt;br /&gt;
[[File:Cmake-generators-non-windows.png|700px]]&lt;br /&gt;
&amp;lt;br&amp;gt;You will see a list of targets scrolling by, and a number of new entries in the variable list at the top of the window, marked in red.&lt;br /&gt;
&lt;br /&gt;
===Choose Build Options===&lt;br /&gt;
Make sure the &amp;quot;Grouped&amp;quot; checkbox is checked, and configure the build by customizing values in the &amp;quot;BUILD&amp;quot; group, &amp;quot;EXTENSIONS&amp;quot; group,  and &amp;quot;USE&amp;quot; group. &lt;br /&gt;
[[File:Cmake-configured-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Generate Makefiles===&lt;br /&gt;
Then, click &amp;quot;Generate&amp;quot; to create build files. When CMake displays its &amp;quot;Generating done&amp;quot; message, your BCI2000 build directory will now contain a Makefile (or a project file for your compiler of chioce), as well as a number of additional CMake-generated files.&lt;br /&gt;
[[File:Cmake-done-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
==Compile BCI2000==&lt;br /&gt;
===Open Terminal===&lt;br /&gt;
Open a new terminal window and navigate to your BCI2000 build directory.&lt;br /&gt;
[[File:terminal-bulid-directory-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Build Makefiles===&lt;br /&gt;
Run:&lt;br /&gt;
 make&lt;br /&gt;
from your BCI2000 build directory. Once this is finished your BCI2000 prog directory will contain a number of executables, one for each module, plus a few helper executables. Not everything works the same or, in some cases, at all on non-windows platforms. See, [[Non-Windows Functionality]] for more information.&lt;br /&gt;
[[File:Make-done-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
The build process is now complete. Run &lt;br /&gt;
 make&lt;br /&gt;
again to recompile. Or&lt;br /&gt;
 make &amp;lt;target&amp;gt;&lt;br /&gt;
to recompile only a specific target.&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:Automatically_Build_BCI2000_on_Non-Windows_Platforms&amp;diff=9926</id>
		<title>Programming Howto:Automatically Build BCI2000 on Non-Windows Platforms</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:Automatically_Build_BCI2000_on_Non-Windows_Platforms&amp;diff=9926"/>
		<updated>2022-09-16T00:51:38Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=[[Programming Howto:Building_and_Customizing_BCI2000_on_Non-Windows_Platforms|Back]]=&lt;br /&gt;
[[Programming Howto:Building_and_Customizing_BCI2000_on_Non-Windows_Platforms|to the overview page]]&lt;br /&gt;
=Navigate to BCI2000 Directory=&lt;br /&gt;
Navigate to the BCI2000 &amp;quot;trunk&amp;quot; directory in a finder window.&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:Trunk-directory-non-windows.png|700px]]&lt;br /&gt;
=Run Install Script=&lt;br /&gt;
Double click on the script named &amp;quot;install.&amp;quot; It will begin the installation process in a new terminal window. First, it will prompt you for your Qt installation directory. If you installed Qt with homebrew this will be /opt/homebrew/Cellar/qt@5/5.15.5_1/ on apple silicon or /usr/homebrew/Cellar/qt@5/5.15.5_1/ otherwise. Drag this folder onto the window and press Enter. After you press Enter, the installation will continue without any additional user input.&lt;br /&gt;
[[File:Automatic-compile-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
Once this script finishes running, your BCI2000 will be built!&lt;br /&gt;
&lt;br /&gt;
[[File:Screen Shot 2022-08-12 at 3.55.18 PM.png|700px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
And the &amp;quot;prog&amp;quot; directory in your BCI2000 trunk will have been populated with executables.&lt;br /&gt;
&lt;br /&gt;
[[File:Prog-folder-non-windows.png|700px]]&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:_Install_Prerequisites_on_Non-Windows_Platforms&amp;diff=9925</id>
		<title>Programming Howto: Install Prerequisites on Non-Windows Platforms</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:_Install_Prerequisites_on_Non-Windows_Platforms&amp;diff=9925"/>
		<updated>2022-09-16T00:47:00Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: /* Next */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=[[Programming Howto:Building_and_Customizing_BCI2000_on_Non-Windows_Platforms|Back]]=&lt;br /&gt;
[[Programming Howto:Building_and_Customizing_BCI2000_on_Non-Windows_Platforms|to the overview page]]&lt;br /&gt;
&lt;br /&gt;
=Homebrew=&lt;br /&gt;
[https://brew.sh Homebrew] is a package manager for mac and linux that we will be using to install several items. You may also use another package manager if you have one that you prefer. Install it with&lt;br /&gt;
 /bin/bash -c &amp;quot;$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)&amp;quot;&lt;br /&gt;
Now check to make sure that it was installed correctly with&lt;br /&gt;
 brew --version&lt;br /&gt;
&lt;br /&gt;
=SVN=&lt;br /&gt;
SVN is used to checkout the source code repository. Install it with&lt;br /&gt;
 brew install Subversion&lt;br /&gt;
Now check to make sure that it was installed correctly with&lt;br /&gt;
 svn --version&lt;br /&gt;
&lt;br /&gt;
=Qt5=&lt;br /&gt;
Qt is used to render to BCI2000 windows. &amp;lt;b&amp;gt;Qt version 5 is the only version that is supported on Non-Windows Platforms.&amp;lt;/b&amp;gt; Install it with&lt;br /&gt;
 brew install qt@5&lt;br /&gt;
Now check to make sure that it was installed correctly with&lt;br /&gt;
 brew list qt5&lt;br /&gt;
If it is installed correctly, it will list the places where it has files. If it is not installed, it will give an error.&lt;br /&gt;
&lt;br /&gt;
=CMake=&lt;br /&gt;
CMake is used to customize BCI2000 builds. Install it with&lt;br /&gt;
 brew install cmake&lt;br /&gt;
Now check to make sure that it was install correctly with&lt;br /&gt;
 cmake --version&lt;br /&gt;
&lt;br /&gt;
=[[Programming_Howto:Register_with_BCI2000_Project|Next]]=&lt;br /&gt;
[[Programming_Howto:Register_with_BCI2000_Project|Register with BCI2000]]&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:_Install_Prerequisites_on_Non-Windows_Platforms&amp;diff=9924</id>
		<title>Programming Howto: Install Prerequisites on Non-Windows Platforms</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:_Install_Prerequisites_on_Non-Windows_Platforms&amp;diff=9924"/>
		<updated>2022-09-16T00:46:25Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: /* Homebrew */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=[[Programming Howto:Building_and_Customizing_BCI2000_on_Non-Windows_Platforms|Back]]=&lt;br /&gt;
[[Programming Howto:Building_and_Customizing_BCI2000_on_Non-Windows_Platforms|to the overview page]]&lt;br /&gt;
&lt;br /&gt;
=Homebrew=&lt;br /&gt;
[https://brew.sh Homebrew] is a package manager for mac and linux that we will be using to install several items. You may also use another package manager if you have one that you prefer. Install it with&lt;br /&gt;
 /bin/bash -c &amp;quot;$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)&amp;quot;&lt;br /&gt;
Now check to make sure that it was installed correctly with&lt;br /&gt;
 brew --version&lt;br /&gt;
&lt;br /&gt;
=SVN=&lt;br /&gt;
SVN is used to checkout the source code repository. Install it with&lt;br /&gt;
 brew install Subversion&lt;br /&gt;
Now check to make sure that it was installed correctly with&lt;br /&gt;
 svn --version&lt;br /&gt;
&lt;br /&gt;
=Qt5=&lt;br /&gt;
Qt is used to render to BCI2000 windows. &amp;lt;b&amp;gt;Qt version 5 is the only version that is supported on Non-Windows Platforms.&amp;lt;/b&amp;gt; Install it with&lt;br /&gt;
 brew install qt@5&lt;br /&gt;
Now check to make sure that it was installed correctly with&lt;br /&gt;
 brew list qt5&lt;br /&gt;
If it is installed correctly, it will list the places where it has files. If it is not installed, it will give an error.&lt;br /&gt;
&lt;br /&gt;
=CMake=&lt;br /&gt;
CMake is used to customize BCI2000 builds. Install it with&lt;br /&gt;
 brew install cmake&lt;br /&gt;
Now check to make sure that it was install correctly with&lt;br /&gt;
 cmake --version&lt;br /&gt;
&lt;br /&gt;
=[[Programming_Howto:Register_with_BCI2000_Project|Next]]=&lt;br /&gt;
[[Programming_Howto:Register_with_BCI2000_Project|Install Dependencies]]&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:_Install_Prerequisites_on_Non-Windows_Platforms&amp;diff=9923</id>
		<title>Programming Howto: Install Prerequisites on Non-Windows Platforms</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:_Install_Prerequisites_on_Non-Windows_Platforms&amp;diff=9923"/>
		<updated>2022-09-16T00:45:09Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: /* Qt5 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=[[Programming Howto:Building_and_Customizing_BCI2000_on_Non-Windows_Platforms|Back]]=&lt;br /&gt;
[[Programming Howto:Building_and_Customizing_BCI2000_on_Non-Windows_Platforms|to the overview page]]&lt;br /&gt;
&lt;br /&gt;
=Homebrew=&lt;br /&gt;
[https://brew.sh|Homebrew] is a package manager for mac and linux that we will be using to install several items. You may also use another package manager if you have one that you prefer. Install it with&lt;br /&gt;
 /bin/bash -c &amp;quot;$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)&amp;quot;&lt;br /&gt;
Now check to make sure that it was installed correctly with&lt;br /&gt;
 brew --version&lt;br /&gt;
&lt;br /&gt;
=SVN=&lt;br /&gt;
SVN is used to checkout the source code repository. Install it with&lt;br /&gt;
 brew install Subversion&lt;br /&gt;
Now check to make sure that it was installed correctly with&lt;br /&gt;
 svn --version&lt;br /&gt;
&lt;br /&gt;
=Qt5=&lt;br /&gt;
Qt is used to render to BCI2000 windows. &amp;lt;b&amp;gt;Qt version 5 is the only version that is supported on Non-Windows Platforms.&amp;lt;/b&amp;gt; Install it with&lt;br /&gt;
 brew install qt@5&lt;br /&gt;
Now check to make sure that it was installed correctly with&lt;br /&gt;
 brew list qt5&lt;br /&gt;
If it is installed correctly, it will list the places where it has files. If it is not installed, it will give an error.&lt;br /&gt;
&lt;br /&gt;
=CMake=&lt;br /&gt;
CMake is used to customize BCI2000 builds. Install it with&lt;br /&gt;
 brew install cmake&lt;br /&gt;
Now check to make sure that it was install correctly with&lt;br /&gt;
 cmake --version&lt;br /&gt;
&lt;br /&gt;
=[[Programming_Howto:Register_with_BCI2000_Project|Next]]=&lt;br /&gt;
[[Programming_Howto:Register_with_BCI2000_Project|Install Dependencies]]&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=Main_Page&amp;diff=9902</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=Main_Page&amp;diff=9902"/>
		<updated>2022-08-15T14:04:17Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__ __NOEDITSECTION__&lt;br /&gt;
&amp;lt;table cellspacing=&amp;quot;10&amp;quot; class=&amp;quot;noprint&amp;quot; style=&amp;quot;width:100%;margin-top:-2em;margin-bottom:0&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;border:1px solid #dfdfdf;background-color:#efefef;padding-left:1em;word-spacing:1em&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;htmltag tagname=&amp;quot;form&amp;quot; name=&amp;quot;sitesearch&amp;quot; action=&amp;quot;https://www.google.com/search&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;htmltag tagname=&amp;quot;input&amp;quot; name=&amp;quot;q&amp;quot; type=&amp;quot;text&amp;quot; size=&amp;quot;40&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;htmltag tagname=&amp;quot;input&amp;quot; type=&amp;quot;submit&amp;quot; value=&amp;quot;Google site search of bci2000.org&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;htmltag tagname=&amp;quot;input&amp;quot; type=&amp;quot;hidden&amp;quot; name=&amp;quot;sitesearch&amp;quot; value=&amp;quot;bci2000.org&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;htmltag tagname=&amp;quot;input&amp;quot; type=&amp;quot;hidden&amp;quot; name=&amp;quot;ie&amp;quot; value=&amp;quot;utf-8&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;htmltag tagname=&amp;quot;input&amp;quot; type=&amp;quot;hidden&amp;quot; name=&amp;quot;oe&amp;quot; value=&amp;quot;utf-8&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;/htmltag&amp;gt;&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;table cellspacing=&amp;quot;10&amp;quot; style=&amp;quot;width:100%;margin-top:-10px&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt; &amp;lt;td style=&amp;quot;margin:0; margin-top:10px; margin-right:10px; border:1px solid #dfdfdf; padding:0 1em 1em 1em; background-color:#e0f2ff; align:right;vertical-align:top;&amp;quot;&amp;gt;&lt;br /&gt;
=&amp;lt;b&amp;gt;What is BCI2000?&amp;lt;/b&amp;gt;=&lt;br /&gt;
BCI2000 is a general-purpose software system for brain-computer interface (BCI) research.&lt;br /&gt;
BCI2000 includes software tools that can acquire and process data, present stimuli and feedback, and manage interaction with outside devices such as robotic arms. BCI2000 is a real-time system that can synchronize EEG and other signals with a wide variety of biosignals and input devices such as mice or eye-trackers. It has several modules to manage data importing and exporting in common file formats. BCI2000 operates on most Windows systems, and the source code can be compiled on most Windows machines. &lt;br /&gt;
&amp;lt;/td&amp;gt; &amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;table cellspacing=&amp;quot;10&amp;quot; style=&amp;quot;width:100%;margin-top:-10px&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;margin:0; margin-top:10px; margin-right:10px; border:1px solid #dfdfdf; padding:0 1em 1em 1em; background-color:#cef0ea; align:right;vertical-align:top;&amp;quot;&amp;gt;&lt;br /&gt;
==BCI2000 for Users==&lt;br /&gt;
&lt;br /&gt;
* [//{{SERVERNAME}}/useradmin Create or modify a User Account]&lt;br /&gt;
* [[DownloadBCI2000|Download BCI2000]]&lt;br /&gt;
* Take the introductory [[User Tutorial:BCI2000 Tour|BCI2000 Tour]]&lt;br /&gt;
* Learn more through an &amp;lt;br /&amp;gt; [[Introduction_to_Adaptive_Neurotechnologies|Introduction to Adaptive Neurotechnologies]]&lt;br /&gt;
* Review the terminology in the [[BCI2000 Glossary]]&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;margin:0; margin-top:10px; margin-right:10px; border:1px solid #dfdfdf; padding:0 1em 1em 1em; background-color:#fbefcc; align:right;vertical-align:top;&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==BCI2000 for Developers==&lt;br /&gt;
* [//{{SERVERNAME}}/useradmin Create or modify a User Account]&lt;br /&gt;
* Download [[BCI2000 Binaries]]&lt;br /&gt;
* Download, build, and customize the BCI2000 toolchain for windows using&amp;lt;br /&amp;gt; [[Programming_Howto:Building and Customizing BCI2000|Building and Customizing Howto]]&lt;br /&gt;
* Download, build, and customize the BCI2000 toolchain for non-windows platforms using&amp;lt;br /&amp;gt;[[ Programming_Howto:Non:Building_and_Customizing_BCI2000_on_Non-Windows_Platforms|Building and Customizing Howto for Non-Windows]]&lt;br /&gt;
* Access to the [[Programming Howto:Building and Customizing BCI2000|BCI2000 Source Code]]&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;margin:0; margin-top:10px; margin-right:10px; border:1px solid #dfdfdf; padding:0 1em 1em 1em; background-color:#f7dfea; align:right;vertical-align:top;&amp;quot;&amp;gt;&lt;br /&gt;
==BCI2000 References==&lt;br /&gt;
===BCI2000 Overview and Tools===&lt;br /&gt;
* The [[User Reference:Contents|User Reference Manual]] describes all details&amp;lt;br /&amp;gt;of system configuration and usage&lt;br /&gt;
===Technical References===&lt;br /&gt;
* The [[Technical Reference:Contents|Technical Reference Manual]] contains a discussion of its &amp;lt;br /&amp;gt;basic concepts, and a detailed specification of the BCI2000 standard.&lt;br /&gt;
===Programming References===&lt;br /&gt;
* The [[Programming Reference:Contents|Programming Reference]] provides background information &amp;lt;br /&amp;gt;which you need in order to understand, modify, or create code that &amp;lt;br /&amp;gt;depends on the BCI2000 framework.&lt;br /&gt;
===Contributions===&lt;br /&gt;
* [[Contributions:Contents|User-Contributed BCI2000 Components and Patches]]&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;margin:0; margin-top:10px; margin-right:10px; border:1px solid #dfdfdf; padding:0 1em 1em 1em; background-color:#F9DED7; align:right;vertical-align:top;&amp;quot;&amp;gt;&lt;br /&gt;
==BCI2000 Tutorials==&lt;br /&gt;
===Setup Tutorials===&lt;br /&gt;
*[[Programming Howto:Install Prerequisites|Install Prerequisites]]&lt;br /&gt;
*[[Programming Howto:Register with BCI2000 Project|Register with the BCI2000 Project]]&lt;br /&gt;
*[[Programming Howto:Download the BCI2000 Sourcecode|Download the BCI2000 Sourcecode]]&lt;br /&gt;
*[[Programming Howto:Configure BCI2000 for Compilation|Configure BCI2000 for Compilation]]&lt;br /&gt;
*[[Programming Howto:Compile BCI2000|Compile BCI2000]]&lt;br /&gt;
===Experimental Tutorials===&lt;br /&gt;
*[[User Tutorial:Mu Rhythm BCI Tutorial|Mu Rhythm BCI Tutorial]]&lt;br /&gt;
*[[User Tutorial:P300 BCI Tutorial|P300 BCI Tutorial]]&lt;br /&gt;
===Programming Tutorials===&lt;br /&gt;
*[[Programming Tutorial:Implementing a Source Module|Implementing a Source Module]]&lt;br /&gt;
*[[Programming Tutorial:Implementing a Signal Processing Filter|Implementing a Signal Processing Filter]]&lt;br /&gt;
*[[Programming Tutorial:Implementing a Matlab-based Filter|Implementing a Matlab-based Filter]]&lt;br /&gt;
*[[Programming Tutorial:Implementing an Input Logger|Implementing an Input Logger]]&lt;br /&gt;
===Data Analysis Tutorials===&lt;br /&gt;
*[[User Tutorial:Data Analysis|Data Analysis with BCI2000]]&lt;br /&gt;
* Converting and Analyzing BCI2000 Data with  [[User Reference:Matlab MEX Files|Matlab MEX Files]]&lt;br /&gt;
* Analyze BCI2000 Data in Python with [https://github.com/neurotechcenter/BCI2kReader BCI2k Reader]&lt;br /&gt;
===All Tutorials:See a complete list of [[User Tutorial|BCI2000 tutorials]] here===&lt;br /&gt;
* &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;td style=&amp;quot;margin:0; margin-right:10px; border:1px solid #dfdfdf; padding:0 1em 1em 1em; background-color:#e8eaff; align:right;vertical-align:top;&amp;quot;&amp;gt;&lt;br /&gt;
==Supported Frameworks==&lt;br /&gt;
* BCI2000 Remote - includes Matlab, C++, and Python &lt;br /&gt;
** [[Technical Reference:BCI2000Remote Library]]&lt;br /&gt;
** [[Programming Reference:BCI2000Remote Class]]&lt;br /&gt;
** [[User Tutorial:BCI2000Remote]]&lt;br /&gt;
* [[PsychoPy]]&lt;br /&gt;
* [[BCPy2000]]&lt;br /&gt;
** [[User Tutorial:BCPy2000]]&lt;br /&gt;
** [[Contributions:BCPy2000]]&lt;br /&gt;
* BCI2000 Core Frameworks&lt;br /&gt;
** [[User Reference:P3SpellerTask|P3 Speller]]&lt;br /&gt;
** [[User Reference:StimulusPresentationTask|Stimulus Presentation]] &lt;br /&gt;
** [[User Reference:CursorTask|Cursor Task]]&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;td style=&amp;quot;margin:0; margin-top:10px; margin-right:10px; border:1px solid #dfdfdf; padding:0 1em 1em 1em; background-color:#d2f0f7; align:right;vertical-align:top;&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Additional Information==&lt;br /&gt;
* [[System Features|Features supported by BCI2000]]&lt;br /&gt;
* [https://github.com/neurotechcenter NCAN Github]&lt;br /&gt;
* [//{{SERVERNAME}}/phpbb BCI2000 Community Forum]&lt;br /&gt;
* [//{{SERVERNAME}}/tracproj/newticket Submit a Bug Report]  (make sure you log in)&lt;br /&gt;
* [[User FAQ|BCI2000 Frequently Asked Questions]]&lt;br /&gt;
* [[BCI2000 Glossary]]&amp;lt;br /&amp;gt;of terms specific to BCI2000&lt;br /&gt;
* [[BCI2000 Licensing|Licensing Information]]&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table cellspacing=&amp;quot;10&amp;quot; style=&amp;quot;width:100%;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
&amp;lt;td style=&amp;quot;margin:0; margin-top:10px; margin-right:10px; border:1px solid #dfdfdf; padding:0 1em 1em 1em; background-color:white; align:right;vertical-align:top;&amp;quot;&amp;gt;&lt;br /&gt;
==BCI2000 Publications==&lt;br /&gt;
* [http://{{SERVERNAME}}/downloads/doc/paper.pdf G. Schalk, D.J. McFarland, T. Hinterberger, N. Birbaumer, and J.R. Wolpaw: &#039;&#039;BCI2000: A General-Purpose Brain-Computer Interface (BCI) System&#039;&#039;, IEEE Trans Biomed Eng, 51(6), June 2004.]&lt;br /&gt;
* J. Mellinger, G. Schalk: &#039;&#039;BCI2000: A General-Purpose Software Platform for BCI Research,&#039;&#039; In: G. Dornhege, J. del R. Millán, T. Hinterberger, D.J. McFarland, K.-R. Müller (eds.), &#039;&#039;Toward Brain-Computer Interfacing,&#039;&#039; MIT Press, 2007.&lt;br /&gt;
* [http://www.amazon.com/Practical-Guide-BrainComputer-Interfacing-BCI2000/dp/1849960917/ G. Schalk, J. Mellinger: &amp;quot;A Practical Guide to Brain-Computer Interfacing with BCI2000&amp;quot;, Springer, 2010.]&lt;br /&gt;
* J. Mellinger, G. Schalk: &amp;quot;Using BCI2000 in BCI Research,&amp;quot; In: B. Graimann, B. Allison, G. Pfurtscheller (eds.), &amp;quot;Brain-Computer Interfaces: Revolutionizing Human-Computer Interaction&amp;quot;, Springer, 2010.&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:Manually_Build_BCI2000_on_Non-Windows_Platforms&amp;diff=9901</id>
		<title>Programming Howto:Manually Build BCI2000 on Non-Windows Platforms</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:Manually_Build_BCI2000_on_Non-Windows_Platforms&amp;diff=9901"/>
		<updated>2022-08-15T14:00:45Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: /* Installing Dependencies */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Installing Dependencies==&lt;br /&gt;
There are three dependencies that need to be installed before you can compile BCI2000:&lt;br /&gt;
*ffmpeg (version 4.4.1, version 5 does not work with BCI2000)&lt;br /&gt;
*portaudio&lt;br /&gt;
*sdl2&lt;br /&gt;
These can be installed using the &lt;br /&gt;
 install_dependencies&lt;br /&gt;
script in the BCI2000 home directory. This will automatically detect your homebrew or it will download a portable version of homebrew in your BCI2000 directory. Then it will install the necessary dependencies. Alternatively, you can manually install them, and they will be automatically detected by CMake. If you have already installed homebrew, this can be done with&lt;br /&gt;
 brew install ffmpeg@4&lt;br /&gt;
 brew link ffmpeg@4&lt;br /&gt;
 brew install portaudio&lt;br /&gt;
 brew install sdl2&lt;br /&gt;
&lt;br /&gt;
==Configure BCI2000 for Compilation==&lt;br /&gt;
&lt;br /&gt;
===Run the CMake GUI===&lt;br /&gt;
Double-click &amp;quot;Configure.sh.cmd&amp;quot; in your BCI2000 build directory.&lt;br /&gt;
[[File:Cmake-init-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Tell CMake which Qt installation to use===&lt;br /&gt;
Click &amp;quot;AddEntry&amp;quot; in the CMake window (&amp;lt;i&amp;gt;Note that checking off &amp;quot;Advanced&amp;quot; in Cmake is optional and does not impact the compilation&amp;lt;/i&amp;gt;) and enter the path to a Qt directory. If you installed Qt with homebrew this will be /opt/homebrew/Cellar/qt@5/5.15.5_1/ on apple silicon or /usr/homebrew/Cellar/qt@5/5.15.5_1/ otherwise. Use CMAKE_PREFIX_PATH as the name for the new entry. Be aware that the entry&#039;s name is case sensitive. &amp;lt;b&amp;gt;Currently, on non-windows platform, Qt 5 is the only version that is supported.&amp;lt;/b&amp;gt;&lt;br /&gt;
[[File:Cmake-add-cache-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Perform the configuration step===&lt;br /&gt;
In the CMake window, click &amp;quot;Configure&amp;quot; and choose a generator that is consistent with your compiler. This tutorial will be using Unix Makefiles. Then click &amp;quot;Done&amp;quot; to perform the configuration step. &lt;br /&gt;
[[File:Cmake-generators-non-windows.png|700px]]&lt;br /&gt;
&amp;lt;br&amp;gt;You will see a list of targets scrolling by, and a number of new entries in the variable list at the top of the window, marked in red.&lt;br /&gt;
&lt;br /&gt;
===Choose Build Options===&lt;br /&gt;
Make sure the &amp;quot;Grouped&amp;quot; checkbox is checked, and configure the build by customizing values in the &amp;quot;BUILD&amp;quot; group, &amp;quot;EXTENSIONS&amp;quot; group,  and &amp;quot;USE&amp;quot; group. &lt;br /&gt;
[[File:Cmake-configured-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Generate Makefiles===&lt;br /&gt;
Then, click &amp;quot;Generate&amp;quot; to create build files. When CMake displays its &amp;quot;Generating done&amp;quot; message, your BCI2000 build directory will now contain a Makefile (or a project file for your compiler of chioce), as well as a number of additional CMake-generated files.&lt;br /&gt;
[[File:Cmake-done-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
==Compile BCI2000==&lt;br /&gt;
===Open Terminal===&lt;br /&gt;
Open a new terminal window and navigate to your BCI2000 build directory.&lt;br /&gt;
[[File:terminal-bulid-directory-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Build Makefiles===&lt;br /&gt;
Run:&lt;br /&gt;
 make&lt;br /&gt;
from your BCI2000 build directory. Once this is finished your BCI2000 prog directory will contain a number of executables, one for each module, plus a few helper executables. Not everything works the same or, in some cases, at all on non-windows platforms. See, [[Non-Windows Functionality]] for more information.&lt;br /&gt;
[[File:Make-done-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
The build process is now complete. Run &lt;br /&gt;
 make&lt;br /&gt;
again to recompile. Or&lt;br /&gt;
 make &amp;lt;target&amp;gt;&lt;br /&gt;
to recompile only a specific target.&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:Manually_Build_BCI2000_on_Non-Windows_Platforms&amp;diff=9900</id>
		<title>Programming Howto:Manually Build BCI2000 on Non-Windows Platforms</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:Manually_Build_BCI2000_on_Non-Windows_Platforms&amp;diff=9900"/>
		<updated>2022-08-15T13:59:24Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: Created page with &amp;quot;==Installing Dependencies== There are three dependencies that need to be installed before you can compile BCI2000: *ffmpeg (version 4.4.1, version 5 does not work with BCI2000...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Installing Dependencies==&lt;br /&gt;
There are three dependencies that need to be installed before you can compile BCI2000:&lt;br /&gt;
*ffmpeg (version 4.4.1, version 5 does not work with BCI2000)&lt;br /&gt;
*portaudio&lt;br /&gt;
*sdl2&lt;br /&gt;
These can be installed using the &lt;br /&gt;
 install_dependencies&lt;br /&gt;
script in the BCI2000 home directory. This will automatically detect your homebrew or it will download a portable version of homebrew in your BCI2000 directory. Then it will install the necessary dependencies. Alternatively, you can manually install them, and they will be automatically detected by CMake. With homebrew, this can be done with&lt;br /&gt;
 brew install ffmpeg@4&lt;br /&gt;
 brew link ffmpeg@4&lt;br /&gt;
 brew install portaudio&lt;br /&gt;
 brew install sdl2&lt;br /&gt;
&lt;br /&gt;
==Configure BCI2000 for Compilation==&lt;br /&gt;
&lt;br /&gt;
===Run the CMake GUI===&lt;br /&gt;
Double-click &amp;quot;Configure.sh.cmd&amp;quot; in your BCI2000 build directory.&lt;br /&gt;
[[File:Cmake-init-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Tell CMake which Qt installation to use===&lt;br /&gt;
Click &amp;quot;AddEntry&amp;quot; in the CMake window (&amp;lt;i&amp;gt;Note that checking off &amp;quot;Advanced&amp;quot; in Cmake is optional and does not impact the compilation&amp;lt;/i&amp;gt;) and enter the path to a Qt directory. If you installed Qt with homebrew this will be /opt/homebrew/Cellar/qt@5/5.15.5_1/ on apple silicon or /usr/homebrew/Cellar/qt@5/5.15.5_1/ otherwise. Use CMAKE_PREFIX_PATH as the name for the new entry. Be aware that the entry&#039;s name is case sensitive. &amp;lt;b&amp;gt;Currently, on non-windows platform, Qt 5 is the only version that is supported.&amp;lt;/b&amp;gt;&lt;br /&gt;
[[File:Cmake-add-cache-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Perform the configuration step===&lt;br /&gt;
In the CMake window, click &amp;quot;Configure&amp;quot; and choose a generator that is consistent with your compiler. This tutorial will be using Unix Makefiles. Then click &amp;quot;Done&amp;quot; to perform the configuration step. &lt;br /&gt;
[[File:Cmake-generators-non-windows.png|700px]]&lt;br /&gt;
&amp;lt;br&amp;gt;You will see a list of targets scrolling by, and a number of new entries in the variable list at the top of the window, marked in red.&lt;br /&gt;
&lt;br /&gt;
===Choose Build Options===&lt;br /&gt;
Make sure the &amp;quot;Grouped&amp;quot; checkbox is checked, and configure the build by customizing values in the &amp;quot;BUILD&amp;quot; group, &amp;quot;EXTENSIONS&amp;quot; group,  and &amp;quot;USE&amp;quot; group. &lt;br /&gt;
[[File:Cmake-configured-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Generate Makefiles===&lt;br /&gt;
Then, click &amp;quot;Generate&amp;quot; to create build files. When CMake displays its &amp;quot;Generating done&amp;quot; message, your BCI2000 build directory will now contain a Makefile (or a project file for your compiler of chioce), as well as a number of additional CMake-generated files.&lt;br /&gt;
[[File:Cmake-done-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
==Compile BCI2000==&lt;br /&gt;
===Open Terminal===&lt;br /&gt;
Open a new terminal window and navigate to your BCI2000 build directory.&lt;br /&gt;
[[File:terminal-bulid-directory-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
===Build Makefiles===&lt;br /&gt;
Run:&lt;br /&gt;
 make&lt;br /&gt;
from your BCI2000 build directory. Once this is finished your BCI2000 prog directory will contain a number of executables, one for each module, plus a few helper executables. Not everything works the same or, in some cases, at all on non-windows platforms. See, [[Non-Windows Functionality]] for more information.&lt;br /&gt;
[[File:Make-done-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
The build process is now complete. Run &lt;br /&gt;
 make&lt;br /&gt;
again to recompile. Or&lt;br /&gt;
 make &amp;lt;target&amp;gt;&lt;br /&gt;
to recompile only a specific target.&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=File:Terminal-bulid-directory-non-windows.png&amp;diff=9899</id>
		<title>File:Terminal-bulid-directory-non-windows.png</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=File:Terminal-bulid-directory-non-windows.png&amp;diff=9899"/>
		<updated>2022-08-15T13:56:47Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=File:Make-done-non-windows.png&amp;diff=9898</id>
		<title>File:Make-done-non-windows.png</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=File:Make-done-non-windows.png&amp;diff=9898"/>
		<updated>2022-08-15T13:53:23Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=File:Cmake-done-non-windows.png&amp;diff=9897</id>
		<title>File:Cmake-done-non-windows.png</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=File:Cmake-done-non-windows.png&amp;diff=9897"/>
		<updated>2022-08-12T21:27:21Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=File:Cmake-configured-non-windows.png&amp;diff=9896</id>
		<title>File:Cmake-configured-non-windows.png</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=File:Cmake-configured-non-windows.png&amp;diff=9896"/>
		<updated>2022-08-12T21:26:45Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=File:Cmake-generators-non-windows.png&amp;diff=9895</id>
		<title>File:Cmake-generators-non-windows.png</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=File:Cmake-generators-non-windows.png&amp;diff=9895"/>
		<updated>2022-08-12T21:25:59Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=File:Cmake-add-cache-non-windows.png&amp;diff=9894</id>
		<title>File:Cmake-add-cache-non-windows.png</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=File:Cmake-add-cache-non-windows.png&amp;diff=9894"/>
		<updated>2022-08-12T21:25:23Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=File:Cmake-init-non-windows.png&amp;diff=9893</id>
		<title>File:Cmake-init-non-windows.png</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=File:Cmake-init-non-windows.png&amp;diff=9893"/>
		<updated>2022-08-12T21:24:56Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:Download_the_BCI2000_Sourcecode_on_Non-Windows_Platforms&amp;diff=9892</id>
		<title>Programming Howto:Download the BCI2000 Sourcecode on Non-Windows Platforms</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:Download_the_BCI2000_Sourcecode_on_Non-Windows_Platforms&amp;diff=9892"/>
		<updated>2022-08-12T21:08:24Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=[[Programming Howto:Building_and_Customizing_BCI2000_on_Non-Windows_Platforms|Back]]=&lt;br /&gt;
[[Programming Howto:Building_and_Customizing_BCI2000_on_Non-Windows_Platforms|to the overview page]]&lt;br /&gt;
=Open Terminal=&lt;br /&gt;
First open a terminal application and navigate to the location you want your source code to be located at. For example, a folder named BCI2000 in the users home directory. &lt;br /&gt;
[[File:Navigate-to-bci2000-directory-mac.png|700px]]&lt;br /&gt;
=Checkout SVN Repository=&lt;br /&gt;
Now, checkout the BCI2000 source code with svn. You will be prompted for your computer&#039;s password and your username and password for the BCI2000 project that you created in the last step.&lt;br /&gt;
 svn checkout https://bci2000.org/svn/trunk&lt;br /&gt;
[[File:Svn-checkout-non-windows.png|700px]]&lt;br /&gt;
&amp;lt;br/&amp;gt;You will now have a new folder, named trunk, in that directory. Inside of &amp;quot;trunk&amp;quot; will be the source code for BCI2000.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:Trunk-directory-non-windows.png|700px]]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
=Next=&lt;br /&gt;
[[Programming Howto:Automatically Build BCI2000 on Non-Windows Platforms|Automatically Build BCI2000]] OR [[Programming Howto:Manually Build BCI2000 on Non-Windows Platforms|Manually Build BCI2000]]&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:Building_and_Customizing_BCI2000_on_Non-Windows_Platforms&amp;diff=9891</id>
		<title>Programming Howto:Building and Customizing BCI2000 on Non-Windows Platforms</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:Building_and_Customizing_BCI2000_on_Non-Windows_Platforms&amp;diff=9891"/>
		<updated>2022-08-12T21:05:35Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: Created page with &amp;quot;This tutorial will walk you through the process of obtaining the BCI2000 source distribution and building BCI2000.  =How To Steps= *Programming Howto: Install Prerequisites...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This tutorial will walk you through the process of obtaining the BCI2000 source distribution and building BCI2000.&lt;br /&gt;
&lt;br /&gt;
=How To Steps=&lt;br /&gt;
*[[Programming Howto: Install Prerequisites on Non-Windows Platforms|Install Prerequisites]]&lt;br /&gt;
*[[Programming Howto:Register with BCI2000 Project|Register with the BCI2000 Project]]&lt;br /&gt;
*[[Programming Howto:Download the BCI2000 Sourcecode on Non-Windows Platforms|Download the BCI2000 Sourcecode]]&lt;br /&gt;
*[[Programming Howto:Automatically Build BCI2000 on Non-Windows Platforms|Automatically Build BCI2000]] &amp;lt;b&amp;gt;OR&amp;lt;/b&amp;gt; [[Programming Howto:Manually Build BCI2000 on Non-Windows Platforms|Manually Build BCI2000]]&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:Automatically_Build_BCI2000_on_Non-Windows_Platforms&amp;diff=9890</id>
		<title>Programming Howto:Automatically Build BCI2000 on Non-Windows Platforms</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:Automatically_Build_BCI2000_on_Non-Windows_Platforms&amp;diff=9890"/>
		<updated>2022-08-12T21:04:44Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: Created page with &amp;quot;=Back= Programming Howto:Building_and_Customizing_BCI2000_on_Non-Windows_Platforms|to the ove...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=[[Programming Howto:Building_and_Customizing_BCI2000_on_Non-Windows_Platforms|Back]]=&lt;br /&gt;
[[Programming Howto:Building_and_Customizing_BCI2000_on_Non-Windows_Platforms|to the overview page]]&lt;br /&gt;
=Navigate to BCI2000 Directory=&lt;br /&gt;
Navigate to the BCI2000 &amp;quot;trunk&amp;quot; directory in a finder window.&lt;br /&gt;
[[File:Trunk-directory-non-windows.png|700px]]&lt;br /&gt;
=Run Install Script=&lt;br /&gt;
Double click on the script named &amp;quot;install.&amp;quot; It will begin the installation process in a new terminal window. First, it will prompt you for your Qt installation directory. If you installed Qt with homebrew this will be /opt/homebrew/Cellar/qt@5/5.15.5_1/ on apple silicon or /usr/homebrew/Cellar/qt@5/5.15.5_1/ otherwise. Drag this folder onto the window and press Enter. After you press Enter, the installation will continue without any additional user input.&lt;br /&gt;
[[File:Automatic-compile-non-windows.png|700px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Once this script finishes running, your BCI2000 will be built!&lt;br /&gt;
[[File:Screen Shot 2022-08-12 at 3.55.18 PM.png|700px]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
And the &amp;quot;prog&amp;quot; directory in your BCI2000 trunk will have been populated with executables.&lt;br /&gt;
[[File:Prog-folder-non-windows.png|700px]]&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=File:Prog-folder-non-windows.png&amp;diff=9889</id>
		<title>File:Prog-folder-non-windows.png</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=File:Prog-folder-non-windows.png&amp;diff=9889"/>
		<updated>2022-08-12T21:02:05Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=File:Screen_Shot_2022-08-12_at_3.55.18_PM.png&amp;diff=9888</id>
		<title>File:Screen Shot 2022-08-12 at 3.55.18 PM.png</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=File:Screen_Shot_2022-08-12_at_3.55.18_PM.png&amp;diff=9888"/>
		<updated>2022-08-12T20:55:51Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=File:Automatic-compile-non-windows.png&amp;diff=9887</id>
		<title>File:Automatic-compile-non-windows.png</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=File:Automatic-compile-non-windows.png&amp;diff=9887"/>
		<updated>2022-08-12T20:48:14Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=File:Terminal-trunk-directory-non-windows.png&amp;diff=9886</id>
		<title>File:Terminal-trunk-directory-non-windows.png</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=File:Terminal-trunk-directory-non-windows.png&amp;diff=9886"/>
		<updated>2022-08-12T20:35:48Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:Non:Building_and_Customizing_BCI2000_on_Non-Windows_Platforms&amp;diff=9885</id>
		<title>Programming Howto:Non:Building and Customizing BCI2000 on Non-Windows Platforms</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:Non:Building_and_Customizing_BCI2000_on_Non-Windows_Platforms&amp;diff=9885"/>
		<updated>2022-08-12T20:29:45Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: Created page with &amp;quot;This tutorial will walk you through the process of obtaining the BCI2000 source distribution and building BCI2000.  =How To Steps= *Programming Howto: Install Prerequisites...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This tutorial will walk you through the process of obtaining the BCI2000 source distribution and building BCI2000.&lt;br /&gt;
&lt;br /&gt;
=How To Steps=&lt;br /&gt;
*[[Programming Howto: Install Prerequisites on Non-Windows Platforms|Install Prerequisites]]&lt;br /&gt;
*[[Programming Howto:Register with BCI2000 Project|Register with the BCI2000 Project]]&lt;br /&gt;
*[[Programming Howto:Download the BCI2000 Sourcecode on Non-Windows Platforms|Download the BCI2000 Sourcecode]]&lt;br /&gt;
*[[Programming Howto:Automatically Build BCI2000 on Non-Windows Platforms|Automatically Build BCI2000]] &amp;lt;b&amp;gt;OR&amp;lt;/b&amp;gt; [[Programming Howto:Manually Build BCI2000 on Non-Windows Platforms|Manually Build BCI2000]]&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:_Install_Prerequisites_on_Non-Windows_Platforms&amp;diff=9884</id>
		<title>Programming Howto: Install Prerequisites on Non-Windows Platforms</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:_Install_Prerequisites_on_Non-Windows_Platforms&amp;diff=9884"/>
		<updated>2022-08-12T20:22:34Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: Created page with &amp;quot;=Back= Programming Howto:Building_and_Customizing_BCI2000_on_Non-Windows_Platforms|to the ove...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=[[Programming Howto:Building_and_Customizing_BCI2000_on_Non-Windows_Platforms|Back]]=&lt;br /&gt;
[[Programming Howto:Building_and_Customizing_BCI2000_on_Non-Windows_Platforms|to the overview page]]&lt;br /&gt;
&lt;br /&gt;
=Homebrew=&lt;br /&gt;
[https://brew.sh|Homebrew] is a package manager for mac and linux that we will be using to install several items. You may also use another package manager if you have one that you prefer. Install it with&lt;br /&gt;
 /bin/bash -c &amp;quot;$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)&amp;quot;&lt;br /&gt;
Now check to make sure that it was installed correctly with&lt;br /&gt;
 brew --version&lt;br /&gt;
&lt;br /&gt;
=SVN=&lt;br /&gt;
SVN is used to checkout the source code repository. Install it with&lt;br /&gt;
 brew install Subversion&lt;br /&gt;
Now check to make sure that it was installed correctly with&lt;br /&gt;
 svn --version&lt;br /&gt;
&lt;br /&gt;
=Qt5=&lt;br /&gt;
Qt is used to render to BCI2000 windows. &amp;lt;b&amp;gt;Qt version 5 is the only version that is supported on Non-Windows Platforms.&amp;lt;/b&amp;gt; Install it with&lt;br /&gt;
 brew install qt@5&lt;br /&gt;
Now check to make sure that it was installed correctly with&lt;br /&gt;
 qmake --version&lt;br /&gt;
&lt;br /&gt;
=CMake=&lt;br /&gt;
CMake is used to customize BCI2000 builds. Install it with&lt;br /&gt;
 brew install cmake&lt;br /&gt;
Now check to make sure that it was install correctly with&lt;br /&gt;
 cmake --version&lt;br /&gt;
&lt;br /&gt;
=[[Programming_Howto:Register_with_BCI2000_Project|Next]]=&lt;br /&gt;
[[Programming_Howto:Register_with_BCI2000_Project|Install Dependencies]]&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:Download_the_BCI2000_Sourcecode_on_Non-Windows_Platforms&amp;diff=9883</id>
		<title>Programming Howto:Download the BCI2000 Sourcecode on Non-Windows Platforms</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=Programming_Howto:Download_the_BCI2000_Sourcecode_on_Non-Windows_Platforms&amp;diff=9883"/>
		<updated>2022-08-12T20:12:08Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: Created page with &amp;quot;=Back= Programming Howto:Building_and_Customizing_BCI2000_on_Non-Windows_Platforms|to the ove...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=[[Programming Howto:Building_and_Customizing_BCI2000_on_Non-Windows_Platforms|Back]]=&lt;br /&gt;
[[Programming Howto:Building_and_Customizing_BCI2000_on_Non-Windows_Platforms|to the overview page]]&lt;br /&gt;
=Open Terminal=&lt;br /&gt;
First open a terminal application and navigate to the location you want your source code to be located at. For example, a folder named BCI2000 in the users home directory. &lt;br /&gt;
[[File:Navigate-to-bci2000-directory-mac.png|700px]]&lt;br /&gt;
=Checkout SVN Repository=&lt;br /&gt;
Now, checkout the BCI2000 source code with svn. You will be prompted for your computer&#039;s password and your username and password for the BCI2000 project that you created in the last step.&lt;br /&gt;
 svn checkout https://bci2000.org/svn/trunk&lt;br /&gt;
[[File:Svn-checkout-non-windows.png|700px]]&lt;br /&gt;
&amp;lt;br/&amp;gt;You will now have a new folder, named trunk, in that directory. Inside of &amp;quot;trunk&amp;quot; will be the source code for BCI2000.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:Trunk-directory-non-windows.png|700px]]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
=[[Programming Howto:Install Dependencies on Non-Windows Platforms|Next]]=&lt;br /&gt;
[[Programming Howto:Install Dependencies on Non-Windows Platforms|Install Dependencies]]&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=File:Trunk-directory-non-windows.png&amp;diff=9882</id>
		<title>File:Trunk-directory-non-windows.png</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=File:Trunk-directory-non-windows.png&amp;diff=9882"/>
		<updated>2022-08-12T20:03:47Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=File:Svn-checkout-non-windows.png&amp;diff=9881</id>
		<title>File:Svn-checkout-non-windows.png</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=File:Svn-checkout-non-windows.png&amp;diff=9881"/>
		<updated>2022-08-12T20:01:08Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: Mmarcus uploaded a new version of File:Svn-checkout-non-windows.png&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=File:Svn-checkout-non-windows.png&amp;diff=9880</id>
		<title>File:Svn-checkout-non-windows.png</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=File:Svn-checkout-non-windows.png&amp;diff=9880"/>
		<updated>2022-08-12T19:57:27Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: Mmarcus uploaded a new version of File:Svn-checkout-non-windows.png&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=File:Svn-checkout-non-windows.png&amp;diff=9879</id>
		<title>File:Svn-checkout-non-windows.png</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=File:Svn-checkout-non-windows.png&amp;diff=9879"/>
		<updated>2022-08-12T19:48:57Z</updated>

		<summary type="html">&lt;p&gt;Mmarcus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Mmarcus</name></author>
	</entry>
</feed>