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! :)