In the previous post I mentioned that the acceleration vector or the force vector can be used to detect gestures like shake. Here is a crude implementation of shake detection,
double x = (double)sensorData.tiltX / 1000;
double y = (double)sensorData.tiltY / 1000;
double z = (double)sensorData.tiltZ / 1000;
double forceSqrd = x * x + y * y + z * z;
System.Console.WriteLine("Force:{0}", forceSqrd);
if (forceSqrd >= SHAKE_THRESHOLD)
{
isShake = true;
}
return isShake;
}
This function calculates the square of the magnitude of the force vector and if the value exceeds a certain threshold, shake is detected. After experimenting with a few threshold values, 5.0f seemed to work ok. The problem with this implementation is that it makes an assumption that if the force acting on the device is more than 5.0f, it must be experiencing shake. This, of course, can be false. If you hold and swing the device in one fast sweep, shake will be detected. Technically, that’s not a shake if you ask me. The algorithm can be improved by checking the force against the threshold continuously, say 4-5 times, will work on that when I have time. Here’s a video showing shake detection,
Mark Arteaga wrote a post on shake detection sometime back. The algorithm he used compares (x, y), (x, z) and (y, z) values against a threshold. A shake is registered when the threshold is reached or exceeded 5 times. I replaced my function with his implementation and it works nicely.
A couple of weeks ago I went out and bought myself a HTC HD2. Yes, the 4.3inch monster running windows mobile, probably the best windows mobile device ever; this one running Windows Mobile 6.5. Did you just wince in pain on hearing windows mobile? Well, if it makes you feel any better let me assure you that I’ll buy a Windows Phone 7 device as soon as one is available in market. Ok?
I haven’t tweaked around with it too much yet but this week I had some time to look into the accelerometer.
The Accelerometer
The accelerometer sensor measures the gravitational force acting on it. When the phone is at rest the force acting on it is equal to 1g, move the phone around and the force changes (and that is how you detect shake and other gestures). The accelerometer reports the force as vectors along 3-axes, (x, y, z); the magnitude of the force can be calculated using the formula sqrt(x*x + y*y + z*z). If you hold the phone up facing you, the x axis is the horizontal, y axis is the vertical and z axis is along the direction from the phone pointing towards you. This co-ordinate system moves along with the phone. Now the direction along which the values of x, y and z increase and the origin of this co-ordinate system might depend on the implementation on that particular device, so here we will see how it’s implemented on HD2. With respect to HD2 the top-left corner of the phone can be considered as the origin of the co-ordinate system (see image below). Again, with the phone facing you, x axis is horizontal with values increasing towards the right; y axis is the vertical with values increasing as you go from top to bottom; z axis pointing towards you with values increasing as you move from the origin towards you.
Lets do a little exercise. When the phone is lying flat, face-up on a table, what is the acceleration vector? It is (0, 0, –1). These are of course ideal values, in practice there will be slight variations because of inaccuracies in the sensor. Why is the vector (0, 0, –1)? Because when the phone is lying flat, the x and y axes are along the horizontal and there is no gravitational force acting along those axes. The z axis which is pointing upwards now, experiences a gravitational pull of 1g in the opposite direction, that explains the negative sign. Now if you pick the phone up and it is facing you the acceleration vector is (0, 1, 0). When the phone is facing you, the x and the z axes form a horizontal plane and therefore the forces are zero. y axis is pointing downwards, in the same direction as the gravitational force and so the value becomes +1. Now if you turn the phone 90 degrees in counter-clockwise direction the force vector becomes (-1, 0, 0), you should be able to figure this one out. HD2 reports the vector values after scaling them by a factor of 1000. So instead of reporting 0.984, it reports 984. Here are the values that my HD2 reports:
lying flat on a table: (X:-67, Y:84, Z:-973)
facing me: (X:74, Y:974, Z:26)
Accelerometer on HD2
From João Paulo Figueira’s post on the HTC G Sensor I came to know that someone called Scott Seligman reverse engineered the G Sensor driver and figured out how to use it. It also led to a project on Codeplex called “Windows Mobile Unified Sensor API” which provided you with a managed wrapper around various sensors in several devices. I wonder how much effort it takes to reverse engineer and figure out how to use an exported function from a dll, but I am sure it involves biting through a lot of assembly code. Anyways, the accelerometer driver in HD2 is implemented in a dll called HTCSensorSDK.dll.
If you run the dumpbin tool on this dll, c:\iamdir> dumpbin.exe /EXPORTS HTCSensorSDK.dll
you can see that it implements a few other sensors as well, like the compass and the light sensor (or proximity sensor). The functions of interest to us are HTCSensorOpen(), HTCSensorGetDataOutput() and HTCSensorClose(), which control the accelerometer and are pretty self-explanatory. Open() initializes the accelerometer sensor, GetDataOutput() returns the current (x, y, z) acceleration vector and Close() de-initializes the sensor. These functions are accessed using a combination of LoadLibrary() and GetProcAddress() apis if you want to access it through native code, or you could use the interop services and p/invokes to access it from managed code.
I modified an existing native application to access the accelerometer and there is a lot of unnecessary code in it, if you want the native app leave a comment on this post, I’ll clean it up and post it here. Meanwhile I will be posting the managed application source code here. I have tested it on HD2 and I am guessing it should work well on devices like Touch Pro 2, HTC Diamond as well.
Here’s a brief video of the sample managed application which uses the data returned by the accelerometer to move a marble on the screen. I shot two videos, one using my pathetic camera (VGA resolution) and the other using a desktop screen capture tool which records at 15fps, so you’ll have to live with these until I buy a better camera.
Microsoft released yesterday the beta version of the Windows Phone 7 development tools, which was up until now in CTP. You can download it from here. It installs Visual Studio 2010 Express, Silverlight and XNA 4.0 for Windows Phone 7, Windows Phone 7 emulator and Expression Blend 4 beta. Yep, Expression Blend now installs with the beta version and you don’t have to install it separately which is nice. The beta version breaks some of the namespaces and classes from the previous April refresh CTP release. The details about the changes can be found in the release notes here. And finally here is a post explaining how to migrate your app from the CTP to the beta release. You’ll also find two new developer tools with the new installation, Windows Phone Developer Registration and XAP deployment tool. If you’re lucky enough to get your hands on a WP7 developer device you can use this tool to unlock the device for side loading and testing your apps. XAP deployment tool allows you to directly deploy a .xap file to the emulator or a real device. You can find these tools in Start -> Programs -> Windows Phone Developer Tools
Update
Just a slight annoyance while installing the beta release. I uninstalled the CTP and then tried to install the beta and it threw an error saying ".NET Framework 4.0 multi-targeting pack is installed, uninstall it to continue", so I uninstalled it and ran the setup again, guess what it installed first, yep, .NET Framework 4.0 multi-targeting pack.
As promised in the previous post, this post will cover two variations of the marble move program. The first one, Infinite Move, keeps the marble moving towards the click point, rebounding it off the screen edges and changing its direction when the user clicks again. The second version, Finite Move, is the same as first except that the marble does not move forever. It moves towards the click point, rebounds off the screen edges and slowly comes to rest. The amount of time that it moves depends on the distance between the click point and marble.
Infinite Move
This case is simple (actually both cases are simple). In this case all we need is the direction information which is exactly what the unit vector stores. So when the user clicks, you calculate the unit vector towards the click point and then keep updating the marbles position like crazy. And, of course, there is no stop condition. There’s a little more additional code in the bounds checking conditions. Whenever the marble goes off the screen boundaries, we need to reverse its direction. Here is the code for mouse up event and UpdatePosition() method,
//stores the unit vector
double unitX = 0, unitY = 0;
double speed = 6;
//speed times the unit vector
double incrX = 0, incrY = 0;
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
double x = e.X – marble1.x;
double y = e.Y – marble1.y;
//calculate distance between click point and current marble position
double lenSqrd = x * x + y * y;
double len = Math.Sqrt(lenSqrd);
//unit vector along the same direction (from marble towards click point)
unitX = x / len;
unitY = y / len;
timer1.Enabled = true;
}
private void UpdatePosition()
{
//amount by which to increment marble position
incrX = speed * unitX;
incrY = speed * unitY;
So whenever the user clicks we calculate the unit vector along that direction and also the amount by which the marble position needs to be incremented. The speed in this case is fixed at 6. You can experiment with different values. And under bounds checking, whenever the marble position goes out of bounds along the x or y direction we reverse the direction of the unit vector along that direction. Here’s a video of it running;
Finite Move
The code for finite move is almost exactly same as that of Infinite Move, except for the difference that the speed is not fixed and there is an end condition, so the marble comes to rest after a while. Code follows,
//unit vector along the direction of click point
double unitX = 0, unitY = 0;
//reduce speed by 3% in every loop
speed = speed * 0.97f;
if ((int)speed <= 0)
{
timer1.Enabled = false;
}
}
So the only difference is that the speed is calculated as a function of length when the mouse up event occurs. Again, this can be experimented with. Bounds checking is same as before. In the update and draw cycle, we reduce the speed by 3% in every cycle. Since speed is calculated as a function of length, speed = length/12, the amount of time it takes speed to reach zero is directly proportional to length. Note that the speed is in ‘pixels per 40ms’ because the timeout value of the timer is 40ms. The readability can be improved by representing speed in ‘pixels per second’. This would require you to add some more calculations to the code, which I leave out as an exercise. Here’s a video of this second version,
In part 1 of this series we saw how we can make the marble move towards the click point, with a fixed speed. In this post we’ll see, first, how to get rid of Atan2(), sine() and cosine() in our calculations, and, second, reducing the speed of the marble as it approaches the destination, so it looks like the marble is easing into it’s final position. As I mentioned in one of the previous posts, this is achieved by making the speed of the marble a function of the distance between the marble and the destination point.
Getting rid of Atan2(), sine() and cosine()
Ok, to be fair we are not exactly getting rid of these trigonometric functions, rather, replacing one form with another. So instead of writing sin(θ), we write y/length. You see the point. So instead of using the trig functions as below,
double x = destX – marble1.x;
double y = destY – marble1.y;
//distance between destination and current position, before updating marble position
distanceSqrd = x * x + y * y;
double angle = Math.Atan2(y, x);
//Cos and Sin give us the unit vector, 6 is the value we use to magnify the unit vector along the same direction
incrX = speed * Math.Cos(angle);
incrY = speed * Math.Sin(angle);
marble1.x += incrX;
marble1.y += incrY;
we use the following,
double x = destX – marble1.x;
double y = destY – marble1.y;
//distance between destination and marble (before updating marble position)
lengthSqrd = x * x + y * y;
length = Math.Sqrt(lengthSqrd);
//unit vector along the same direction as vector(x, y)
unitX = x / length;
unitY = y / length;
so we replaced cos(θ) with x/length and sin(θ) with y/length. The result is the same.
Adding oomph to the way it moves
In the last post we had the speed of the marble fixed at 6,
double speed = 6;
to make the marble decelerate as it moves, we have to keep updating the speed of the marble in every frame such that the speed is calculated as a function of the length. So we may have, speed = length/12; ‘length’ keeps decreasing as the marble moves and so does speed. The Form1_MouseUp() function remains the same as before, here is the UpdatePosition() method,
//distance between destination and marble (after updating marble position)
x = destX – (marble1.x);
y = destY – (marble1.y);
lengthSqrdNew = x * x + y * y;
/*
* End Condition:
* 1. If there is not much difference between lengthSqrd and lengthSqrdNew
* 2. If the marble has moved more than or equal to a distance of totLenToTravel (see Form1_MouseUp)
*/
x = startPosX – marble1.x;
y = startPosY – marble1.y;
double totLenTraveledSqrd = x * x + y * y;
if ((int)totLenTraveledSqrd >= (int)totLenToTravelSqrd)
{
System.Console.WriteLine("Stopping because Total Len has been traveled");
timer1.Enabled = false;
}
else if (Math.Abs((int)lengthSqrd – (int)lengthSqrdNew) < 4)
{
System.Console.WriteLine("Stopping because no change in Old and New");
timer1.Enabled = false;
}
}
A point to note here is that, in this implementation, the marble never stops because it travelled a distance of totLenToTravelSqrd (first if condition). This happens because speed is a function of the length. During the final few frames length becomes very small and so does speed; and so the amount by which the marble shifts is quite small, and the second if condition always hits true first.
I’ll end this series with a third post. In part 3 we will cover two things, one, when the user clicks, the marble keeps moving in that direction, rebounding off the screen edges and keeps moving forever. Two, when the user clicks on the screen, the marble moves towards it, with it’s speed reducing by every frame. It doesn’t come to a halt when the destination point is reached, instead, it continues to move, rebounds off the screen edges and slowly comes to halt. The amount of time that the marble keeps moving depends on how far the user clicks from the marble. I had mentioned this second situation here.
Before you continue reading this post, a suggestion; if you haven’t read “Programming Windows Phone 7 Series” by Charles Petzold, go read it. Now. If you find 150+ pages a little too long, at least go through Chapter 5, Principles of Movement, especially the section “A Brief Review of Vectors”. This post is largely inspired from this chapter.
At this point I assume you know what vectors are, how they are represented using the pair (x, y), what a unit vector is, and given a vector how you would normalize the vector to get a unit vector.
Our task in this post is simple, a marble is drawn at a point on the screen, the user clicks at a random point on the device, say (destX, destY), and our program makes the marble move towards that point and stop when it is reached. The tricky part of this task is the word “towards”, it adds a direction to our problem, making it seem a bit, err, esoteric? Making a marble bounce around the screen is simple, all you have to do is keep incrementing the X and Y co-ordinates by a certain amount and handle the boundary conditions. Here, however, we need to find out exactly how to increment the X and Y values, so that the marble appears to move towards the point where the user clicked. And this is where vectors can be so helpful.
The code I’ll show you here is not ideal, we’ll be working with C# on Windows Mobile 6.x, so there is no built-in vector class that I can use, though I could have written one and done all the math inside the class. I think it is trivial to the actual problem that we are trying to solve and can be done pretty easily once you know what’s going on behind the scenes. In other words, this is an excuse for me being lazy.
The first approach uses the function Atan2() to solve the “towards” part of the problem. Atan2() takes a point (x, y) as input, Atan2(y, x), note that y goes first, and then it returns an angle in radians. What angle you ask. Imagine a line from the origin (0, 0), to the point (x, y). The angle which Atan2 returns is the angle the positive X-axis makes with that line, measured clockwise. The figure below makes it clear, wiki has good details about Atan2(), give it a read. Atan is short for Arc Tangent, the angle, θ, which it returns is such that, tan(θ) = y/x
The pair (x, y) also denotes a vector. A vector whose magnitude is the length of that line, which is Sqrt(x*x + y*y), and a direction θ, as measured from positive X axis clockwise. If you’ve read that chapter from Charles Petzold’s book, this much should be clear. Now Sine and Cosine of the angle θ are special. Cosine(θ) divides x by the vectors length (adjacent by hypotenuse), thus giving us a unit vector along the X direction. And Sine(θ) divides y by the vectors length (opposite by hypotenuse), thus giving us a unit vector along the Y direction. Therefore the vector represented by the pair (cos(θ), sin(θ)), is the unit vector (or normalization) of the vector (x, y). This unit vector has a length of 1 (remember sin2(θ) + cos2(θ) = 1 ?), and a direction which is the same as vector (x, y). Now if I multiply this unit vector by some amount, then I will always get a point which is a certain distance away from the origin, but, more importantly, the point will always be on that line. For example, if I multiply the unit vector with the length of the line, I get the point (x, y). Thus, all we have to do to move the marble towards our destination point, is to multiply the unit vector by a certain amount each time and draw the marble, and the marble will magically move towards the click point.
Now time for some code. The application uses a timer based frame draw method to draw the marble on the screen. The timer is disabled initially and whenever the user clicks on the screen, the timer is enabled. The callback function for the timer follows the standard Update and Draw cycle.
Form1_MouseUp() method is called when ever the user touches and releases the screen. In this function we save the click point in destX and destY, this is the destination point for the marble and we also enable the timer. We store a few more values which we will use in the UpdatePosition() method to detect when the marble has reached the destination and stop the timer. So we store the start position of the marble and the square of the total length to be travelled. I’ll leave out the term ‘sqrd’ when speaking of lengths from now on. The time out interval of the timer is set to 40ms, thus giving us a frame rate of about ~25fps. In the timer callback, we update the marble position and draw the marble. We know what DrawMarble() does, so here, we’ll only look at how UpdatePosition() is implemented;
private void UpdatePosition()
{
//the vector (x, y)
double x = destX – marble1.x;
double y = destY – marble1.y;
double incrX=0, incrY=0;
double distanceSqrd=0;
double speed = 6;
//distance between destination and current position, before updating marble position
distanceSqrd = x * x + y * y;
double angle = Math.Atan2(y, x);
//Cos and Sin give us the unit vector, 6 is the value we use to magnify the unit vector along the same direction
incrX = speed * Math.Cos(angle);
incrY = speed * Math.Sin(angle);
//distance between destination and current point, after updating marble position
x = destX – marble1.x;
y = destY – marble1.y;
double newDistanceSqrd = x * x + y * y;
//length from start point to current marble position
x = startPosX – (marble1.x);
y = startPosY – (marble1.y);
double lenTraveledSqrd = x * x + y * y;
//check for end conditions
if ((int)lenTraveledSqrd >= (int)totLenToTravelSqrd)
{
System.Console.WriteLine("Stopping because destination reached");
timer1.Enabled = false;
}
else if (Math.Abs((int)distanceSqrd – (int)newDistanceSqrd) < 4)
{
System.Console.WriteLine("Stopping because no change in Old and New position");
timer1.Enabled = false;
}
}
Ok, so in this function, first we subtract the current marble position from the destination point to give us a vector. The first three lines of the function construct this vector (x, y). The vector (x, y) has the same length as the line from (marble1.x, marble1.y) to (destX, destY) and is in the direction pointing from (marble1.x, marble1.y) to (destX, destY). Note that marble1.x and marble1.y denote the center point of the marble. Then we use Atan2() to get the angle which this vector makes with the positive X axis and use Cosine() and Sine() of that angle to get the unit vector along that same direction. We multiply this unit vector with 6, to get the values which the position of the marble should be incremented by. This variable, speed, can be experimented with and determines how fast the marble moves towards the destination. After this, we check for bounds to make sure that the marble stays within the screen limits and finally we check for the end condition and stop the timer.
The end condition has two parts to it. The first case is the normal case, where the user clicks well inside the screen. Here, we stop when the total length travelled by the marble is greater than or equal to the total length to be travelled. Simple enough. The second case is when the user clicks on the very corners of the screen. Like I said before, the values marble1.x and marble1.y denote the center point of the marble. When the user clicks on the corner, the marble moves towards the point, and after some time tries to go outside of the screen, this is when the bounds checking comes into play and corrects the marble position so that the marble stays inside the screen. In this case the marble will never travel a distance of totLenToTravelSqrd, because of the correction is its position. So here we detect the end condition when there is not much change in marbles position. I use the value 4 in the second condition above. After experimenting with a few values, 4 seemed to work okay. There is a small thing missing in the code above. In the normal case, case 1, when the update method runs for the last time, marble position over shoots the destination point. This happens because the position is incremented in steps (which are not small enough), so in this case too, we should have corrected the marble position, so that the center point of the marble sits exactly on top of the destination point. I’ll add this later and update the post.
This has been a pretty long post already, so I’ll leave you with a video of how this program looks while running. Notice in the video that the marble moves like a bot, without any grace what so ever. And that is because the speed of the marble is fixed at 6. In the next post we will see how to make the marble move a little more elegantly. And also, if Atan2(), Sine() and Cosine() are a little too much to digest, we’ll see how to achieve the same effect without using them, in the next to next post maybe. Ciao!
Came across another gem of an article by Joel Spolsky. It’s a pretty old article written in June of 2004, has lot of tidbits and I really enjoyed reading it, so much in fact that I read it twice! So hit the link below and give it a read if you haven’t already,
excerpt,
"I first heard about this from one of the developers of the hit game SimCity, who told me that there was a critical bug in his application: it used memory right after freeing it, a major no-no that happened to work OK on DOS but would not work under Windows where memory that is freed is likely to be snatched up by another running application right away. The testers on the Windows team were going through various popular applications, testing them to make sure they worked OK, but SimCity kept crashing. They reported this to the Windows developers, who disassembled SimCity, stepped through it in a debugger, found the bug, and added special code that checked if SimCity was running, and if it did, ran the memory allocator in a special mode in which you could still use memory after freeing it."
Well, yesterday night I was watching a tutorial on XNA when I came across this neat little trick. It was a simple XNA application with a Windows Phone logo in it and whenever the user clicked on the device the logo would move towards the click point, and I couldn’t resist experimenting with the marble (;
The code is written in C# using CF3.5. Here is a video of the demo,
You probably noticed the motion of the marble towards the click point (destination). The marble starts off with a high velocity and slows down as it reaches its destination. This is achieved by making the speed of the marble a function of the distance between marble’s current position and the destination, so as the marble approaches the destination point, the distance between them reduces and so does the speed, until it becomes zero.
More on the code and the logic behind it in the next post. What I’d like to do next is, instead of making the marble stop at the click point, it should continue to move beyond it, bounce around the screen a few times and eventually come to a stop after a while. Let’s see how that goes.
“Is there a way to make a default choice for the messagebox that happens after a period of time if the user doesn’t choose (Clicked ) Yes or No buttons.”
To elaborate, the requirement is to show a message box to the user with certain options to select, and if the user does not respond within a predefined time limit (say 8 seconds) then the message box must dismiss itself and select a default option. Now such a functionality is not available with the MessageBox() api, you will have to write your own custom dialog box.
Surely, creating a dialog box is quite a simple task using the DialogBox() api, and we have been creating full screen dialog boxes all the while. So how will this custom message box be any different? It’s not much different from a regular dialog box except for a few changes in its properties. First, it has a title bar but no buttons on the title bar (no ‘x’ or ‘ok’ button on the title bar), it doesn’t occupy full screen and it contains the controls that you put into it, thus justifying the title ‘custom’.
So in this post we create a custom dialog box with two buttons, ‘Black’ and ‘White’. The user is given 8 seconds to select one of those colours, if the user doesn’t make a selection in 8 seconds, the default option ‘Black’ is selected. Before going into the implementation here is a video of how the dialog box works;
Custom dialog box
To start off, add a new dialog resource into your application, size it appropriately and add whatever controls you need to the dialog. In my case, I added two static text labels and two buttons, as below;
Now we need to write up the window procedure for this dialog, here is the complete function;
}
break;
case WM_PAINT:
{
hdc = BeginPaint(hDlg, &ps);
EndPaint(hDlg, &ps);
}
break;
}
return FALSE;
}
The MSDN documentation mentions that you need to specify the flag WS_NONAVDONEBUTTON, but I got an error saying that the value could not be found, so we can ignore this for now. Next up, while calling SHInitDialog() for your custom dialog, make sure that you don’t specify SHDIF_DONEBUTTON in the dwFlags member of the SHINITDIALOG structure, this flag makes the ‘ok’ button appear on the dialog title bar. Finally, we need to call SHDoneButton() with SHDB_HIDE flag to, well, hide the Done button. The ‘Done’ button is the same as the ‘ok’ button, so this step might seem redundant, and the dialog works fine without calling SHDoneButton() too, but it’s better to stick with the documentation (; So you can see that we have followed all these steps above, under WM_INITDIALOG. We also setup a few things like a variable to keep track of the time, and setting off a one second timer.
Every time the timer fires, we receive a WM_TIMER message. We then update the static label displaying the amount of time left to the user. If 8 seconds go by without the user selecting any option, we kill the timer and end the dialog with IDC_BUTTON_BLACK_DEF. This is just a #define’d integer value, make sure it’s unique. You’ll see why this is important. If the user makes a selection, either Black or White, we kill the timer and end the dialog with the corresponding selection the user made, that is, either IDC_BUTTON_BLACK or IDC_BUTTON_WHITE.
Ok, so now our custom dialog is ready to be used. I invoke the custom dialog from a menu entry in the main window as below,
case IDM_MENU_CUSTOMDLG:
{
int ret = DialogBox(g_hInst, MAKEINTRESOURCE(IDD_CUSTOM_DIALOG), hWnd, CustomDialogProc);
switch(ret)
{
case IDC_BUTTON_BLACK_DEF:
SetWindowText(g_hStaticSelection, L"You Selected: Black (default)");
break;
case IDC_BUTTON_BLACK:
SetWindowText(g_hStaticSelection, L"You Selected: Black");
break;
case IDC_BUTTON_WHITE:
SetWindowText(g_hStaticSelection, L"You Selected: White");
break;
}
UpdateWindow(g_hStaticSelection);
}
break;
So you see why ending the dialog with the corresponding value was important, that’s what the DialogBox() api returns with. And in the main window I update a static text label to show which option was selected.
I cranked this out in about an hour, and unfortunately don’t have time for a managed C# version. That will have to be another post, if I manage to get it working that is (;