Cool thing of the Week: Week 8

21. March 2012

 

 

Hey, I’m on time this time! Well, almost…

 

 

This weeks cool thing is in an area where there aren’t too many options, audio capture and manipulation tools.  On the “pro” side, the dominant player is probably Pro-Tools, which is in a word expensive.  With pricing starting at 700$ and going up from there, it is out of the reach of many peoples budget.  Truth of the matter is, it’s probably overkill for most people too.

 

 

In the mid range you have other, slightly cheaper options such as Adobe's SoundBooth or if you are the Mac type, Apple’s Logic Pro.  Both of these apps sell for about 200$.  If you’ve noticed one thing about me though, it’s I like free stuff, I really like free stuff.

 

 

Thankfully there is a free option, and it’s pretty damned good.  This weeks CTofW is Audacity.  In addition to being a rather clever pun, it is also a “free, open source, cross-platform software for recording and editing sounds.  It is available on Windows, Linux and Mac. 

 

 

Audacity in action editing a Wav file:

image

 

 

As is pretty typical of open-source projects, it’s a bit on the ugly side, although compared to it’s open-source peers, it is the belle of the ball.  However, unlike most open sourced projects, it’s incredibly well documented.  In addition to the included documentation, there are actually a few published books including Getting Started with Audacity 1.3 and The book of Audacity.  It’s a good thing too, even though Audacity is pretty simple to get started with, it’s an amazingly deep program.  The short form description for their site goes as follows:

 

You can use Audacity to:

  • Record live audio.
  • Convert tapes and records into digital recordings or CDs.
  • Edit Ogg Vorbis, MP3, WAV or AIFF sound files.
  • Cut, copy, splice or mix sounds together.
  • Change the speed or pitch of a recording.
  • And more!

 

 

 

Instead of going into depth here about what this program can do, I’ll refer you to their feature list.  And I promise you, that list just scratches the surface.

 

 

So, if you are looking for a audio capture and manipulation application and are doing things on a budget, you really can’t do better than Audacity.  Seeing as it’s free and only a 20MB download, what have you got to lose?

Cool Thing of the Week




Adventures in Appcelerator part two

20. March 2012

 

 

As you might have noticed from my previous post I am currently evaluating Appcelerator and I have to say, the early frustrations are far too common.  In the future I may do a full review, if I don’t give up on it completely.  For now though, let me share a few of the issues I’ve run into, beyond the one described in the previous post.

 

 

Failed to find Javac.

I got an error the first time I tried to compile my code, stating that it failed to find javac. So I opened a command prompt, CD to %JAVA_HOME% and there it is.  WTF?  Some Googling later and I discover it doesn’t support file paths with spaces!  Seriously?  What, is this 1994?  Moved Java to c:\jdk and problem went away.  Seriously, when was the last time you ran into an app that didn’t support spaces?

 

 

Blackberry Support

A big part of why I chose Appcelerator in the first place is support for iOS, Android AND Blackberry, as I have all three tablets in my house.  I go to make a Mobile application in Appcelerator and Blackberry is grayed out.  I click through to a “Get SDK” link, download 500mb of Blackberry stuff, restart Appcelerator Studio and… Blackberry is still grayed out.  Turns out this is a “pro only” feature…  and that’s only discovered by reading a forum post, their own documentation says nothing of the sort!  Disappointing, not only that it’s a premium feature, but because they didn’t indicate this anywhere, the UI suggests otherwise, causing me to waste a couple hours of my life.

 

 

Android device support

So, native blackberry support isnt a huge deal, now that you can bundle Android apps as Blackberry Playbook apps, so I continue on targeting just Android.  I configure and setup the Android SDK, create a demo app, launch it on by Transformer, all good so far.  So I set a breakpoint, hit debug and…….. the emulator launches.  If you’ve done any Android development, you know using this emulator is somewhere between an 8 and 9 out of 10 on the “Things that hurt” scale.  It is sloooooooooooooooow.  But get this, Appcelerator can’t debug on device, emulator only.   This.  Sucks.  Hard.

 

 

 

 

So, let’s just say, after two days I am extremely unimpressed, and I haven’t even got around to coding yet!

 

 

Anyone out there have prior experience with Appcelerator?  Am I just hitting all the bad stuff up front, or is this what I should expect as the norm?

General




Installing Titanium Appcelerator Studio to work with blackberry… gotchas

17. March 2012

 

 

 

So I have decided to give Appcelerator Titanium a shot for a cross platform mobile project I am working on.  If you are previously unaware of Appcelerator, it is basically a cross platform framework where you program in Javascript and can natively target a number of mobile devices including Android, iOS or in this case Blackberry.  That said, the IDE is based on Eclipse, so that means I am going to develop a number of new pains in my backside.   Lo and behold, I wasn’t wrong.

 

 

Installed the app, went to make a project and BLAMMO, hit the first wall.  Apparently you need to install the Android and Blackberry SDKs.  This of itself is no big shock, the problem arises when you try to install the Blackberry Java SDK which as you can see, you can either download as a pre-configured Eclipse install, or you have to use the Eclipse Updater.  As my Eclipse install is Titanium itself, I obviously have to go the updater route.  Fortunately, Appcelerator already has the Blackberry updater site configured, but then I hit the wall.

 

 

 

You select Help->Install New Software… select the Blackberry Update Site, then select the Blackberry Plugin, like so:

 

image

 

 

Of course, this is Eclipse we are talking about, so of course it isn’t going to work, throwing up the following error:

 

Cannot complete the install because one or more required items could not be found.
  Software being installed: BlackBerry Java Plug-in (core) 1.5.0.201112201607 (net.rim.EclipseJDE.feature.group 1.5.0.201112201607)
  Missing requirement: BlackBerry Java Plug-in (core) 1.5.0.201112201607 (net.rim.EclipseJDE.feature.group 1.5.0.201112201607) requires 'org.eclipse.jdt.debug.ui 0.0.0' but it could not be found

 

 

Oh joy.  Off to Google I go!  Sadly, I didn’t find an answer, but a few minutes later I puzzled it out myself.  If you are using Titanium Studio and run into dependency errors like this, there are a few things you need to change to fix it.

 

 

In the Available Software dialog, click the “Available Software Sites” link:

 

image

 

 

Check the box beside Eclipse Update site like below:

 

image

 

 

This will give you access to all the various Eclipse updates.  Finally back on the updates screen, you want to verify that the “Contact all update sites during install” checkbox is checked:

 

image

 

 

 

With this change, the Blackberry SDK install will be able to resolve it’s dependencies and complete the install.

 

 

 

 

It’s a small thing, but if you are just starting out with Eclipse, this is the kinda showstopper garbage that make me hate recommending this tool.

General




Network programming with SFML and Node.js: Part 3

14. March 2012

 

 

In part 1 we look at a very basic example of sending information across the wire from SFML to NodeJS.  In part 2 we looked at JSON encoding high score data, that is then sent via UDP socket to a Node server.  Now we complete the process, by having Node return high score data back to your C++ SFML app.  By the end of this section, you will have all the code you need for a functioning ( if somewhat fragile ) high score client and server.

 

 

First we look at the C++ code.  Things are very similar to part 2, except code has been refactored a bit for re-use.  Lets look now.

 

 

#include "SFML/Network.hpp" #include "JSON.h" #include <iostream> void MakePacket(const wchar_t* action, const wchar_t * name, const float score, sf::Packet &packet) { JSONObject data; data[L"action"] = new JSONValue(action); data[L"name"] = new JSONValue(name); data[L"score"] = new JSONValue(score); JSONValue * val = new JSONValue(data); data.clear(); std::wstring dataString = val->Stringify(); delete val; std::string notSoWide; notSoWide.assign(dataString.begin(),dataString.end()); packet.Append(notSoWide.c_str(),notSoWide.length()); } int main(int argc, char* argv[]) { sf::IPAddress ip("127.0.0.1"); sf::SocketUDP socket; sf::Packet packet; unsigned short port = 1000; unsigned short respPort = 1001; if(argc == 1) { //No arguments means program should retrieve scores and print them MakePacket(L"GetScores",L"",0.0f,packet); socket.Bind(respPort); socket.Send(packet,ip,port); char buffer[512]; // The buffer to store raw response data in sf::IPAddress respIP; // The ip address where the response came from size_t respSize; // The amount of data actually written to buffer // Now receive a response. This is a blocking call, meaning your program // will hang until a response is received. socket.Receive(buffer,512,respSize,respIP,port); socket.Close(); std::string respString(buffer,respSize); // Now lets turn the string back into JSON JSONValue * jsonHighScores = JSON::Parse(respString.c_str()); if(!jsonHighScores->IsObject()) { std::cout << "Something went wrong, not good."; return -1; } JSONObject root = jsonHighScores->AsObject(); if(root.find(L"Scores") != root.end() && root[L"Scores"]->IsArray()) { JSONArray scores = root[L"Scores"]->AsArray(); std::cout << "Current high scores:" << std::endl; for(int i = 0; i < scores.size();i++) { JSONObject curObj = scores[i]->AsObject(); std::wcout << "Name:" << curObj[L"Name"]->AsString(); std::cout << " High Score:" << curObj[L"Score"]->AsNumber() << std::endl; } } delete jsonHighScores; } else if(argc == 3) { MakePacket(L"AddScore", std::wstring(argv[1],argv[1] + strlen(argv[1])).c_str(), atof(argv[2]), packet); if(socket.Send(packet,ip,port) != sf::Socket::Done) { std::cout << "An error ocurred sending packet" << std::endl; } socket.Close(); } else { std::cout << "Invalid usage, proper format is player name then score, for example:" << std::endl; std::cout << "Or run with no arguments to get a list of scores returned" << std::endl; std::cout << "Scoreboard \"Player Name\" 42" << std::endl; return -1; } return 0; }

Click here to download Scoreboard.cpp

 

 

We have reorganized slightly to use a set of if/else’s based on the number of parameters passed in.  The common code between the two handled conditions has been moved to the method MakePacket(), which contains nothing new from last part.  It’s the section where argc == 1 ( which means there were no parameters specified, as argc at 1 represents the executables name ) that we are interested in.  If the user runs the application from the command line with no parameters, we want to fetch the high scores from the server.

 

 

The request process is the same, although we are passing the action GetScores instead.  One key difference is we Bind our port.  Think of this action as say “Yo!  This port is ours!”.  Only one application per computer can have access to a given port.  This is why we run our server on 1000, but then bind our response port on 1001, since client and server on running on the same machine.  Unlike when we add a score, for GetScores we want to listen for a response, which is what we do with socket.Receive().  Keep in mind, this action blocks, so your program wont be able to continue until this is done.  There are alternatives ( like Selector ) if this behavior is undesirable.

 

 

Now assuming Receive() worked correctly ( which in the Real World™ you shouldn’t!), buffer will be full of our JSON encoded string, while respSize will represent the amount of buffer that was actually used.  Using these two pieces of information, lets create a string from only the meaningful bits ( the rest of the buffer will be full of gibberish ).  We now turn our string back into JSON ( in production code, I would extend the JSON library to work with standard strings ), and check to see if it is a valid JSON object, error out if it’s not.  Now it’s a matter of parsing out the JSON into meaningful form.  Remember that a JSONObject is actually just a STL map of key/value pairs, so we find our array of type JSONArray named Scores.  Each item in that array is in turn another map, so we loop through them all find the value for “Name” and “Score”, turn them back into their native type and display them out to the console.  And that’s about it.

 

 

Now lets take a look at the server side of things.  Here we made much less invasive changes, so lets just look at what has changed.  To see the fully modified server.js click here.  I no doubt forgot a small change here or there, I always do!

 

 

First we add another condition to the switch statement as follows:

 

case "GetScores": console.log("Get Scores called"); // Turn highscores back into a JSON encoded string var highScoreAsString = JSON.stringify(highScores); // Create a buffer to hold that string var responseBuffer = new Buffer(highScoreAsString.length); // Write the string to the buffer responseBuffer.write(highScoreAsString); // Send it back to the client, using the addressing information // passed in via rinfo server.send(responseBuffer,0,responseBuffer.length, rinfo.port,rinfo.address, function(err, sent){ if(err) console.log("Error sending response"); else console.log("Responded to client at " + rinfo.address + ":" + rinfo.port ); }); break;

 

 

The code is pretty much documented, the nutshell version is, we turn our high score information into a JSON encoded string, make a buffer large enough for the string, copy the string to the buffer, then call send to the address and port the request came from, as defined in rinfo.

 

 

Then, mostly because we can, we use Node to create an extremely simple high score web server, so if you visit this site with your browser you can get a current list of high scores.  Look how laughably easy that task is!

 

 

// Now, lets show off a bit, with the worlds simplest web server. // Dynamically creates webpage showing current high scores. var webServer = require('http'); webServer.createServer(function(req,res){ res.writeHead(200, {'Content-Type': 'text/html'}); res.write("<html><body><h1>High Scores</h1><ul>"); for(i=0;i < highScores.Scores.length;++i) { res.write(highScores.Scores[i].Name + "&nbsp;&nbsp;" + highScores.Scores[i].Score + "<br />"); } res.write("</ul></body></html>"); res.end(); }).listen(80);

 

 

 

And… that’s it!  So now, lets take a look at things in action.  Open a command prompt and launch your server.js in node.  Then in another command prompt run scoreboard.exe, like this:

 

 

Here is using Scoreboard from the command line:

image

 

 

And here is the server handling these requests:

 

image

 

 

Finally, fire up a web browser and hit 127.0.0.1 ( assuming you don’t have another webserver running on your machine ):

 

image

 

 

It ain’t pretty, but it is a fully functioning high score server.  All you need to do is add a layer of security, harden things a bit with an iota of fault tolerance, pretty things up a bit and you are set.

 

 

As always, you can download the complete project zip here.

Programming ,




Building a SFML 1.6 project in release mode

9. March 2012

 EDIT: DO not use the included binaries, instead look at the link from the Pang tutorial series to your right!

 

I have gotten a few emails or messages on this topic, enough so that I figure I will put together a post on the subject.  In my PANG! SFML C++ game tutorial, I show how to configure for debug builds but not release.

 

 

So, first and foremost, you are going to need to compile SFML 1.6 for release mode if you don’t already have the release libraries.  You can either download the SFML 1.6  source code here and compile them for release, in either DLL or static mode.  To do so, in Visual Studio 2010 after importing the project ( from SFML-1.6\build\vc2008 ) go ahead and delete the samples folder in the Solution Explorer. Then select the Build Menu, go to the Configuration Manager, then select the build you want to make:

 

Untitled

 

 

You either want to build Release DLL or Release Static, depending on if you are compiling static or dynamic.  If that is completely alien to you what the difference is, dynamic means you will ship the SFML Dll’s with your application, which will contain the SFML related code.  Static on the other hand, will compile all of the SFML related code into your EXE file, making it quite large but easier to distribute.  Either works, but if you ran into the dreaded ATI bug, static fixes it.  On the other hand, if you don’t use all parts of the SFML library, dynamic can be a whole lot smaller.

 

 

If you can’t be bothered building the DLLs, I have compiled them for you.  This archive contains the .lib/dll files for both static and dll versions of SFML compiled for Visual Studio 2010.

 

 

Now that you have the proper lib and dll files, the instructions are basically identical to this part of the tutorial.   The only thing you have to do different is, when in your projects properties before adding libraries, you need to select Release Build.

 

image

 

 

Also, when you specify the library names, you do not include –d at the end.  So for example, instead of adding sfml-system-d.lib, you add sfml-system.lib.  Repeat this for each library.

 

Now you should be able to build the release version of your game without problem.  This again is accomplished using Build->Configuration Manager, like so:

 

image

 

 

Simply switch to release rebuild and done.

Programming