This documentation describes how the LibMuse unity sample application was designed and provides a more in-depth description of how things are integrated together.
To abstract platform specific LibMuse API calls from the C# code, SampleApp.cs uses an interface called LibmuseBridge. LibmuseBridge is an abstract class that has two derived classes with implementations for Android and iOS, LibmuseBridgeAndroid and LibmuseBridgeIos respectively. These two classes are the wrapper layer that translates calls in C# to call the respective native code in either Java or Objective C. These two classes don’t actually contain any logic, they simply forward any calls to the native side.
The LibmuseUnityIos and LibmuseUnityAndroid classes provide the implementation and contain the actual logic that communicates with the headband and handles requests for data using the LibMuse API. They handle any requests from Unity for the type of data that should be received and calls any listener methods in C# when data is received. Data is passed back to C# by invoking the UnitySendMessage API provided by Unity. If there are multiple pieces of data to return, data is returned as a JSON string.
As an example of the platform differences, in LibmuseBridgeAndroid.cs we create an instance of LibmuseUnityAndroid class and invoke methods on this object using methods provided by Unity to interact with java classes and objects. This is different on iOS where they directly call C functions in the Dll library and no instance is required.
Note that this sample application do not contain all of the functionality that is available in the LibMuse API and is intended for demonstration purposes only. It only contains the detection/connection/disconnection logic and associated data listeners. You can modify and change the code to fit your needs and expand this plugin to use any additional features in the LibMuse API you require.
This plugin is written for and tested on Unity version 5.3.5.
Note you only need to perform the steps in the next two sections if you plan to modify the sample plugin code we provided to suit your needs. Otherwise you don’t need to follow these steps below. You can simply use the plugin we provided for you by reading the getting started guide.
Creating Unity Plugin for iOS
Unity has a wealth of documentation on how to create plugins for various platforms (see links below). For iOS, we can simply put the source code files under the Asssets/Plugins/iOS/ folder directly. When Unity creates the XCode project, these source file will be included in the iOS compilation automatically. As such, this is where LibmuseUnityIos.h and LibmuseUnityIos.mm file are placed.
Unity has a limitation of only calling C like functions on iOS and we must explicitly declare these C functions in C# before we can call them. This is done with the
DllImport directive provided by Unity (see LibmuseBridgeIos.cs). The actual implementation of these C functions are in the LibmuseUnityIos.mm file under an
extern C block. These C functions in turn will call methods on the LibmuseUnityIos class defined in LibmuseUnityIos.h and their implementation in the Objective C file. These instance methods will interact with the LibMuse API.
Since the LibMuse API shipped as a library, we must also place the native library inside Assets/Plugin/iOS/ folder. The library folder is named Muse.framework and contains the necessary header files and the static library file called Muse.
You can modify the LibmuseUnityIos.h and .mm files however you want. This is where you would add additional functionality that is provided in the LibMuse API. Please see the LibMuse iOS API reference for more information.
Creating Unity Plugin for Android
Creating plugin for Android is a bit more complicated than iOS because we can not simply include the java source file in the Assets/Plugin/Android folder. We must create a .jar file and put that in the folder instead. A video on how to do this with Android Studio can be found here. When building the jar file, include:
- The LibmuseUnityAndroid.java file from Assets/Plugins/Android
- The libmuse_android.jar file from Assets/Plugins/Android/libs
- The classes.jar file from Unity installation folder. On Windows this file is located at C:\Program Files\Unity\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Release\Classes. On Mac OSX, it is located at /Applications/Unity/PlaybackEngines/AndroidPlayer/Variations/mono/Release/Classes. If you do not include this file, you will get an error complaining about undefined reference to UnitySendMessage.
Copy the produced jar file over to Assets/Plugin/Android/ folder. Note that our sample plugin places everything under the Assets/Plugin/Android/libs folder instead (this also works). You must also copy the armeabi-v7a folder and the native library it contains from Assets/Plugins/Android/libs and place it next to the jar file. It is not necessary to copy the original source code as it will be ignored by Unity.
You can modify the LibmuseUnityAndroid.java file however you want. This is where you would add additional functionality that is provided in the LibMuse API. For more information, please refer to LibMuse Android API reference.
In Assets/Plugin/Android/ folder of our sample plugin, there is an AndroidManifest.xml file. This file overrides the default AndroidManifest.xml in Unity and has been modified to include the Permissions needed to use Bluetooth to connect to the Muse headband. The permissions are the only modifications to the file. Note that on Android devices running OS 6.0 and higher, the ACCESS_COARSE_LOCATION permission must be acquired at runtime by asking the user. Sample code for this is not included and left to you. On Android devices running an OS less than 6.0, no additional code is required.
You can find the default manifest file provided by Unity on Mac OSX at /Applications/Unity/PlaybackEngines/AndroidPlayer/Apk on on Windows at C:\Program Files\Unity\Editor\Data\PlaybackEngines\AndroidPlayer\Apk if you need to.