{"_id":"55096a172dd6a11900e6e774","project":"55093b151c38c50d00611894","user":"55093bd84510200d00adf3c7","version":{"_id":"55093b161c38c50d00611897","project":"55093b151c38c50d00611894","__v":4,"createdAt":"2015-03-18T08:45:10.369Z","releaseDate":"2015-03-18T08:45:10.368Z","categories":["55093b161c38c50d00611898","55093ee2961f17170070abb9","55093ee9961f17170070abba","55093ef52ee8bf2b00491916"],"is_deprecated":false,"is_hidden":false,"is_beta":false,"is_stable":true,"codename":"","version_clean":"1.0.0","version":"1.0"},"__v":7,"category":{"_id":"55093ef52ee8bf2b00491916","project":"55093b151c38c50d00611894","version":"55093b161c38c50d00611897","__v":9,"pages":["55094202961f17170070abbe","5509437a368a5617004146da","550963c0dd77250d007369c1","55096a172dd6a11900e6e774","5509811add77250d00736a1f","5509815f4ba6432d00bb7875","5509913ca2b4750d00a2341e","5509916add77250d00736a55","551923b0337285170047f861"],"sync":{"url":"","isSync":false},"reference":false,"createdAt":"2015-03-18T09:01:41.604Z","from_sync":false,"order":3,"slug":"code-examples","title":"Code Examples"},"updates":[],"next":{"pages":[],"description":""},"createdAt":"2015-03-18T12:05:43.809Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"results":{"codes":[]},"auth":"required","params":[],"url":""},"isReference":false,"order":3,"body":"# Magic beep #\n\nWelcome to _the second tutorial_ example !\n\nThis example presents the fundamental steps to master the ISKN API. \nYou will learn how to connect to the slate, how to receive the slate events, \nand how to handle those events and get their parameters.\n\nThis is a simple tone generation application using the ISKN Slate. \nThe application detects the presence of a pen in the view field of the slate, \nand generates a tone when the pen touches the surface. \nThe tone frequency and its duration depends on the pen colour and the position of the pen on the slate.  \n\nNote that you can find __the full source code__ for this example in the ISKN_API examples folder. \n \n## 1.Set Up Your Project\n\nBefore you start, be sure you have your development environment set up.\nIn this example you need to create an empty Win32 Console project.\nYou can specify _MagicBeep_ as a project name.\n\nLink the ISKN API to your project. To do so you can see the first tutorial [here](md_src_example_vs_s1.html).\n\nAdd a main source file Main.cpp to the project and create the project entry point (the main function).\n\nAdd a new class named MagicBeep. This generates a header file 'MagicBeep.h' and a source file 'MagicBeep.cpp'.\n\nNow your project solution should look like this :\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/Lu4yQByTDmerZQy8Ihbg_Mb_Solution_Explorer.PNG\",\n        \"Mb_Solution_Explorer.PNG\",\n        \"351\",\n        \"433\",\n        \"#9b5b69\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\n\n## 2.Including the ISKN API main header file\n\n+In order to use the API, include ISKN_API.h in the header file of the MagicBeep :\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"#include \\\"ISKN_API.h\\\"\\nusing namespace ISKN_API;\",\n      \"language\": \"cplusplus\"\n    }\n  ]\n}\n[/block]\n## 3.Preparing the event listener class\n\n+To receive the Slate events, you need to register a listener. \nIn this example, the MagicBeep class extends the Listener class.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"class MagicBeep : public Listener\",\n      \"language\": \"cplusplus\"\n    }\n  ]\n}\n[/block]\nThe listener class is an interface providing the following methods :\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"void processEvent(Event &e, unsigned int timecode);\\nvoid connectionStatusChanged(bool connected);\",\n      \"language\": \"cplusplus\"\n    }\n  ]\n}\n[/block]\nThose methods should be implemented by the subclass in order to receive the slate events.\n\nAt this point, the MagicBeep listener class is ready to be registered. \n\n## 4.Preparing the communication tools\n\nBefore registering the listener, we need to create the Slate manager object, then get the device object.\nTo do so, add those attributes to your MagicBeep class declaration :\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"SlateManager *iskn_SlateManager;\\n    Device      *iskn_Device;\",\n      \"language\": \"cplusplus\"\n    }\n  ]\n}\n[/block]\nYour header file MagicBeep.h should be like this:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"#pragma once\\n\\n#include \\\"ISKN_API.h\\\"\\nusing namespace ISKN_API;\\n\\n#include <iostream>\\nusing namespace std;\\n\\nclass MagicBeep:public Listener\\n{\\npublic:\\n\\tMagicBeep();\\n\\t~MagicBeep();\\n\\n\\tSlateManager *iskn_SlateManager;\\n\\tDevice      *iskn_Device;\\n\\t\\n\\tVector3D prevPos;\\n\\tint spectrumMultiplier;\\n\\n\\tvoid processEvent(Event &e, unsigned int timecode);\\n\\tvoid connectionStatusChanged(bool connected);\\n};\",\n      \"language\": \"cplusplus\"\n    }\n  ]\n}\n[/block]\nIn the constructor method of the MagicBeep class, create the Slate manager object and get the Device object:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"  iskn_SlateManager  = new SlateManager();\\n  iskn_Device     = &iskn_SlateManager->getDevice();\",\n      \"language\": \"cplusplus\"\n    }\n  ]\n}\n[/block]\n## 5. Registering the events listener\n\nOnce the slate manager, is created, it is possible to register the MagicBeep class as a listener. \nTo do so, use the registerListener method of the slate manager :\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"iskn_SlateManager->registerListener(this);\",\n      \"language\": \"text\"\n    }\n  ]\n}\n[/block]\n## 6. Connect to the slate and subscribe to the services\n\nBefore being able to receive slate events, the application should connect to the Slate. \nUse the connect method of the Slate manager object to create a connection \nand `connectionStatusChanged(bool)` to check if the connection was made successfully.\nOnce connected, request the slate description in order to update the Device object information.\nThis gathers specific slate information such as slate name, the size of the slate, the writing zone of the slate.\nThis is performed by the request method of the Slate manager object.\nFinally, you need to subscribe to automatic events services. This tells the Slate which events your listener should receive.\n\nIn this application, we request four types of events :\n+ AUTO_STATUS        \t\t: Asks to receive slate status changes (Battery charge change, (SD card insertion/ removal))\n+ AUTO_SOFTWARE_EVENTS    \t: Asks to receive Software events like object status change (Object recognised (SE_OBJECT_IN), object lost(SE_OBJECT_OUT), handshake event (a periodic event used to detect that the Slate is still on)). \n+ AUTO_HARDWARE_EVENTS \t\t: Asks to receive Hardware events (When a button is pressed (new page button, new layer button, reset event (long press on new page button)), SD card inserted or removed ) \n+ AUTO_PEN_3D        \t\t: Asks to receive the Pen tip 3D position and contact status at a 140Hz frequency when the pen is in the field of view of the slate.  \n\nThe MagicBeep constructor :\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"MagicBeep::MagicBeep()\\n{\\n\\tprevPos = { 0.0f, 0.0f, 0.0f };\\n\\tspectrumMultiplier = 5;\\n\\n\\t// Create SlateManager and Device\\n\\tiskn_SlateManager = new SlateManager();\\n\\tiskn_Device = &iskn_SlateManager->getDevice();\\n\\n\\t// Register events Listener\\n\\tiskn_SlateManager->registerListener(this);\\n\\n\\t// Connect to the Slate\\n\\tcout << \\\"Attempting to connect to iSketchnote device...\\\" << endl;\\n\\tiskn_SlateManager->connect();\\n}\",\n      \"language\": \"cplusplus\"\n    }\n  ]\n}\n[/block]\nThe MagicBeep connectionStatusChanged method :\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"void MagicBeep::connectionStatusChanged(bool connected)\\n{\\n\\ttry\\n\\t{\\t\\n\\t\\tif (connected)\\n\\t\\t{\\n\\t\\t\\t// Request Slate description\\n\\t\\t\\tiskn_SlateManager->request(REQ_DESCRIPTION);\\n\\t\\t\\t// Subscribe to events (Status event, Software events, Hardware events and Pen 3D event)\\n\\t\\t\\tiskn_SlateManager->subscribe(AUTO_STATUS | AUTO_SOFTWARE_EVENTS | AUTO_HARDWARE_EVENTS | AUTO_PEN_3D);\\n\\t\\t\\tcout << \\\"Slate connected !\\\" << endl;\\n\\t\\t}\\n\\t\\telse\\n\\t\\t{\\n\\t\\t\\tcout << \\\"Slate could not connect !\\\" << endl;\\n\\t\\t}\\n\\t}\\n\\tcatch (Error &err)\\n\\t{\\n\\t\\twcout << err.Message() << endl;\\n\\t}\\n}\",\n      \"language\": \"cplusplus\"\n    }\n  ]\n}\n[/block]\n## 7. Receive and extract events\n\nThe processEvent method is called whenever a new event is received from the Slate.\nUse the type attribute of the Event object in order to figure out the event name.\nYou can use a switch case statement as follow :\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"switch (e.Type)\\n\\t{\\n\\t\\tcase EVT_STATUS:\\n\\t\\t\\t// A status change detected\\n\\t\\t\\tbreak;\\n\\t\\tcase EVT_DESCRIPTION:\\n\\t\\t\\t// Event received after a Description request\\n\\t\\t\\tbreak;\\n\\t\\tcase EVT_SOFTWARE:\\n\\t\\t\\t// A software event happened\\n\\t\\t\\tswitch (e.SoftwareEvent.getSoftwareEventType())\\n\\t\\t\\t{\\n\\t\\t\\tcase SE_OBJECT_IN:\\n\\t\\t\\t\\t// A new object is detected, use e.SoftwareEvent.getObjectID() to get the object ID\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase SE_OBJECT_OUT:\\n\\t\\t\\t\\t// Object lost, use e.SoftwareEvent.getObjectID() to get the object ID\\n\\t\\t\\t\\tbreak;\\n\\n\\t\\t\\tcase SE_HANDSHAKE:\\n\\t\\t\\t\\t// Periodic handshake event\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\t}\\n\\t\\t\\tbreak;\\n\\n\\t\\tcase EVT_HARDWARE:\\n\\t\\t\\t// A hardware event happened\\n\\t\\t\\tswitch (e.HardwareEvent.getHardwareEventType())\\n\\t\\t\\t{\\n\\t\\t\\tcase HE_BUTTON1_PRESSED:\\n\\t\\t\\t\\t//Button 1 pressed\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase HE_BUTTON2_PRESSED:\\n\\t\\t\\t\\t//Button 2 pressed\\n\\t\\t\\t\\tbreak;\\t\\t\\n\\t\\t\\t}\\n\\t\\t\\tbreak;\\n\\n\\t\\tcase EVT_PEN_3D:\\n\\t\\t{\\n\\t\\t\\t// New pen position and contact status\\n\\t\\t\\tbreak;\\n\\t\\t}\\n\\t}\",\n      \"language\": \"cplusplus\"\n    }\n  ]\n}\n[/block]\n## 8. Determining the tone style by determining the pen ID\n\nIn this application, we use the EVT_PEN_STATUS / PEN_STATUS_IN event to get the pen ID. \nWe use it to define the tone frequency multiplier. This will define the frequency range used to generate the tones.\n\nCreate an int array containing the multiplier list :\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"int toneMultiplier[5] = {0, 2, 5, 10, 15 };\",\n      \"language\": \"cplusplus\"\n    }\n  ]\n}\n[/block]\nCreate an attribute in the MagicBeep class called spectrumMultiplier :\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"int spectrumMultiplier;\",\n      \"language\": \"cplusplus\"\n    }\n  ]\n}\n[/block]\nWhen the pen is recognised (a software event is received with event type SE_OBJECT_IN), use the object ID to determine the spectrumMultiplier :\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"\\tcase EVT_SOFTWARE:\\n\\t\\tswitch (e.SoftwareEvent.getSoftwareEventType())\\n\\t\\t{\\n\\t\\tcase SE_OBJECT_IN:\\n\\t\\t\\t// A new pen is detected, select the appropriate tone\\n\\t\\t\\tcout << \\\"Pen in : \\\" << e.SoftwareEvent.getObjectID() << endl;\\n\\t\\t\\tspectrumMultiplier = toneMultiplier[e.SoftwareEvent.getObjectID()];\\n\\t\\t\\tcout << \\\"Tone changed : \\\" << spectrumMultiplier << endl;\\n\\t\\t\\tbreak;\\n\\n\\t\\tcase SE_OBJECT_OUT:\\n\\t\\t\\t// Pen is out of reach\\n\\t\\t\\tcout << \\\" -----------------\\\" << endl;\\n\\t\\t\\tbreak;\\n\\n\\t\\tcase SE_HANDSHAKE:\\n\\t\\t\\tbreak;\\n\\t\\t}\\n\\t\\tbreak;\",\n      \"language\": \"cplusplus\"\n    }\n  ]\n}\n[/block]\n## 9. Playing the tone\n\nAfter recognising the pen, the slate will start sending its 3D position of the pen tip as well as contact information.\nWe use the Y coordinate of the pen tip to determine the frequency of the sound that we will generate.\nWe use the X coordinate of the pen to determine the tone duration.\nWe use the Z coordinate to separate tones. (The user should hit the slate with the pen tip to produce the tone).\nTo generate the tone we use the Windows Beep function.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"case EVT_PEN_3D :\\n{\\n\\t\\t// Recover pen tip position\\n        Vector3D pos = e.Pen3D.getPosition();\\n        // Compute tone parameters\\n        DWORD freq = pos.Y*spectrumMultiplier; // tone (can be changed to have larger tone spectrum)\\n        DWORD duration = pos.X * 2;\\n        // Detect that the tip of the pen just crossed the 15mm threshold (going down)\\n        if (prevPos.Z>15 && pos.Z<15)\\n        {\\n            // Display frequency bar\\n            cout << \\\"Freq \\\";\\n            for (int i = 0; i < (int)pos.Y/10; i++)\\n                cout << \\\"|\\\";\\n            cout << endl;\\n            // Display duration bar\\n            cout << \\\"Dur \\\";\\n            for (int i = 0; i < (int)pos.X / 10; i++)\\n                cout << \\\"-\\\";\\n            cout << endl;\\n            // Play tone\\n            Beep(freq, duration);\\n\\n        }\\n\\t// Backup the pen position\\n        prevPos = pos;\\n}\\nbreak ;\",\n      \"language\": \"cplusplus\"\n    }\n  ]\n}\n[/block]\nTo sum up your MagicBeep.h and MagicBeep.cpp files should be like this :\n\nMagicBeep.h :\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"#pragma once\\n\\n#include \\\"ISKN_API.h\\\"\\nusing namespace ISKN_API;\\n\\n#include <iostream>\\nusing namespace std;\\n\\nclass MagicBeep:public Listener\\n{\\npublic:\\n\\n\\t// ISKN API attributes\\n\\tSlateManager *iskn_SlateManager;\\n\\tDevice      *iskn_Device;\\n\\n\\t//Application specific attributes\\n\\tVector3D prevPos;\\n\\tint spectrumMultiplier;\\n\\n\\t//Constructor\\n\\tMagicBeep();\\n\\t~MagicBeep();\\n\\n\\t//Inherited methods\\n\\tvoid processEvent(Event &e, unsigned int timecode);\\n\\tvoid connectionStatusChanged(bool connected);\\n};\",\n      \"language\": \"cplusplus\"\n    }\n  ]\n}\n[/block]\nMagicBeep.cpp :\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"#include \\\"MagicBeep.h\\\"\\n#include <math.h>\\n\\nint toneMultiplier[5] = {0, 2, 5, 10, 15 };\\n\\nMagicBeep::MagicBeep()\\n{\\n\\tprevPos = { 0.0f, 0.0f, 0.0f };\\n\\tspectrumMultiplier = 5;\\n\\n\\t// Create SlateManager and Device\\n\\tiskn_SlateManager = new SlateManager();\\n\\tiskn_Device = &iskn_SlateManager->getDevice();\\n\\n\\t// Register events Listener\\n\\tiskn_SlateManager->registerListener(this);\\n\\n\\t// Connect to the Slate\\n\\tcout << \\\"Attempting to connect to iSketchnote device...\\\" << endl;\\n\\tiskn_SlateManager->connect();\\n}\\n\\nvoid MagicBeep::connectionStatusChanged(bool connected)\\n{\\n\\ttry\\n\\t{\\t\\n\\t\\tif (connected)\\n\\t\\t{\\n\\t\\t\\t// Request Slate description\\n\\t\\t\\tiskn_SlateManager->request(REQ_DESCRIPTION);\\n\\t\\t\\t// Subscribe to events (Status event, Software events, Hardware events and Pen 3D event)\\n\\t\\t\\tiskn_SlateManager->subscribe(AUTO_STATUS | AUTO_SOFTWARE_EVENTS | AUTO_HARDWARE_EVENTS | AUTO_PEN_3D);\\n\\t\\t\\tcout << \\\"Slate connected !\\\" << endl;\\n\\t\\t}\\n\\t\\telse\\n\\t\\t{\\n\\t\\t\\tcout << \\\"Slate could not connect !\\\" << endl;\\n\\t\\t}\\n\\t}\\n\\tcatch (Error &err)\\n\\t{\\n\\t\\twcout << err.Message() << endl;\\n\\t}\\n}\\n\\nvoid MagicBeep::processEvent(Event &e, unsigned int timecode)\\n{\\n\\tswitch (e.Type)\\n\\t{\\n\\tcase EVT_STATUS:\\n\\t\\tcout << \\\"Battery : \\\" << iskn_Device->getBatteryCharge() << endl;\\t\\t\\n\\t\\tbreak;\\n\\tcase EVT_DESCRIPTION:\\n\\t\\twcout << \\\"Device id: \\\" << iskn_Device->getDeviceName().c_str() << endl;\\n\\t\\tbreak;\\n\\tcase EVT_SOFTWARE:\\n\\t\\tswitch (e.SoftwareEvent.getSoftwareEventType())\\n\\t\\t{\\n\\t\\tcase SE_OBJECT_IN:\\n\\t\\t\\t// A new pen is detected, select the appropriate tone\\n\\t\\t\\tcout << \\\"Pen in : \\\" << e.SoftwareEvent.getObjectID() << endl;\\n\\t\\t\\tspectrumMultiplier = toneMultiplier[e.SoftwareEvent.getObjectID()];\\n\\t\\t\\tcout << \\\"Tone changed : \\\" << spectrumMultiplier << endl;\\n\\t\\t\\tbreak;\\n\\t\\tcase SE_OBJECT_OUT:\\n\\t\\t\\t// Pen is out of reach\\n\\t\\t\\tcout << \\\" -----------------\\\" << endl;\\n\\t\\t\\tbreak;\\n\\n\\t\\tcase SE_HANDSHAKE:\\n\\t\\t\\tbreak;\\n\\t\\t}\\n\\t\\tbreak;\\n\\n\\tcase EVT_HARDWARE:\\n\\t\\tcout << \\\"Device hardware event : \\\" << e.HardwareEvent.getHardwareEventType() << endl;\\n\\t\\tswitch (e.HardwareEvent.getHardwareEventType())\\n\\t\\t{\\n\\t\\tcase HE_BUTTON1_PRESSED:\\n\\t\\t\\tcout << \\\"Button 1 pressed\\\" << endl;\\n\\t\\t\\tbreak;\\n\\t\\tcase HE_BUTTON2_PRESSED:\\n\\t\\t\\tcout << \\\"Button 2 pressed\\\" << endl;\\n\\t\\t\\tbreak;\\n\\t\\t}\\n\\t\\tbreak;\\n\\n\\tcase EVT_PEN_3D:\\n\\t{\\n\\t\\t// Recover pen tip position\\n\\t\\tVector3D pos = e.Pen3D.getPosition();\\n\\t\\t// Compute tone parameters\\n\\t\\tDWORD freq = pos.Y*spectrumMultiplier; // tone (can be changed to have larger tone spectrum)\\n\\t\\tDWORD duration = pos.X * 2;\\n\\t\\t// Detect that the tip of the pen just crossed the 15mm threshold (going down)\\n\\t\\tif (prevPos.Z>15 && pos.Z<15)\\n\\t\\t{ \\n\\t\\t\\t// Display frequency bar\\n\\t\\t\\tcout << \\\"Freq \\\";\\n\\t\\t\\tfor (int i = 0; i < (int)pos.Y/10; i++)\\n\\t\\t\\t\\tcout << \\\"|\\\";\\n\\t\\t\\tcout << endl;\\n\\t\\t\\t// Display duration bar\\n\\t\\t\\tcout << \\\"Dur \\\";\\n\\t\\t\\tfor (int i = 0; i < (int)pos.X / 10; i++)\\n\\t\\t\\t\\tcout << \\\"-\\\";\\n\\t\\t\\tcout << endl;\\n\\t\\t\\t// Play tone\\n\\t\\t\\tBeep(freq, duration);\\n\\n\\t\\t}\\n\\t\\tprevPos = pos;\\n\\t}\\n\\t\\tbreak;\\n\\n\\tdefault:\\n\\t\\tif (e.Type >= EVT_ERROR)\\n\\t\\t\\tcout << \\\"Event : \\\" << (int)e.Type << endl;\\n\\t\\tbreak;\\n\\t}\\n}\\n\\nMagicBeep::~MagicBeep()\\n{\\n}\",\n      \"language\": \"cplusplus\"\n    }\n  ]\n}\n[/block]\n## 10. Run your project\n\nYour project is now ready to run.\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/XnzonBFBS42ic5jmmB5n_MbConsole.PNG\",\n        \"MbConsole.PNG\",\n        \"843\",\n        \"551\",\n        \"#bf5250\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]","excerpt":"","slug":"magicbeep-example-on-vs","type":"basic","title":"MagicBeep example on VS"}

MagicBeep example on VS


# Magic beep # Welcome to _the second tutorial_ example ! This example presents the fundamental steps to master the ISKN API. You will learn how to connect to the slate, how to receive the slate events, and how to handle those events and get their parameters. This is a simple tone generation application using the ISKN Slate. The application detects the presence of a pen in the view field of the slate, and generates a tone when the pen touches the surface. The tone frequency and its duration depends on the pen colour and the position of the pen on the slate. Note that you can find __the full source code__ for this example in the ISKN_API examples folder. ## 1.Set Up Your Project Before you start, be sure you have your development environment set up. In this example you need to create an empty Win32 Console project. You can specify _MagicBeep_ as a project name. Link the ISKN API to your project. To do so you can see the first tutorial [here](md_src_example_vs_s1.html). Add a main source file Main.cpp to the project and create the project entry point (the main function). Add a new class named MagicBeep. This generates a header file 'MagicBeep.h' and a source file 'MagicBeep.cpp'. Now your project solution should look like this : [block:image] { "images": [ { "image": [ "https://files.readme.io/Lu4yQByTDmerZQy8Ihbg_Mb_Solution_Explorer.PNG", "Mb_Solution_Explorer.PNG", "351", "433", "#9b5b69", "" ] } ] } [/block] ## 2.Including the ISKN API main header file +In order to use the API, include ISKN_API.h in the header file of the MagicBeep : [block:code] { "codes": [ { "code": "#include \"ISKN_API.h\"\nusing namespace ISKN_API;", "language": "cplusplus" } ] } [/block] ## 3.Preparing the event listener class +To receive the Slate events, you need to register a listener. In this example, the MagicBeep class extends the Listener class. [block:code] { "codes": [ { "code": "class MagicBeep : public Listener", "language": "cplusplus" } ] } [/block] The listener class is an interface providing the following methods : [block:code] { "codes": [ { "code": "void processEvent(Event &e, unsigned int timecode);\nvoid connectionStatusChanged(bool connected);", "language": "cplusplus" } ] } [/block] Those methods should be implemented by the subclass in order to receive the slate events. At this point, the MagicBeep listener class is ready to be registered. ## 4.Preparing the communication tools Before registering the listener, we need to create the Slate manager object, then get the device object. To do so, add those attributes to your MagicBeep class declaration : [block:code] { "codes": [ { "code": "SlateManager *iskn_SlateManager;\n Device *iskn_Device;", "language": "cplusplus" } ] } [/block] Your header file MagicBeep.h should be like this: [block:code] { "codes": [ { "code": "#pragma once\n\n#include \"ISKN_API.h\"\nusing namespace ISKN_API;\n\n#include <iostream>\nusing namespace std;\n\nclass MagicBeep:public Listener\n{\npublic:\n\tMagicBeep();\n\t~MagicBeep();\n\n\tSlateManager *iskn_SlateManager;\n\tDevice *iskn_Device;\n\t\n\tVector3D prevPos;\n\tint spectrumMultiplier;\n\n\tvoid processEvent(Event &e, unsigned int timecode);\n\tvoid connectionStatusChanged(bool connected);\n};", "language": "cplusplus" } ] } [/block] In the constructor method of the MagicBeep class, create the Slate manager object and get the Device object: [block:code] { "codes": [ { "code": " iskn_SlateManager = new SlateManager();\n iskn_Device = &iskn_SlateManager->getDevice();", "language": "cplusplus" } ] } [/block] ## 5. Registering the events listener Once the slate manager, is created, it is possible to register the MagicBeep class as a listener. To do so, use the registerListener method of the slate manager : [block:code] { "codes": [ { "code": "iskn_SlateManager->registerListener(this);", "language": "text" } ] } [/block] ## 6. Connect to the slate and subscribe to the services Before being able to receive slate events, the application should connect to the Slate. Use the connect method of the Slate manager object to create a connection and `connectionStatusChanged(bool)` to check if the connection was made successfully. Once connected, request the slate description in order to update the Device object information. This gathers specific slate information such as slate name, the size of the slate, the writing zone of the slate. This is performed by the request method of the Slate manager object. Finally, you need to subscribe to automatic events services. This tells the Slate which events your listener should receive. In this application, we request four types of events : + AUTO_STATUS : Asks to receive slate status changes (Battery charge change, (SD card insertion/ removal)) + AUTO_SOFTWARE_EVENTS : Asks to receive Software events like object status change (Object recognised (SE_OBJECT_IN), object lost(SE_OBJECT_OUT), handshake event (a periodic event used to detect that the Slate is still on)). + AUTO_HARDWARE_EVENTS : Asks to receive Hardware events (When a button is pressed (new page button, new layer button, reset event (long press on new page button)), SD card inserted or removed ) + AUTO_PEN_3D : Asks to receive the Pen tip 3D position and contact status at a 140Hz frequency when the pen is in the field of view of the slate. The MagicBeep constructor : [block:code] { "codes": [ { "code": "MagicBeep::MagicBeep()\n{\n\tprevPos = { 0.0f, 0.0f, 0.0f };\n\tspectrumMultiplier = 5;\n\n\t// Create SlateManager and Device\n\tiskn_SlateManager = new SlateManager();\n\tiskn_Device = &iskn_SlateManager->getDevice();\n\n\t// Register events Listener\n\tiskn_SlateManager->registerListener(this);\n\n\t// Connect to the Slate\n\tcout << \"Attempting to connect to iSketchnote device...\" << endl;\n\tiskn_SlateManager->connect();\n}", "language": "cplusplus" } ] } [/block] The MagicBeep connectionStatusChanged method : [block:code] { "codes": [ { "code": "void MagicBeep::connectionStatusChanged(bool connected)\n{\n\ttry\n\t{\t\n\t\tif (connected)\n\t\t{\n\t\t\t// Request Slate description\n\t\t\tiskn_SlateManager->request(REQ_DESCRIPTION);\n\t\t\t// Subscribe to events (Status event, Software events, Hardware events and Pen 3D event)\n\t\t\tiskn_SlateManager->subscribe(AUTO_STATUS | AUTO_SOFTWARE_EVENTS | AUTO_HARDWARE_EVENTS | AUTO_PEN_3D);\n\t\t\tcout << \"Slate connected !\" << endl;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tcout << \"Slate could not connect !\" << endl;\n\t\t}\n\t}\n\tcatch (Error &err)\n\t{\n\t\twcout << err.Message() << endl;\n\t}\n}", "language": "cplusplus" } ] } [/block] ## 7. Receive and extract events The processEvent method is called whenever a new event is received from the Slate. Use the type attribute of the Event object in order to figure out the event name. You can use a switch case statement as follow : [block:code] { "codes": [ { "code": "switch (e.Type)\n\t{\n\t\tcase EVT_STATUS:\n\t\t\t// A status change detected\n\t\t\tbreak;\n\t\tcase EVT_DESCRIPTION:\n\t\t\t// Event received after a Description request\n\t\t\tbreak;\n\t\tcase EVT_SOFTWARE:\n\t\t\t// A software event happened\n\t\t\tswitch (e.SoftwareEvent.getSoftwareEventType())\n\t\t\t{\n\t\t\tcase SE_OBJECT_IN:\n\t\t\t\t// A new object is detected, use e.SoftwareEvent.getObjectID() to get the object ID\n\t\t\t\tbreak;\n\t\t\tcase SE_OBJECT_OUT:\n\t\t\t\t// Object lost, use e.SoftwareEvent.getObjectID() to get the object ID\n\t\t\t\tbreak;\n\n\t\t\tcase SE_HANDSHAKE:\n\t\t\t\t// Periodic handshake event\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase EVT_HARDWARE:\n\t\t\t// A hardware event happened\n\t\t\tswitch (e.HardwareEvent.getHardwareEventType())\n\t\t\t{\n\t\t\tcase HE_BUTTON1_PRESSED:\n\t\t\t\t//Button 1 pressed\n\t\t\t\tbreak;\n\t\t\tcase HE_BUTTON2_PRESSED:\n\t\t\t\t//Button 2 pressed\n\t\t\t\tbreak;\t\t\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase EVT_PEN_3D:\n\t\t{\n\t\t\t// New pen position and contact status\n\t\t\tbreak;\n\t\t}\n\t}", "language": "cplusplus" } ] } [/block] ## 8. Determining the tone style by determining the pen ID In this application, we use the EVT_PEN_STATUS / PEN_STATUS_IN event to get the pen ID. We use it to define the tone frequency multiplier. This will define the frequency range used to generate the tones. Create an int array containing the multiplier list : [block:code] { "codes": [ { "code": "int toneMultiplier[5] = {0, 2, 5, 10, 15 };", "language": "cplusplus" } ] } [/block] Create an attribute in the MagicBeep class called spectrumMultiplier : [block:code] { "codes": [ { "code": "int spectrumMultiplier;", "language": "cplusplus" } ] } [/block] When the pen is recognised (a software event is received with event type SE_OBJECT_IN), use the object ID to determine the spectrumMultiplier : [block:code] { "codes": [ { "code": "\tcase EVT_SOFTWARE:\n\t\tswitch (e.SoftwareEvent.getSoftwareEventType())\n\t\t{\n\t\tcase SE_OBJECT_IN:\n\t\t\t// A new pen is detected, select the appropriate tone\n\t\t\tcout << \"Pen in : \" << e.SoftwareEvent.getObjectID() << endl;\n\t\t\tspectrumMultiplier = toneMultiplier[e.SoftwareEvent.getObjectID()];\n\t\t\tcout << \"Tone changed : \" << spectrumMultiplier << endl;\n\t\t\tbreak;\n\n\t\tcase SE_OBJECT_OUT:\n\t\t\t// Pen is out of reach\n\t\t\tcout << \" -----------------\" << endl;\n\t\t\tbreak;\n\n\t\tcase SE_HANDSHAKE:\n\t\t\tbreak;\n\t\t}\n\t\tbreak;", "language": "cplusplus" } ] } [/block] ## 9. Playing the tone After recognising the pen, the slate will start sending its 3D position of the pen tip as well as contact information. We use the Y coordinate of the pen tip to determine the frequency of the sound that we will generate. We use the X coordinate of the pen to determine the tone duration. We use the Z coordinate to separate tones. (The user should hit the slate with the pen tip to produce the tone). To generate the tone we use the Windows Beep function. [block:code] { "codes": [ { "code": "case EVT_PEN_3D :\n{\n\t\t// Recover pen tip position\n Vector3D pos = e.Pen3D.getPosition();\n // Compute tone parameters\n DWORD freq = pos.Y*spectrumMultiplier; // tone (can be changed to have larger tone spectrum)\n DWORD duration = pos.X * 2;\n // Detect that the tip of the pen just crossed the 15mm threshold (going down)\n if (prevPos.Z>15 && pos.Z<15)\n {\n // Display frequency bar\n cout << \"Freq \";\n for (int i = 0; i < (int)pos.Y/10; i++)\n cout << \"|\";\n cout << endl;\n // Display duration bar\n cout << \"Dur \";\n for (int i = 0; i < (int)pos.X / 10; i++)\n cout << \"-\";\n cout << endl;\n // Play tone\n Beep(freq, duration);\n\n }\n\t// Backup the pen position\n prevPos = pos;\n}\nbreak ;", "language": "cplusplus" } ] } [/block] To sum up your MagicBeep.h and MagicBeep.cpp files should be like this : MagicBeep.h : [block:code] { "codes": [ { "code": "#pragma once\n\n#include \"ISKN_API.h\"\nusing namespace ISKN_API;\n\n#include <iostream>\nusing namespace std;\n\nclass MagicBeep:public Listener\n{\npublic:\n\n\t// ISKN API attributes\n\tSlateManager *iskn_SlateManager;\n\tDevice *iskn_Device;\n\n\t//Application specific attributes\n\tVector3D prevPos;\n\tint spectrumMultiplier;\n\n\t//Constructor\n\tMagicBeep();\n\t~MagicBeep();\n\n\t//Inherited methods\n\tvoid processEvent(Event &e, unsigned int timecode);\n\tvoid connectionStatusChanged(bool connected);\n};", "language": "cplusplus" } ] } [/block] MagicBeep.cpp : [block:code] { "codes": [ { "code": "#include \"MagicBeep.h\"\n#include <math.h>\n\nint toneMultiplier[5] = {0, 2, 5, 10, 15 };\n\nMagicBeep::MagicBeep()\n{\n\tprevPos = { 0.0f, 0.0f, 0.0f };\n\tspectrumMultiplier = 5;\n\n\t// Create SlateManager and Device\n\tiskn_SlateManager = new SlateManager();\n\tiskn_Device = &iskn_SlateManager->getDevice();\n\n\t// Register events Listener\n\tiskn_SlateManager->registerListener(this);\n\n\t// Connect to the Slate\n\tcout << \"Attempting to connect to iSketchnote device...\" << endl;\n\tiskn_SlateManager->connect();\n}\n\nvoid MagicBeep::connectionStatusChanged(bool connected)\n{\n\ttry\n\t{\t\n\t\tif (connected)\n\t\t{\n\t\t\t// Request Slate description\n\t\t\tiskn_SlateManager->request(REQ_DESCRIPTION);\n\t\t\t// Subscribe to events (Status event, Software events, Hardware events and Pen 3D event)\n\t\t\tiskn_SlateManager->subscribe(AUTO_STATUS | AUTO_SOFTWARE_EVENTS | AUTO_HARDWARE_EVENTS | AUTO_PEN_3D);\n\t\t\tcout << \"Slate connected !\" << endl;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tcout << \"Slate could not connect !\" << endl;\n\t\t}\n\t}\n\tcatch (Error &err)\n\t{\n\t\twcout << err.Message() << endl;\n\t}\n}\n\nvoid MagicBeep::processEvent(Event &e, unsigned int timecode)\n{\n\tswitch (e.Type)\n\t{\n\tcase EVT_STATUS:\n\t\tcout << \"Battery : \" << iskn_Device->getBatteryCharge() << endl;\t\t\n\t\tbreak;\n\tcase EVT_DESCRIPTION:\n\t\twcout << \"Device id: \" << iskn_Device->getDeviceName().c_str() << endl;\n\t\tbreak;\n\tcase EVT_SOFTWARE:\n\t\tswitch (e.SoftwareEvent.getSoftwareEventType())\n\t\t{\n\t\tcase SE_OBJECT_IN:\n\t\t\t// A new pen is detected, select the appropriate tone\n\t\t\tcout << \"Pen in : \" << e.SoftwareEvent.getObjectID() << endl;\n\t\t\tspectrumMultiplier = toneMultiplier[e.SoftwareEvent.getObjectID()];\n\t\t\tcout << \"Tone changed : \" << spectrumMultiplier << endl;\n\t\t\tbreak;\n\t\tcase SE_OBJECT_OUT:\n\t\t\t// Pen is out of reach\n\t\t\tcout << \" -----------------\" << endl;\n\t\t\tbreak;\n\n\t\tcase SE_HANDSHAKE:\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\n\tcase EVT_HARDWARE:\n\t\tcout << \"Device hardware event : \" << e.HardwareEvent.getHardwareEventType() << endl;\n\t\tswitch (e.HardwareEvent.getHardwareEventType())\n\t\t{\n\t\tcase HE_BUTTON1_PRESSED:\n\t\t\tcout << \"Button 1 pressed\" << endl;\n\t\t\tbreak;\n\t\tcase HE_BUTTON2_PRESSED:\n\t\t\tcout << \"Button 2 pressed\" << endl;\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\n\tcase EVT_PEN_3D:\n\t{\n\t\t// Recover pen tip position\n\t\tVector3D pos = e.Pen3D.getPosition();\n\t\t// Compute tone parameters\n\t\tDWORD freq = pos.Y*spectrumMultiplier; // tone (can be changed to have larger tone spectrum)\n\t\tDWORD duration = pos.X * 2;\n\t\t// Detect that the tip of the pen just crossed the 15mm threshold (going down)\n\t\tif (prevPos.Z>15 && pos.Z<15)\n\t\t{ \n\t\t\t// Display frequency bar\n\t\t\tcout << \"Freq \";\n\t\t\tfor (int i = 0; i < (int)pos.Y/10; i++)\n\t\t\t\tcout << \"|\";\n\t\t\tcout << endl;\n\t\t\t// Display duration bar\n\t\t\tcout << \"Dur \";\n\t\t\tfor (int i = 0; i < (int)pos.X / 10; i++)\n\t\t\t\tcout << \"-\";\n\t\t\tcout << endl;\n\t\t\t// Play tone\n\t\t\tBeep(freq, duration);\n\n\t\t}\n\t\tprevPos = pos;\n\t}\n\t\tbreak;\n\n\tdefault:\n\t\tif (e.Type >= EVT_ERROR)\n\t\t\tcout << \"Event : \" << (int)e.Type << endl;\n\t\tbreak;\n\t}\n}\n\nMagicBeep::~MagicBeep()\n{\n}", "language": "cplusplus" } ] } [/block] ## 10. Run your project Your project is now ready to run. [block:image] { "images": [ { "image": [ "https://files.readme.io/XnzonBFBS42ic5jmmB5n_MbConsole.PNG", "MbConsole.PNG", "843", "551", "#bf5250", "" ] } ] } [/block]