Tuesday 8 December 2009

My first Mix Tikl!

http://t1kl.me?2PJAAIAAAAAAAAdpAqAAABOSBwAAACgkCYAAAC5IDgAAAMaQaAAAAVEAAAAACoAAAAAAVAAAAAACoAAAAAAVAAAAAACpAAAAAAVIAAAAAAA==

Amazing stuff. :-)

Mixtikl 2 launch day - at last!

So here we are, Mixtikl 2 launch day.

Product launch days are always a bit hard, there is always too much to do, and we're focused for now purely on completing the web side of things.

The good news of course is that the software is stable and we're pretty happy with what we've created.

As always, we're wondering what people will think of how we've changed and extended things. Of course, Mixtikl 2 looks quite a lot different to Mixtikl 1, some aspects of the UI have changed a lot and will take some getting used to for users of Mixtikl 1.

We've featured generative content very strongly, and added what we think are some exciting new features aimed at collaboration and content sharing through text audio vectors. And, of course, we're now running on iPod/iPhone; I should think that some people will be interested to compare and contrast the experience of using Mixtikl on iPhone/iPod, compared to Windows Mobile. :)

The biggest challenges for Mixtikl have been of our own making: a continued wish to have it run on as many platforms as possible; to have Mixtikl be usable on both touchable and non-touchable devices; to introduce extensive content sharing features which build on our long experience of "vector audio"; to introduce web browser plug-in variants.

Whatever we do, we know that some people will love Mixtikl 2, others will hate it - and the struggle to create compelling generative software continues!

Life certainly would be easier if we just supported one platform and just focused on one major feature; but then Mixtikl simply wouldn't be so interesting and kaleidoscopic! :)

Pete

Friday 20 November 2009

Moving to Android NDK 1.6 from Android NDK 1.5 ...

I've updated my Android configuration to NDK 1.6, and am using the latest STLPort download.

There were a few things that changed, mainly system paths, as some posters to my blog were kind enough to point-out in earlier posts.

Here are some notes on that process, from the point of view of a cygwin-based setup under Windows. The comments generally apply to Linux/Mac as well, however.

Getting STLPort

I performed the "git" command for STLPort from within the root of the Android NDK folder, in other words from within this folder:

C:\android-ndk-1.6_r1

The command to use is this:

git clone git://umbel.mooo.com/ndk-wrappers.git

This puts the STLPort code in a slightly different place to where it was before, such that the code appears under the ndk-wrappers folder...


ndk-wrappers\stlport


... which you'll need to account for when you update the paths!

There were a couple of other things that I found tricky to get right in this transition were as follows.

env.sh

When you try running env.sh, you must do it with "source" otherwise the environment isn't updated properly. In other words, type this:

source ./env.sh


Application.mk

If your project is called "fred", then you need to have the following folder:

C:\android-ndk-1.6_r1\apps\fred

This should contain just one item, which is the Application.mk file, with the following (example!) two lines in it:

APP_PROJECT_PATH := /cygdrive/c/DOCUME~1/me/MYDOCU~1/WORKSP~1/fred
APP_MODULES := fred

libstlport.a

Once you've rebuilt STLPort, you need to copy libstlport.a (which seemed to be called libstlport.5.1.a in the previous build system... again, watch out for that!) to a new folder, which you'll need to create in the following location:

C:\android-ndk-1.6_r1\out\apps\fred\libs

The jni folder

You need to have at least two files (your source .cc file, and your Android.mk file) in the jni folder under your project, which is here in my example:

C:\Documents and Settings\me\My Documents\workspace\fred\jni

Android.mk

In my example, the Android.mk file contains this data:


LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

STLPORT_BASE := /cygdrive/c/android-ndk-1.6_r1/ndk-wrappers/stlport


LOCAL_MODULE := fred
LOCAL_CPP_EXTENSION := .cc
LOCAL_CFLAGS += -I$(STLPORT_BASE)/stlport \
-D__NEW__ \
-D__SGI_STL_INTERNAL_PAIR_H \
-DANDROID \
-DOS_ANDROID
LOCAL_SRC_FILES := fred.cc

#Static Libraries:
LOCAL_PREBUILT_LIBS := libs/libstlport.a
include $(BUILD_MULTI_PREBUILT)
LOCAL_STATIC_LIBRARIES := libs/libstlport

include $(BUILD_SHARED_LIBRARY)


Good luck!

That should be enough to get you up-and-running with NDK 1.6!

Wednesday 4 November 2009

Mixtikl 2 - coming December 8th 2009

The Mixtikl 2 release date has now been set at December 8th 2009.

Can't wait! :)

Thursday 8 October 2009

Mixtikl update

After a long push, Mixtikl 2 is now feature complete! We're now focussed on tidying-up a few loose ends, meaning that there is a good chance we'll be able to release for Mac/Win/Windows Mobile at the end of the month. We'll also submit the iPhone/iPod version to the app store at that time; that'll arrive at such time as Apple approve it!

Amongst all the other stuff we've done for Mixtikl 2, we've created Mixtikl internet browser plug-ins for Mac and Windows, meaning that you'll be able to publish your Mixes and Partikl tracks on-line. Which is pretty cool! :)

Thursday 10 September 2009

How create a new JNI / STL based project for Android

Now that I've been through the process of creating new JNI / STL-based projects for Android a few times, I thought I'd summarise the steps; as you can see, they are pretty complicated! The problem isn't down to STL; the problem is one of the basic complexity of setting up a JNI-based project (which is never easy to get started, but is fine once you're up and running!).

Note: the steps below assume you're using cygwin and Windows. You'd need to tweak them a little if you're using Mac or Linux.

1. Make sure Eclipse uses a sensible workspace folder

NOTE!! I modified my Eclipse preferences to put my files in
Documents and Settings/myname/My Documents/workspace
rather than the Eclipse default of
Documents and Settings/myname/workspace
which I find really difficult to track-down and/or backup!

2. Create a new Android Java project.

a) Create a package called com.mycompany.MyStl, with your activity class called AdaptorClass

Ensure the following code is in your ActivityClass source code...


// A native method that is implemented by the
// 'libMyStl' native library, which is packaged
public native String stringFromSTL();

// Note: remember to put-in some test code that calls the above native method!!

// this will load the 'libMyStl.so' library on application startup.
static {
System.loadLibrary("MyStl");
}


b) you must add a "libs" folder to your project: and then add an "armeabi" sub-folder in this folder.

c) Build the project (and fix any compilation errors) - but don't run it yet!

3. Create the JNI / STL project

a) Create a folder in for your project, e.g.:


C:\android-ndk-1.5_r1\apps\MyStl


b) Create a file in this folder called Application.mk, which contains the following:


APP_PROJECT_PATH := /cygdrive/c/DOCUME~1/MYNAME/MYDOCU~1/WORKSP~1/MyStl
APP_MODULES := MyStl


NOTE!! The path is a path with no spaces (as otherwise the Android NDK make system gets confused...!), and was generated using cygwin's cygpath command. You must generate and use one that suits your user, using a command similar to the following...


cygpath -dm /cygdrive/c/Documents\ and\ Settings/myname/My\ Documents/workspace


c) Make an empty folder in this folder called "project".

4. Create the JNI / STL sources, and integrate with your Android project:

a) Create a folder for your C++ source code, e.g.:


C:\android-ndk-1.5_r1\sources\MyStl


b) Create a file in this folder called Android.mk ...


LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

STLPORT_BASE := /cygdrive/c/android-ndk-1.5_r1/stlport

LOCAL_MODULE := MyStl
LOCAL_CPP_EXTENSION := .cc
LOCAL_CFLAGS += -I$(STLPORT_BASE)/stlport \
-D__NEW__ \
-D__SGI_STL_INTERNAL_PAIR_H \
-DANDROID \
-DOS_ANDROID
LOCAL_SRC_FILES := MyStl.cc

LOCAL_STATIC_LIBRARIES := /../../../../../stlport/build/lib/obj/gcc/ar/libstlport.5.1

include $(BUILD_SHARED_LIBRARY)


c) Create a file in this folder called MyStl.cc ... note the instructions that follow in d) on how to re-generate your own method prototypes...!


/*
* Class: com_mycompany_MySTL_AdaptorClass
* Method: stringFromSTL
* Signature: ()Ljava/lang/String;
*/

// Prototype - make sure it uses C-style linkage!
extern "C"
{
JNIEXPORT jstring JNICALL Java_com_mycompany_MyStl_AdaptorClass_stringFromSTL
(JNIEnv *, jobject);
};

// Implementation
JNIEXPORT jstring JNICALL Java_com_mycompany_MyStl_AdaptorClass_stringFromSTL
(JNIEnv *env, jobject)
{
std::vector lVector;
lVector.push_back("Hello from STL!");

std::string simple_string = lVector[0];

return env->NewStringUTF(simple_string.c_str());
}


d) Modify the MyStl.cc file...

The prototype and implementation shown are just examples. You MUST construct your own by doing this:


cd "/cygdrive/c/Documents and Settings/myname/My Documents/workspace/MySTL/bin"
javah -jni com.mycompany.MySTL.AdaptorClass_MySTL


Copy-out the generated prototype from the generated .h file that javah creates for your, and replace what I've shown above with the correct generated function prototype and function name.

e) Then, build the library:


cd $NDK_HOME
./env.sh
make APP=MySTL


f) The first time you've built the library, you must drag the newly constructed .so file from Windows Explorer to your armeabi folder in the project. You must then right-click on the armeabi folder in Eclipse, and select "Refresh". The library is then bundled-in to your project bundle when you next build your Android project.

5. You can now build and run your Android project!

6. If you ever modify your C++ source...

Simply re-build the library (step 4e) and then re-build and run your Android project (step 5).

7. If you need to add a new method...

You'll need to re-use javah to generate the correct prototype function signature to use. Add this to your STL project, re-make, re-build and you're done!

Tuesday 8 September 2009

Android Lists - using the ListView component

Whenever I write GUI code for a platform that is new to me, I always find myself stumped early-on figuring-out how to get simple list gadgets working. After all, most simple applications are based around buttons and lists of data. Buttons are always easy to use, but lists are always a pain.

Every platform seems to use a completely unique approach to creating lists; Android's approach is no exception in terms of how difficult it is to figure-out how to use its LiewView components. My opinion here is that the problem is down to the trend for using Model-View-Controller architectures, which actually seem to get in the way of deploying basic components like a list.

Anyways: you'll find a really useful guide to creating multi-column lists on Android here.

The steps you need to follow:
- create a new res/layout/mylayout.xml file, with the correct magic format and properties that you have to copy from what you can glean through internet searches
- use some magic code based around Adapter classes
- call the setAdapter method on your list

For those who are interested, I think the Windows API model is by *far* the easiest (using owner-draw lists); a piece of cake to use. The Apple APIs (carbon/cocoa) are hideous. The Android APIs are probably the worst.

I really wish that people who wrote APIs would concentrate on making the basic stuff easy, with lots of example code. Well done Microsoft for getting this stuff right in the first place. :)

The good news about Java development these days is support for Java Generics; I'm very happy to find that Android supports them!

Friday 28 August 2009

PC-Lint and Visual Lint

Writing software is always a challenge. When you are responsible for every line of code across multiple products and platforms, it is critical to write solid code that is as good as possible (bugs are very expensive to deal with!) :)

The free lint tools (mainly cppcheck) are OK but seem to miss lots of things compared to the professional tools, and I've been meaning to get a proper static code analysis tool for a long time now...

So: I finally took the plunge a couple of days ago, and bought a license for PC-Lint. I'd been meaning to do this for a long time, having slowly been improving my tool chain. The longer I do programming, the more I realise that it is critical to have as good a set of tools as possible, from operating system, editor, IDE, shell/scripting tools etc. ...!

Having installed PC-Lint and started to use it... I soon realise how difficult it was to use, albeit very powerful. I have never seen a tool with so many command line options, and stepping from command line output to change the code (and back again) is very difficult. So, imagine my complete relief to stumble upon Visual Lint!

For those who don't know, Visual Lint it is a GUI front-end for PC-Lint that makes it a piece of cake to use; it integrates beautifully with Visual Studio.

One thing I like about the evaluation version of Visual Lint is that it makes it very easy for you to see which features you need, so you can end-up choosing the product variant that best meets your needs. I'm guessing I'll get the Professional Edition, and am still making my mind up; but I'm certain to get a copy in a few days.

It is a shame that PC-Lint doesn't have an evaluation model. The software is certainly expensive; which is understandable, but a shame as it prevents more people improving the quality of their code.

If only there were an integrated Static Code Analysis system for XCode on Mac. It seems that the availability of PC-Lint and Visual Lint gives a major advantage to Visual Studio on Windows for cross-platform coding, as much as I love the general speed of working on the Mac. I guess I'll continue to work on the Mac, but spend a little more time now on Windows analysing the cross-platform code I've written using Visual Lint.

Wednesday 26 August 2009

auto_ptr with arrays - and a solution

It is pretty irritating that auto_ptr (a feature of C++, for those who don't know!) doesn't work with array variables.

In other words, it is not safe to do this:


int *pArray = new int[10];
auto_ptr autodel(pArray);


It is pretty easy however to create your own alternative to auto_ptr, that works with array pointers...

template <class T> class auto_ptr_array
{
public:
auto_ptr_array(T *p) :
mp(p)
{
}

~auto_ptr_array()
{
delete[] mp;
}

void reset(T *p)
{
delete []mp;
mp = p;
}

T *get()
{
return mp;
}

T* release()
{
T* lpRet = mp;
mp = NULL;
return lpRet;
}

private:
T *mp;
};


Example usage...

int main (int argc, char *argv[])
{
// Use it one of two ways...
auto_ptr_array autodel(new int[20]);
int *pval = autodel.get();

int *pval2 = new int[20];
auto_ptr_array autodel2(pval2);

printf ("Done!\n");

return 0;
}

Friday 21 August 2009

Android NDK - getting STLPort up and running

If you want to get STLPort running with the Android NDK, you'll have a bit of work to do; especially if using Cygwin under Windows.

First, visit http://umbel.mooo.com/ and get the STLPort version from John Ripley (great job, John!). If you're a cygwin user, you'll first need to remember to install the git package.

Next thing is to copy the files to a place that works for you. On my system, I copied the files into my c:\android-ndk-1.5_r1 folder, and then moved the two hello-stl folders to somewhere that seemed consistent with the other NDK files:


C:\android-ndk-1.5_r1\apps\hello-stl
C:\android-ndk-1.5_r1\sources\samples\hello-stl


I then had to change a few files before I could build the STLPort...

setup.sh

Change the top few lines to look like this:

#!/bin/bash
if uname | grep -qi linux; then
export NDK_HOST=linux-x86
elif uname | grep -qi CYGWIN; then
export NDK_HOST=windows
else

export NDK_HOST=darwin-x86
fi

Change the third line up from the bottom to look like this:


ln -sf "$NDK_DIR/build/prebuilt/${NDK_HOST}/arm-eabi-4.2.1/bin/arm-eabi-$tool" arm-linux-$tool


stlport/build/lib/android.mak

Change the TOOLCHAIN_PREFIX line to look like this:


TOOLCHAIN_PREFIX := $(NDK_DIR)/build/prebuilt/$(NDK_HOST)/arm-eabi-4.2.1/bin/arm-eabi-


sources/samples/hello-stl/Android.mk

Change the STLPORT_BASE line to be this:


STLPORT_BASE := /cygdrive/c/android-ndk-1.5_r1/stlport


Change this:


LOCAL_LDLIBS += -L$(STLPORT_BASE)/build/lib/obj/gcc/so \
-lstlport


to this:


LOCAL_STATIC_LIBRARIES := libstlport.5.1





Building STLPort

Now that the files are merged-in, you're ready to build STLPort!

Run the following in the cygwin shell... it will build the STLPort static library for you! You'll only need to do this once.


export NDK_DIR=/cygdrive/c/android-ndk-1.5-r1
cd $NDK_DIR
./env.sh
./setup.sh


Now, do this to copy the file to your project:


cp -p \
/cygdrive/c/android-ndk-1.5_r1\stlport\build\lib\obj\gcc\ar\libstlport.5.1.a \
/cygdrive/c/android-ndk-1.5_r1\out\apps\hello-stl\android-1.5-arm





Building your project's shared library

You can now go back to the cygwin shell, and do this:


cd /cygdrive/c/android-ndk-1.5_r1
make APP=hello-stl


... which will build your shared library file:

C:\android-ndk-1.5_r1\apps\hello-stl\project\libs\armeabi\libhello-stl.so


Note that this will have the static STLPort library linked-in.

Building the hello-stl project

From Eclipse, use the New Project Wizard to create a new Android project for each sample, using the "Import from Existing Source" option and import the source from c:\android-ndk-1.5_r1\apps\hello-stl\project

You can now build and run your project. The string displayed comes from the shared library, using std::string ...!

Thursday 20 August 2009

Android JNI/NDK - notes on getting started

There are a lot of steps required to get your Android development environment set-up, to a state where you can create your first Android "Hello World" app with JNI/NDK.

This is definitely not for the faint-hearted! It is complicated enough that I thought it'd be useful to run through in a blog entry.

So, here is a summary of what to do, in order to get started with using the Android software under both Mac and Windows.

1. Get the latest Sun Java SE Development Kit

Windows: You can get this from here:
http://java.sun.com/javase/downloads/index.jsp

Mac: You should already be up-to-date, assuming you have XCode installed

2. Get Eclipse

I downloaded the latest version of the "Eclipse IDE for Java Developers" from here:
http://www.eclipse.org/downloads/

Windows: Unzip, and then put a shortcut to eclipse.exe somewhere where you can find it!

Mac: Unstuff, and put Eclipse to your Applications folder.

3. Get the base Android SDK (1.5 or later!)

As we're doing to be doing NDK development, make sure you get Android 1.5 or later from here:

http://developer.android.com/sdk/index.html

Make sure you follow the appropriate instructions for installing/upgrading (depending on what current system you might already have)

Windows: When you unzip the file, make sure that it goes under the c:\ root folder... i.e. so it looks like this (for example):

c:\android-sdk-windows-1.5_r3


Mac: Put this under your home folder, so it looks like this (for example):

~/android-sdk-windows-1.5_r3


4. Windows: Get Cygwin

The cygwin toolchain is required for NDK development if you're using Windows.

So, make sure you have cygwin installed! You can get this from here:
http://www.cygwin.org
... note that you'll need the C/C++ developer tool packages.

Mac: users already have a suitable toolchain built-in through XCode.

5. Get the Android NDK

Get the latest Android NDK, from the "Native Development Tools" in the sidebar on in the sidebar on this page:
http://developer.android.com/sdk/index.html

Windows: When you unzip the files, make sure you copy them such that they are under the C:\ root folder, i.e. so that they look like this:

c:\android-ndk-1.5_r1

... if you leave them under e.g. My Documents, then the system will fail to build your source code due to spaces in the file paths etc.

Mac: Put this under your home folder, so it looks like this (for example):

~/android-ndk-1.5_r1


Make sure you follow the instructions that are in DOCS/INSTALL.TXT ...!!!

6. Windows: My Computer - path

Remember to follow instructions on setting your path variable!

Basically, append something like the following (which you'll have to change if you ever come to upgrade)


;c:\android-sdk-windows-1.5_r3;c:\android-ndk-1.5_r1


7. Create your first AVD

You can create your first AVD to be called something like my_android1.5 ... make sure you base it on the Android 1.5 SDK!

You can do this from Eclipse; and more information is available here:
http://developer.android.com/guide/developing/tools/avd.html

Test that you set-up the NDK properly

The following steps will create the following file:

out/apps/hello-jni/android-1.5-arm/libhello-jni.so


Windows:

start cygwin
cd /cygdrive/c/android-ndk-1.5_r1
make APP=hello-jni


Mac:

Run Terminal
cd ~/android-ndk-1.5_r1
make APP=hello-jni


8. Create your first basic Android Project

Now follow the instructions here:

http://developer.android.com/guide/developing/eclipse-adt.html#CreatingAProject


... and if you're lucky, it will build and run, and you can then get on with the JNI/NDK side of things!

9. Create and build/run your first NDK project

You can now create your first NDK project using JNI, and build/run it, following the steps you'll find here:

http://developer.android.com/sdk/ndk/1.5_r1/index.html#samples

Easy!

Using find with xargs in Linux/Mac/Unix/Cygwin with spaces in the file paths

I'm always having to perform searches through lots of files when on Mac/Linux/Cygwin

This is the style of command I'd normally use from the bash shell (Terminal) on Mac/Linux/Unix/Cygwin ...


find . -name "*.cpp" | xargs -- grep -i "find me" > q.q


This looks from the current folder (and all files below), searching for all files with the cpp file extension. For every file, it runs grep on it (case insensitively); putting the results of all searches in the file called q.q (which you can then edit using e.g. vim).

However, this simply doesn't work when the file or folder being searched has a space character in it. Which is annoyingly common in a files these days...

A short while back I discovered the solution to this "spaces in names/folders" problem, and I figured it'd be useful to write it up to save you the trouble...


find . -name "*.cpp" -print0 | xargs -0 -- grep -i "find me" > q.q


Note how we've added both -print0 and -0, which together magically solve the problem.

Incidentally, the -- in the argument list for xargs, is shell magic that tells xargs to ignore any options it might see after that point (e.g. the -i in the example), and simply pass them directly on to the command (grep in our example).

Tuesday 18 August 2009

Android JNI NDK - and STL support?

There is an interesting post that you can find here, which indicates that it is possible to get STL support working in C++ code that you might want to port to the Android JNI / NDK, using STLPort. Cool!

This is really interesting; I think this was the biggest issue that was blocking a port of Mixtikl to Android devices (I think I can see a way around most other issues). So, I now need to clear some time in my schedule to investigate in more detail! :)

The STLPort info page has more details, and the license looks promising; all-in-all, this is very exciting!

Friday 14 August 2009

Mixtikl ... V2!

We've put so much effort in to Mixtikl V1.5 ... and reworked so many things... that it seems to have evolved into Mixtikl V2. Right under our very eyes!

So, the release of the new version of Mixtikl is going to be quite a lot later than we planned early this year, but that is all part of the fun of designing and coding on the fly. You never know exactly where things will take you! :)

Right now we're focused on finishing off all the UI rework, and then fixing-up the bugs that the rework has (inevitably) introduced. I hope it is worth the wait!

GTK - how to enumerate widgets

I had fun recently trying to figure-out the code that would allow me to enumerate through all available GTK Widgets, a little bit like the Windows EnumWindows function. This took me a while to figure out... mainly because of the terrible state of the GTK documentation. :)

Anyways, here is the bare bones of the solution; as you can see, it is actually really easy.

A couple of things to note:
  • - a GtkWindow can be treated as a GtkWidget...!
  • - if a GtkWindow has child widgets, then it must be of type GTK_CONTAINER

static void widgetEnumerate (int nDepth, GtkWidget *pGtkWidget)
{
printf ("%d: Got GtkWidget=%x\n", nDepth, pGtkWidget);

// If the GtkWidget in question is a also a container,
// then we can enumerate through its children!
if (GTK_IS_CONTAINER(pGtkWidget)
{
GtkContainer *pGtkContainer = GTK_CONTAINER(pGtkWidget);
GList *pGtkWindowList = gtk_container_get_children(pGtkContainer);

GList *pNode;
for (pNode = pGtkWindowList; pNode != NULL; pNode = pNode->next)
{
GtkWidget *pGtkWidget = GTK_WIDGET(pNode->data);
widgetEnumerate(nDepth+1, pGtkWidget);
}
}
}

void enumerateGtkWidgets(void)
{
GList *pGtkWindowList = gtk_window_list_toplevels();
GList *pNode;
for (pNode = pGtkWindowList; pNode != NULL; pNode = pNode->next)
{
GtkWindow *pGtkWindow = GTK_WINDOW(pNode->pData);
widgetEnumerate(1, GTK_WIDGET(pGtkWindow));
}
}

Monday 10 August 2009

iPhone - problems updating the Ad-Hoc Provisioning Profile

If you get the following error in XCode after having updated your Ad-Hoc provisioning profile...

CodeSign error: a valid provisioning profile is required

... then don't panic - help is at hand - here! :)

Friday 7 August 2009

Porting from iPhone to Windows Mobile?

I found this article a couple of days back on the MSDN site - Porting the Amplitude Application from the iPhone to a Windows Mobile Device – a Case Study.

The article talks us through porting an iPhone app to Windows Mobile. This is a good idea of course - but the article decided to use C# as the language in which to completely rewrite the app for Windows mobile! This got me wondering why anybody would want to use anything other than C++ for writing applications (as much as I really like C# as a language), excepting of course those platforms where you have no choice.

The big thing about the iPhone - for me! - is that one of Apple's several great decisions was to adopt Cocoa as their platform. This means that apps are written in Objective-C ... and, if you want, you can use Objective-C++ as well. This means that all of your app code can be written in platform-neutral C++ ... with only the UI-specific code [which is based around the Cocoa Touch framework] being in Objective-C. This way, all of your non-UI code should be easy to port to any other platform that supports C++. Note: this approach assumes that you isolate and minimise your use of low-level Cocoa elements such as NSString as much as possible! This is easy to do if you use things like your own String adaptor classes, which wrap-up this platform specific stuff in a platform-neutral manner.

The nice thing about Windows Mobile is that all your code can be written in C++. So... why would you want to use a completely different language - C# in this case - as your language? Why not instead keep as much of your code as cross-platform as possible, and use C++, which is natively supported for Windows Mobile? Then you have to do much less work to port and maintain your application.

Oh well.

While doing some Android consultancy work recently, it was strange to reflect that all of the code had to be written in Java. I've got nothing against Java per se, it is just the annoying thought that all the code I wrote could not get re-used on other platforms. I can but hope that Android's NDK eventually matures to the point where we can write write most of our graphics code in C++.

As for Symbian - I won't look at that again until they base their development on a standard version of C++ with STL template support and Posix threads ... :)

Monday 27 July 2009

Building installs

I thought I'd share some of what I've learned in building installs for Windows, Mac, Windows Mobile and iPhone.

Windows: Inno Setup

This is free from http://www.jrsoftware.org/isinfo.php

Inno Setup is a marvellous tool, making it really easy to auto-build "standard looking" setup .exe files using scripts. I use cygwin bash shell to grab my latest files, build the setup .exe files and zip them up - dead easy. Spread the word!


Mac: PackageBuilder - free from Apple

Some apps are simple enough just to distribute as zipped-up Disk Images, from which the user can drag the embedded .app file to their Applications folder. However, applications that are more complex (such as Noatikl, which includes various components including Audio Unit and VSTi variants) are tougher to build installs for.

PackageBuilder is built-in to XCode, and builds good looking "Mac Standard" installs, but it is a pain to drive it automatically. I use one bash shell script to copy all the bits I need under a build folder, then I run the PackageBuilder manually using pre-prepared configuration file (can't figure-out how to run it from the command line!) (making sure I save the .pkg files into the right folder... that'll catch you out if you're not careful!) and then a second script to build the pkg file into a .dmg file, then zip it up.

Both these tools allow you to embed licenses that the user has to agree to in order to complete the install, which was important to us; in both cases, those text files can come from .rtf files so they're nicely formated!

PackageBuilder with XCode 3

If you're using XCode 3.0, and have tried to build an installer package and encountered all sorts of annoying problems that prevent it from working; don't despair.

Instead, do what I did, and copy/use intead the PackageBuilder.app from from an XCode 2.x distribution; this works, and means you can totally avoid the buggy version in XCode 3.0 ... :)

This fixes the problem where when your application gets installed, it appears in /Library/Applications rather than ~/Applications ... this is such a huge bug, I'm amazed it actually got into XCode 3 ... oh well!

Here is an outline bash script that you could use. Note the use of sudo to get around some file permission problems; basically, if the files that you work with don't have the appropriate permissions, they won't get installed properly on the target Mac.

sudo /Developer/Tools/packagemaker \
-build \
-v \
-p myprod/install/macosx/myprod_mac.pkg \
-proj imyprod/liptikl/install/macosx/myprod_mac.pmproj \
-f ./myprod_install_root \
-r ./myprod_install_root \
-i myprod/install/macosx/Info.plist \
-d myprod/install/macosx/Description.plist


The .pmproj file is prepared by you, prior to repeated running of this script, by the PackageMaker GUI tool that is in /Developer/Applications/Utilities ...

Oh, and under myprod_install_root, you first have to create separate Applications, Library etc. folders containing copies of my App, Libraries etc. that you want installed, in a folder structure mirroring how they should get installed on the target Mac.

Windows Mobile

The solution here is to build cabinet files using cabwiz (which comes with of Visual Studio). You'll need to construct all sorts of custom code in a custom setup.dll file, that does stuff such as displaying license text that the user must agree to at install time. You should also write a relatively simple launcher .exe for Windows Desktop, that allows the user to install the file directly from their Windows desktop, through the services of ActiveSync (this is a lot easier for your users, than expecting them to copy a .cab file across to their Mobile device's StartUp menu...!)

iPhone

For distribution to your ad-hoc testers, remember that you need to update the version number in version.plist every time you supply an updated build; otherwise, it'll fail to install/update on the target iPhone/iPod! Remember also that if you zip-up a .app file, it won't install properly after being unzipped on the target computer. Instead, first put the .app file in a disk image, and then compress the disk image to a zip file that you can then mail to your ad-hoc testers.

Monday 13 July 2009

File comparison and diff tools - Mac and Windows

File comparison tools are pretty critical to what I do. Most of the time, I rely on command-line diff (under Mac Terminal, or Windows Cygwin shell). But there are times when only a graphical comparison tool will do; such as recently, when I changed a vast amount of code, only to have introduced a new bug that was proving very difficult to track down. In these cases, you need to compare old and new code, one file (or folder) at a time, painstakingly looking at each change until you figure-out what went wrong.

A friend introduced me to Beyond Compare for Windows - which I liked enough to buy a license for. Great software!

However, now that I've changed my focus to do as much of my core development as possible on the Mac (avoiding Parallels where possible as it really is very slow compared to native Mac tools), I've been hunting around for a good graphical diff for Mac. And I have now found that tool - it is called Changes. Give it a try - tremendously good value, I'm very pleased to have bought a license!

Incidentally, I'm quite amazed at how much faster the shell on Mac works compared to Cygwin on Windows. I use a lot of scripting as part of my software development setup; one of the reasons to moving over to doing as much work as possible on the Mac is that the faster scripting makes a big difference to my productivity. I wonder why Cygwin is so much slower than the Mac Terminal window?

Thursday 9 July 2009

More on Android Audio

Many thanks to Jay, who was kind enough to post a comment on my previous post, saying that there is an API we can use for programmatic delivery of audio streams in Android, which you can find documented at http://developer.android.com/reference/android/media/AudioTrack.html.

Now that I know where to look :), I have found that there is also a similar API you can use to capture incoming audio on Android to memory, which is documented at http://developer.android.com/reference/android/media/AudioRecord.html.

So, that means that Intermorphic could at some point create a Noatikl/Partikl player library for Android if we wanted to, using the Android NDK (I wouldn't be surprised if this link breaks at some point...).

However, that would first require the NDK to fill-in some critical (!) gaps:
- no support for C++ exceptions (this is a show stopper for a lot of code...)
- no support for STL (this is also a show stopper...)

If any reader happens to know who to prod at Android, please get them on the case wrt the holes in their C++ support!

I suspect that the full Mixtikl user interface would be a bridge too far :) though it'd be interesting to experiment around what is possible (not that I ever have any spare time!).

Monday 6 July 2009

Android Audio?

I've been investigating Android recenly, and have downloaded the SDK and had a play with it.

And in summary, I'm quite staggered at how poor the support is for audio in the Android SDK.

You can find-out more here.

The fundamental problem is that there is no way for a program to generate its own stream of audio. All audio resources must be from a URI of some sort, or from data bundled-in to the application, or from a file in the file system.

Of course, some bright spark out there might tell me that you can easily create your own "in-app" audio server with Java that you can access through a URI from that self-same application, and that can generate an audio stream on demand; I'd love to hear if this is the case!

On another note, the audio data capture system only allows you to send data to a file; there is no way for your application to get access to the audio as it arrives. So whichever way you look at it, there is no way to create audio FX boxes for Android.

This all reminds me very much of the JSR-135 multimedia APIs for Java, which were completely useless from the perspective of a low-level audio programmer.

I'm pleased to report however that if you want to create interesting audio apps for Mobile, then your needs are well served both by the iPhone/iPod SDK, and the Windows Mobile SDK. Shame about Android though!

Wednesday 1 July 2009

More Mixtikl progress

Well, that always seems to happen. We've decided to put another round of polish on Mixtikl 1.5 for iPhone/iPod, and figure that we'll spend another 4 weeks or so on it, if our estimates are right...!

Holiday season is coming up too which is bound to affect things! :)

Monday 29 June 2009

Android NDK?

Interesting to read about the Android NDK, which is a "native" SDK for Android.

It is a shame that currently, the implementation seems somewhat flawed IMO:
- your app is written in Java and runs through the VM; you can call-out to native code libraries through JNI (which has hardly efficient!)
- no support for C++ exceptions (this is a show stopper for a lot of code...)
- no support for STL (this is also a show stopper...)

Reading the forums, the latter 2 are likely to appear some time; goodness only knows if the first restriction will ever disappear...

Friday 26 June 2009

Is the expanding mobile environment a good thing?

Thanks to a response from "Mobile" to my blog from a couple of days back, pointing out that the whole underlying market for Smartphones will continue to expand and diversify.

It seems pretty clear that most product churn seems to be of little benefit to the consumer. For example: I was pretty happy with Windows 95, and accept that Windows XP is better; but cannot see any point at all in Windows Vista. :) Companies have a need to keep re-inventing successful products, as milking a cash-cow is hugely easier than creating a new one.

For me, phones have been capable enough for most things since Windows Mobile 2002! That allowed full-featured, multi-threaded applications to be written and deployed in C++; with support out-of-the-box for full-duplex audio. With easy exchange of data through the PC using Active Sync. Devices were cheap, too.

All that was missing back then was a realisation by the market that such a device was a genuinely capable, multi-purpose mobile computer.

Since then, I can't see that Windows Mobile has moved on much (although the development tools are now better!); but then it really didn't need to change much, it has been a great platform for a long time. Symbian seems to have stood still for many years, and is stuck with a terrible variant of C++ and an awful tool chain. iPhone has opened a lot of peoples eyes, full credit to Apple for putting their toes in the water and for extending the iPod concept to include iPhone, and for pointing-out a direction for touchable UIs.

Anyways: to the heart of the problem. Now that more platforms offer similar capabilities - though iPhone has big sandboxing and connectivity issues, Android only allows Java apps, Symbian is a pig to code for and (IIRC) only allows applications to support single-duplex audio - that has served mainly to split-up the market. This gives more choice for the consumer in terms of hardware, but ironically makes it more difficult to get all the software you want on your chosen phone. Should you get a Windows Mobile device for application A, or iPhone for application B, or Symbian for application C? What if you want to change platform? Tough: you probably can't bring all your favourite apps with you. Now this might be good for the hardware developer (locking people in to their platforms), but in my opinion this is bad for the consumer.

The applications are what really define the device. You want Halo? You get an XBox. You want Zelda? You get a Wii. If you want Logic, you use a Mac. If you want Microsoft Office, you get a Windows box. Luckily now if you like Open Office, Firefox or other cross-platform tools, you have the option of running on all three main desktop platforms.

When it comes to smaller apps for mobile devices, the sort which are written by smaller developers and which really are what make a phone do what a user wants, and which are a far simpler proposition that the big apps I've just mentioned, you might think that it should surely be possible to write once, and deploy on all the platforms without too much effort? Actually no: it is unbelievably hard work, as you'll have seen from other posts on my blog.

The biggest challenge for mobile software developers, is one of writing an app such that it can reach as much of the market as possible. I can't see many ways to make this easy (apart from using a framework like the one we've painstakingly developed at Intermorphic!); this will lead to each phone platform being a separate island. I can but hope that Antix will succeeed and open up this whole market... which would also allow apps to be written once in C++, and run with binary portability on any device, including TVs, which had the application engine installed.

Thursday 25 June 2009

Sharing data between Mixtikl Windows and Mixtikl iPhone/iPod

While waiting for the skins and Tiklpaks for Mixtikl 1.5 to pull-together, I've been continuing to fill-out the outer edges of Mixtikl. I spent the past week adding-in code that allows Mixtikl on Windows to share data with Mixtikl on iPhone/iPod; this was a lot harder than I wanted, as it involved both bonjour code and the creation of a mini HTTP server, which are things you get "out of the box" with XCode for Mac/iPhone, and which are hard to implement on Windows (to say the least!). Still, the code to do the file sharing all now seems to be working and I'll spend a day or 2 more on testing/tweaking it.

I remain amazed that the iPhone SDK makes it so difficult to share data with the desktop. On Windows Mobile, you can get data on and off via your PC using Active Sync and Windows Explorer; albeit, there is no simple way to get data on/off your Mac (if you have one!) short of installing Windows on your Mac through a VM or Boot Camp. On the iPhone/iPod, your app sits there in its own island, unable to communicate even with a Mac without a large amount of code being written for both Mac and iPhone. And if you want your iPhone/iPod app to communicate with a Windows box, well you're in a world of hurt from a coding perspective.

The good news for us is that now we've done the hard work, I think we'll be able to quite easily roll-out useful utilities within Mixtikl, that will allow quite a lot useful stuff to be done on iPhone/iPod/Windows Mobile - and shared/worked-on on the PC/Mac, as best suits the needs of the user...

Thursday 18 June 2009

Windows Mobile, iPhone, Android, Palm - a look around

It is an interesing time of flux in the mobile software development market. The new version of iPhone OS released, a new version of Windows Mobile in the offing, Android phones have trickled onto the market and the Palm Pre arriving.

Intermorphic are in a pretty good position during this time of change.

The approach we've taken is to try and embrace all the key platforms - provided they support C++, Posix threads and STL. This lowest common denominator allows us develop complex software quite cost effectively. Of course, this required us to engineer our products from the beginnning to be able to reuse 95+% of our UI code, and 99+% of all other code, across all platforms we support; which is a challenge but one that was well worth the effort. That allows us to create standalone Mixtikl variants for Windows Mobile, iPhone, and Mac/Windows desktops. And even plug-in VSTi/AU variants for Mac/Win desktops!

This baseline requirement on C++ means that for now, Android and Palm webOS aren't viable target platforms for Mixtikl. The reason? Android only supports Java applications, and Palm Pre supports only JavaScript/CSS applications. However, the C++ approach does mean that a Symbian Series 60 variant of Mixtikl is possible in the future, if the Symbian SDKs ever become cost-effective to use (I remember various past problems when I last looked at Symbian, including their use of non-standard C++, no thread support, no support for STL...). The Antix platform also looks very promising, I hope it gets mass distribution so we can run on it!

It is interesting to consider how the Android and Palm platforms might succeed in terms of a 3rd party software market. From my perspective as a creator of applications for mobile, I can't see how it could be cost effective for me to invest several months (or years!) in creating a complex app for either Android or Palm, where I could spend just a little more time creating a complex app that would run on all of Windows Mobile, iPhone/iPod, Windows desktop, Mac desktop, and future platforms as yet unknown. The economies of scale seem pretty clear to me. :) I can see small games and utilities being created for the two platforms, but would be surprised to see large-scale commercial apps coming about for either of them.

Pete

Friday 12 June 2009

Mixtikl 1.5 gets closer...

Another 2 weeks on, and another 2 (or 3!) weeks of coding to go.

I've put a lot of effort over the past couple of weeks into further polishing Mixtikl on iPod/iPhone, and have also spent time improving the behaviour of Mixtikl on Windows Mobile (which has not been forgotten amongst all the iPhone work!).

There is still quite a bit of work to do on tweaking the skins for all the different Mixtikl platforms, and we've yet to finalise the Tiklpaks for release; we'll just have to see how we get on and release when we're ready!

Sunday 31 May 2009

Mixtikl iPhone release soon?

It sometimes feels like I've been working on Mixtikl for iPhone for my entire life. :)

Anyways, we've made a great deal of progress over the past months, and are now aiming to submit the app to the App Store in around 4 weeks. Knowing the way things go, we'll no doubt slip by a few weeks, but it is good to have a date to target.

As for how long it'll take to get the app actually listed on the App Store; well, we'll just have to see what happens!

We'll also be rolling-out Mixtikl 1.5 to all the other platforms at the same time. Much to do! :)

Monday 25 May 2009

Parallels 4

Last week, I help my brother configure his new Mac Book Pro. On this, we installed Parallels, so he can use Windows XP easily without rebooting from Mac; and sometimes when booted directly into Windows (mainly, for using legacy Windows Audio tools where he wanted minimum audio latency). The whole idea behind this is to help him transition to doing more work on Mac and less under Windows...

I was a bit worried about installing Parallels, having previously had real problems with it; but his installation went fine, and all seems to be working well. Actually, the performance is pretty impressive!

Things went wrong for me a while back when I had Parallels 2; using this, my Windows partition got corrupted pretty early on, so I gave up and moved to a BootCamp solution. I got the Parallels 3 upgrade when it came out, so that I could try to use my Boot Camp partition with Parallels; but this also corrupted Windows for some reason, leading to yet another re-installation and dumping of Parallels. Well, as my brothers installation of Parallels 4 had gone well, I decided to try yet again..!

I bought the upgrade from Parallels 3 to Parallels 4, and converted the BootCamp on my wife's Mac Book to use Parallels (figuring it best to try on her Mac, rather than my main development Mac!). This went well; so I took the plunge and converted my Boot Camp on my Mac Book Pro using a new (non-upgrade) Parallels 4; this also went well. Phew! :)

However... I then found that I'd installed Parallels for Boot Camp slightly wrong for my wife's machine, and had to track-down instructions on how to enable parallels for her when logged on as her (not just when logged-on as me!). The solution was a pain, and required me to change her account to be an admin account (something that is not documented in the instructions I followed...); but at least it all works now and she can do most of her work now in Mac OS!

You might wonder why I went through all this hassle. The primary reasons are that Mac OS is a lot faster to start-up, and the battery lasts longer in MacOS. I have to do a lot of development work in Mac OS and Windows; and it is a pain to have to reboot between the two; so if I can use Mac OS has my main base, and use Windows whenever I need to, then that saves me a lot of time week-by-week. In the case of my wife, she needs to use Windows for only one thing, which is some Internet Explorer magic to do access her office network. We have found that Open Office 3.1 now lets her open and edit all of her work-related documents, without the need for Microsoft Windows; and she can work the same way in both MacOS and Windows.

It seems that in the main, the tools that most people use most often are the web browser and office tools. We use Firefox for both Windows and Mac, and Open Office for both Windows and Mac; so the operating system is less relevant. This brings me back to secondary issues of speed of start-up and longer battery life; where the Mac wins.

I was also pretty impressed to find that even when booted into Mac OS, running Windows XP in the Parallels VM, I can use Visual Studio 2007 running Mixtikl in a Windows Mobile emulator, debugging real-time audio code without any audio break-up. That is partly because my Mac Book Pro is pretty fast, and also because Parallels 4 really does seem to offer great performance. I wonder when I'll next feel the need to boot-up via Boot Camp?

One more reason for using Windows XP under the Parallels VM, is that just last week I discovered the wonderful Spaces mode in Mac OS, which gives me a dead-easy to use Virtual Desktop. This works brilliantly for me, and has already transformed my development process. There is no build-in virtual windowing mode that I can see in Windows XP, which has long frustrated me... anyways, Spaces also works very well with an external monitor, and/or when using Windows via the Parallels VM. Great software!

Thursday 14 May 2009

Running iPhone UI code from other than the main thread

If you've got a relatively complex multi-threaded app, where you need to have something happen in the UI in response to an event occuring in a thread that is not the main thread, then you're going to have to be careful!

Basically, what you need to do is use performSelectorOnMainThread to execute your code that does UI work; as otherwise the UI calls you make will probably cause your iPhone app to crash!

The way to do this is to create an instance of an Objective-C++ (or C!) wrapper class that has a method on it which'll do the UI work for you (and could well have a modal loop within it, like for yesterday's post). That method could be something simple, like:


- (void)DoTheUiStuff
{
// All the UI code is here
}


Derive this class from NSObject (or maybe UIView, of course!).

You can then invoke this method through a selector, passed to your call on your class instance to performSelectorOnMainThread. When this call returns, you're safe to clean-up your wrapper class instance and get back to whatever your thread was up to in the first place...

Wednesday 13 May 2009

Running a UIAlertView modally

The funny thing about UIAlertView (and other iPhone modal interfaces), is that they don't actually run modally; in other words, you can't do something simple like this:
bool bResult = [myUIAlertView runModal];


Rather, the UIAlertView has a show method ... which shows the dialog, but which doesn't simply hang around and give you a result when done.

What you need to do in this situation, is create a delegate to handle the message generated when the UIAlertView button is pressed; and you must then provide you own modal processing loop!

Here is a simplified version of what you need to do. Spot the code loop that makes it all run modally!

// Create an instance of a custom UIAlertViewDelegate that we use to capture
// the events generated by the UIAlertView
MyUIAlertViewDelegate *lpDelegate = [[MyUIAlertViewDelegate alloc] init];

// Construct and "show" the UIAlertView (message, title, cancel, ok are all
// NSString values created earlier in your code...)
UIAlertView *lpAlertView = [[UIAlertView alloc] initWithTitle:title message:message delegate:lpDelegate cancelButtonTitle:cancel otherButtonTitles:ok,nil];

[lpAlertView show];

// Run modally!
// By the time this loop terminates, our delegate will have been called and we can
// get the result from the delegate (i.e. what button was pressed...)
while ((!lpAlertView.hidden) && (lpAlertView.superview!=nil))
{
[[NSRunLoop currentRunLoop] limitDateForMode:NSDefaultRunLoopMode];
MySleepMilli(10);
}

// Grab the result from our delegate (via a custom property)
int nResult = [lpDelegate result];

// Tidy up!
[lpAlertView release];
[lpDelegate release];


Hope that helps!

Tuesday 12 May 2009

Vim - easy to install MRU list

If you want an MRU list in your vim window for Windows/Linux (which is very useful, trust me!) then simply follow the instructions you'll find here to install a really useful Vim plug-in:

mru.vim : Plugin to manage Most Recently Used (MRU) files

This works very well with with the vims I've tried it on so far, which are gvim and cygwin vim on Windows, console-based vim and gvim on Linux, as well as console vim and MacVim on the Mac.

Even though an MRU system of sorts is already built-in to MacVim, I still recommend using this vim plug-in as it also works very well with MacVim.

Sunday 10 May 2009

iPhone Ad Hoc Distribution gotcha

Here is a good one - if you forget to update the version number in your iPhone app (through the info.plist file): and then try to install the App to your iPod/iPhone as an Ad Hod distribution, iTunes will prompt you to upgrade your app; but will actually fail to upgrade the app at all. :)

In this case, you could either first delete the app and re-install (but this would lose any app-specific data of course); or re-build with a new version number!

On another note, if you try to just zip-up your app with the Compress feature in Finder, and send that - it won't capture enough information, and will fail to install on your ad-hoc target devices. Instead, you should copy your app file to a folder, use Disk Utility to create a DMG file from that folder, and then zip-up the DMG file; and send that on to your testers. That will work. :)

Friday 8 May 2009

iPhone - clearing the Bonjour jungle

Phew: the Mixtikl file sharing code seems to be pretty much sorted out now. It has been a lot of work, but it is great to be able to have Mixtikl on the Mac share files with Mixtikl on the iPhone (in both directions!) through the local network.

I like the way that you can copy a Tiklpak from Mixtikl on your Mac, to Mixtikl on the iPhone, and use it immediately on your iPhone without having to restart. Nifty!

I can now get back to tidying-up the skin code to accomodate Tim's latest design. And when that is done: we'll be in a position to submit Mixtikl 1.5 to the App Store...

Just for the record though, if the iPhone allowed the desktop machine to connect to the iPhone, such that the desktop could read/write data into an "public" area specific to each app; that would have made everybody's lives so much easier without breaking the sandbox model.

The approach taken in Windows Mobile is much more flexible - just copy files around as you want, using Explorer and Active Sync ... though of course the fact that Mixtikl for iPhone has an integrated solution will make it really easy for Mixtikl users with a Mac. Windows users with an iPhone will not find things so easy though...

Sunday 3 May 2009

Fun with Bonjour and NSRunLoop

You know, I keep coming back to not liking much of the implementation behind Cocoa, no matter how much I use it!

Here is the sort of thing that irritates me. I create a dialog within Mixtikl (using our own internal GUI framework), and run it modally. Within that Dialog, I use Cocoa services to request to be told what Bonjour-advertised services are available. What do I get? Well, nothing, other than a call through the delegate to tell me that searching has started.

It turns out that the processing behind the scenes works only if the active NSRunLoop is allowed to do processing; so I've had to add-in a call like this in my modal loop:


[[NSRunLoop currentRunLoop] limitDateForMode:NSDefaultRunLoopMode];


So you might ask, what is wrong with this? I contend that for such processing, the system should be smarter and use an approach that doesn't require specific magic within the client code (in this case, a worker thread that does the work without my having to worry about blocking it). Otherwise, people who know a lot less than me might never be able to figure-out what they've done wrong.

Bonjour is a great idea, and is built-in to Mac/iPhone: however, I can't spot any open-source implementation that I can use for other platforms. If any reader would be kind enough to point me to such an implementation, I'd love to take a look!

Monday 27 April 2009

Objective C++ and file extensions (.m, .mm, .cpp)

If you've ever wondered how to combine C++ and C in your Cocoa code for iPhone or Mac, it is as simple as renaming your files to have a .mm extension, rather than the default .m extension.

It is a shame that Apple don't enable this file extension by default in their code building wizards. It certainly makes the transition to Objective C for C++ programmers a lot easier!

Anyways, for those of you interested in porting your C++ code across to iPhone and Cocoa, without having to rename your files or create lots of .mm file wrappers; I discovered under Linux that -x objective-c++ can be used to tell the compiler to treat the file as an objective c++ file; irrespective of the file extension... as follows (wbere test.cpp actually contains Objective-C++ syntax, and would normally be called test.mm ...):


gcc-4 -x objective-c++ test.cpp -lgcc -lobjc -o a.exe -lc -lstdc++


There are two ways to use this in XCode:
- on file-by-file basis, right-click on any .cpp file in which you want to put some Objective-C and/or C++, and select Get Info. In the Build tab, set -x objective-c++ in the Additional Compiler Flags field.
- alternatively, for the entire project, in Project Settings under Build, under GCC 4.0 - Language, set Compile Sources As to Objective-C++.

As always; this is easy when you know how...!

Pete

Saturday 25 April 2009

CFSocketCreate on iPhone

If you're doing sockets programming on your iPhone (like I'm doing for Mixtikl's file sharing server code), don't panic when your call to CFSocketCreate fails to create an IPv6 TCP socket when passing PF_INET6.

Just accept the IPv4 socket that you will get when passing-in PF_INET, and all will be fine... :)

MacVim and XCode

XCode no longer automatically launches MacVim to edit my files. However, this actually forced me to find what I think is a better solution. :)

All you need to do is open-up MacVim and XCode; and drag any files you want to edit from the XCode project window file list, on to MacVim. The file you drag-across opens automatically in a new tab for editing under MacVim. Really easy!

Even more easily: if you are editing a file in XCode, and don't want the hassle of first searching for it in the project file list in order to drag it to XCode; simply right-click on the XCode editor window, select the option to Reveal in Finder, and then right-click on the file in the Finder window and select the option to edit with Vim.app ...

Friday 24 April 2009

CGContextSelectFont - slow slow slow...

Wow, that was a shock. There I was profiling Mixtikl on the iPhone after tuning various things, and what do I find? CGContextSelectFont is hogging 30% of the CPU cycles!

This is nothing new apparently (see http://www.manton.org/2005/12/cgcontextselectfont.html - which dates from 2005!). Thanks Apple. :-(

The solution was this:
- when you grab a CGContextRef from UIView (or for example when I create my own singleton temporary one I use for off-line calculation of text display areas...), set the font just once on that CGContextRef by calling CGContextSelectFont with a temporary font size of e.g. 10; do this before you do any text drawing operations with the CGContextRef...!
- Whenever you need to draw text, call CGContextSetFontSize before you call CGContextShowText (or whatever...); do not call CGContextSelectFont as there is no need to set the font by name and size in most cases, just the font size. Calls to CGContextSetFontSize hardly take any time at all ... and your performance problems will disappear.

That makes a huge difference to performance, and is easy to do when you know how. :)

Thursday 23 April 2009

Tweaking Mixtikl on the iPhone

While Tim is fiddling-away with the new iPhone skin (there's no point in rushing him, he only ignores me anyways ... just joking Tim!), I've been spending my time tweaking the UI responsiveness of Mixtikl on the iPhone, and fixing some odd bugs left-over from the porting process.

User interface latency is really fabulous ... so much better than Windows Mobile.

Our pluggable font engine has paid dividends yet again, the effort to move text display across to iPhone was only the matter of a few hours work, as is usual for our trans-platform graphics architecture. It sometimes amazes me when things like this work so quickly, but I guess I shouldn't be surprised any more. :)

I have few other bits-and-bobs to sort out, but things are looking and sounding very good indeed...

Missing symbol with mangled name when loading a library under Linux? How to track it down.

Suffering from a missing with a mangled name when loading a library under Linux? Here is how you can track down what is missing.

I had a library failing to load...

The error output reported a "symbol lookup error" for a mangled name like _Zkasdfkadf83 ... which didn't help me much. :)

To figure-out what this is:


cd [the folder with your libraries in]
grep Zkasdfkadf83 *.so


... This tells you the library that the symbol is referred to from.
Assume this is fred.so

Then, do this. Note: the first version shows you the mangled names, the second version shows you the UNMANGLED (i.e. human readable) names... Other than that, they are identical.


nm -B fred.so > sym.mangled
nm -C fred.so > sym.unmangled


Edit both files.
Look for the missing symbol in the first file, make note of the line number.
Go to that line in the second file. That shows you the unmangled-name corresponding to the mangled name. It should now be crystal-clear what the missing symbol is!

HTH

Pete

Tuesday 21 April 2009

The power of Vim

I don't often post on tools, but I thought I'd make a mention for some fabulous new software I discovered and installed today:
- ViEmu: a Vim editor plug-in for Microsoft Visual Studio, which integrates really well within Visual Studio and is a bargain IMO ... http://www.viemu.com/index.html
- MacVim ... http://code.google.com/p/macvim/ - a wonderful version of Vim for Mac, which works quite well with XCode. And it is free!

I've been a power Vim user for many years now, having first started using vi around 20 years or so back. The key for me is that whatever programming work I have done, on every single platform (apart from VMS - shudder!) I've been able to use one vi variant or other as an ultra-productive editor.

vi and Vim have been staples of mine on Windows for ages, mainly in the context of cygwin on Windows. I've been using gvim for Windows for a long time now, and it works quite well with Visual Studio; but the ViEmu/VS is such a great integrated solution that I simply wish I'd heard about it years ago - I hate to think how many hours of programming time it would have saved me. :)

On MacOS X, I naturally use vim from the terminal window (this has been built-in to all Macs for ages). But MacVim is a great implementation, and hooks-in an awful lot better to XCode. Again, I wish that I'd installed it a long time back. It is going to save me a huge amount of time going forward.

I should note that while there are some good points about both the editors in XCode and Visual Studio, they are both staggeringly less productive to use for every day editing than Vim. When you consider the amount of cross-platform coding I do, I simply can't afford to specialise in either of these two editors. I need one common editing paradigm that rocks for all platforms. So for me, great implementations of Vim on Windows and Mac, that integrate well with Visual Studio and XCode respectively, are tremendously important.

I also spent some time today learning about some features of Vim that I simply didn't know about, that are going to transform my editing life. Visual selection modes, anybody? :)

Finally, if you're a serious programmer and haven't tried Vim - go for it. Take the pain of 2 weeks learning curve, get touch-typing and begin to feel the force. :) Vim is free, and you can get it from http://www.vim.org/ for most platforms, or within Cygwin for Windows. It is also built-in to MacOS X and Linux.

Friday 17 April 2009

Mixtikl on iPhone - dealing with chubby fingers

We're taking our time to get the iPhone version of Mixtikl "just right".

After playing around with Mixtikl on a real device, it became obvious that the general inaccuracy that you get with touch-only devices using chubby fingers :) meant that the Mixtikl skin needed to be "chunkier". This is as opposed to pointer-controllable devices like most Windows Mobile PDAs, where you can have a UI that supports smaller elements that can be selected accurately with a pointer device.

We've come up with a nice solution to this problem, and in the interim have been extending the underlying .partikl file format to take better advantage of local sample files (in Ogg and DLS format) used in the Tiklpaks. All will become clear when we release the next version of Mixtikl!

These changes are combined with other user-interface tweaks, which we think make a great deal of difference to the usability of Mixtikl across all our platforms.

We can't wait to release this new version ... but won't rush it. :)

Pete

Monday 30 March 2009

Running Mixtikl on my iPhone

At long last, Intermorphic's iPhone SDK application has been activated, we've got our certificate, and we've got Mixtikl running on my iPhone! Exciting times... :)

Sound quality is great, the UI is responsive and things are looking good. :-)

It'll be fun getting Mixtikl tidied-up for the iPhone; Tim's already created a great new iteration of the skin that we'll release first for the current platforms (Windows, Mac, and Windows Mobile). We've also been generally improving the workflow and usability of Mixtikl, and will be using the reworked Mixtikl as the basis for some neat demo videos.

We hope to be in a position to submit Mixtikl to the App Store in the next 3 months or so, but time will tell...! We certainly don't intend to release it until we're totally happy that it offers a polished iPhone experience.

Pete

Monday 16 March 2009

JavaScriptCore and iPhone

I'm really surprised that while Apple use JavaScriptCore within the iPhone platform, they don't expose it to application developers (even though it is available to Mac Desktop developers!. That seems very last century. :)

Application development can be a lot quicker when using scripting approaches, but the SDK only allows you to use scripting technologies provided by Apple. I really hope Apple expose the JavaScriptCore engine in the next update to iPhone, that should unlock a whole lot more creative Apps for the iPhone platform.

Meanwhile, we're continuing to use Lua within the Intermorphic applications for Mac/Windows desktop and Windows Mobile. I've recently been evaluating JavaScriptCore and SpiderMonkey, with a view to using JavaScipt as an alternative to Lua for our applications and engines. The reason? Mainly that a lot more people are familiar with JavaScript than Lua! Reasons not to? Mainly down to licensing pain. And Lua is a great scripting language; Lua is actually very similar to JavaScript.

Is it just me, or were the GPL licenses designed to be some kind of IP virus?

Thursday 19 February 2009

iPhone Interface Builder madness...

Hi!

I've been meaning to mention this for a while... and this has just happened to me again I guess the time is as good as any to mention it!

Basically: if you use XCode to create a New Project, based on Tab Bar Application... as soon as you try adding some items with activated UIAction responders, you're going to get an exception like this when starting the app... which is not a good thing. :)


'NSUnknownKeyException', reason: '[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key ....'


When this happens, you're the victim of a really stupid bug in Interface Builder/Cocoa.

I wonder if this sort of problem is enough to put-off novice developers from using Interface Builder... that would be a shame.

Anyways: the solution to this problem is as follows...

  1. From Interface Builder, select MainWindow.xib

  2. Within the Tab Bar Controller, select each of the two View Controller items in turn... and for each one:

    1. Press Cmd-2

    2. In the window that appears, click on the right-most button with a (i) mark on it

    3. ... and in the Class combo box, specifiy the class to be FirstViewController... (the two items are both wrongly set to be UIViewController!)

Save your XIB file, rebuild the system, and all will then work!

The above steps are explained (obliquely!) here:

Very basic problem with Tab Bar Application and Interface Builder

What surprises me is how little Apple fans complain about hideous bugs like this. :)

Pete

Sunday 25 January 2009

Back to Noatikl!


Noatikl Logo


Now that the first release of Mixtikl has settled-down nicely (with an iPhone port hopefully pending, subject to feedback from Apple), we're starting to look again at Noatikl.

The first thing to sort-out is to make it easier to use templates, and we've just updated Noatikl to version 1.5.0.15 to deal with that. It is now really, really easy to merge Noatikl pieces and templates together.

The next thing we'll be looking at is some big stuff for Noatikl 2: mainly the generative pattern editor, which is a big chunk of work, and is something that is going to take a lot of focus from us over the coming months. We might also spend some time looking at easy-to-use interfaces for the Noatikl engine for mobile. Whatever we do, we're planning on having some real fun with our generative music engine!

Sunday 11 January 2009

iPhone and Bonjour file sharing

I've finally figured-out how to share files between my iPhone running Mixtikl, and other devices connected to the local network using Wi-Fi. Though it is a lot more work that it should be. :)

The way to do it was for Mixtikl to run as a HTTP server which broadcasts it's presence using Bonjour (see Apple's CocoaHTTPServer example to get you started!), and then you can browse for and grab files from it (e.g. saved .mixtikl or .partikl files) using Safari from any browser on your network! From Safari, select Bookmarks -> Show All Bookmarks, and click on the Bonjour tab. There is a Mixtikl entry from every Mixtikl iPhone on the local network; double-click on it to show the list of files on the iPhone, and select/save the files you want to your Mac!

The other way around, you're able to use Mixtikl on the iPhone to see files advertised by Mixtikl on the Mac (which also runs a HTTP server advertised using Bonjour); Mixtikl has a special view allowing you to select the server to use, look at the file list, and select the file(s) you want to copy-across to your iPhone.

Cool stuff; welcome to the Zeroconf revolution! :)

Monday 5 January 2009

Porting Mixtikl to iPhone

I spent most of Christmas finishing-off the bulk of the remaining port of Mixtikl to iPhone, with a view to possibly releasing it if we can resolve various issues related to Apple's SDK terms.

I had planned to work on the Symbian port, but delayed that after reminding myself again of the horrors of porting any code to Symbian. :) That will wait for a few more weeks...!

Anyways, it is interesting to reflect on the iPhone porting process.

All in all, I reckon it took me around 3 to 4 weeks to port Mixtikl; which was mainly about creating an iPhone abstraction layer, with Cocoa variants for some of the code.

Not too hard, but there is some crazy stuff out there:
- you have to abandon all use of fopen() etc., and use Cocoa NSFileManager instead. If you try fopen() in the emulator, it'll try to open files in the host Mac's file system; which isn't what you want. :) opendir() etc. all have to be replaced, too.
- Mixtikl is highly threaded. I simply couldn't get the NSTimer class working properly in such a threaded system, and resorted to using Thread-based timers instead (that wasted a few days, drove me potty!).
- despite what Objective-C/Cocoa heads tell you, I found autorelease pools difficult to get my head round, easy to leak by mistake, and inefficient on occasion. IMO, if you have to learn magic rules for when you can and should release objects returned to you within the system, then the system ain't as smart as it should be. No such problems in Java. No such problems in C++! You need to remember that not all of us spend all of our time writing Objective-C, and it isn't easy to dip-into without making mistakes in this area.
If you call [object release] when you shouldn't, the system fails at some unrelated time in the future; if you fail to call [object release] when you should, the system will leak and it ain't easy to track down! Horrible.
- On a related note, avoid using NSData to hold file read/write data; use the file descriptor and low-level file-descriptor function such as read()/write() instead. Why? Well, if you're reading loads of file data, the NSData objects (which are purged by an auto-release pool) aren't actually purged until some arbitrary point later over which you have no control. This can lead to your system running out of memory as lots of auto-release objects are accumulated but not yet purged (!); leading to memory allocations failing bizarrely even when you're convinced your software should still have access to lots of memory (the memory clearly isn't available until the system purges the autorelease pool.... at some point when it feels like it!). You can avoid this simply by using file descriptors instead (from [myfile fileDescriptor]). Oh, and another reason is that file descriptor based access is a whole lot faster, as there is no unnecessary buffer allocation/releasing going on.
- you'll be amazed at how horrible image drawing is, if you're using Core Graphics like we are. Having to use transformation matrices to account for the inverted Y coordinate was not fun at all, to say the least! :(

On a separate note, the state of play wrt demo code for Apple/iPhone/Microsoft etc. remains pretty poor. When I worked at Tao Group, I put lots of effort into creating many clear, fully-working and complete demo programs that illustrated many different specific specific uses of our Audio APIs, along the lines of "what code do I need to achieve this specific effect", including playing files, playing streams, adding effects plug-ins etc. I can but presume that the reason that most companies don't do this, is that those responsible for writing the APIs aren't actually genuinely passionate about helping the people who want to use their APIs. This always leads to me wasting lots of time fiddling with poorly written demos, trying to figure-out how to actually use the various APIs...