Monday 27 August 2012

Embedding Pure Data into an iOS App

So you want to embed Pure Data into an iOS App?  This process is both very simple, and frustratingly complicated, depending on your Pure Data needs.  However you’re in luck, because I’ve run into (almost) every possible issue, and I’m counting on you, the reader, to bring any new issues to me so I can deal with those too.

Requirements

  • XCode
  • an iOS Device
  • Git

Step one: Get libPd for iOS

The first step is grabbing libPd from github.  For more information on libPD, refer to this post.  This is most easily done by cloning the the pd-for-ios repository with git.  Afterwards, follow the installation instructions on the pd-for-ios github page.
At the time of writing, these instructions are:

‘After cloning the pd-for-ios repository, please make sure to cd into the
pd-for-ios folder and say
 git submodule init
 git submodule update
These two commands install the dependencies from libpd.  After the initial
setup, say
 git pull
 git submodule update
whenever you want to sync with the GitHub repositories.’

Step two: Compile the sample projects


The first thing you’re going to want to test is whether or not you can compile the sample project.  So, open up your newly acquired test project from the repository you just cloned, which is aptly named PdTest01, and try to compile and run.  If that worked, you have my permission to give yourself a nice pat on the back before moving on.
Open up the next sample project, PdTest02.  This project has a more complicated structure because libPD is a sub-project inside of PdTest02.  This means that you can update or modify libPD as much as you want, and it’ll recompile it every time you compile the PdTest02 master project.  This is the same structure that your final iOS application should adopt.  Make sure that you select the PdTest02 scheme (pictured below), then compile and run.



Step three: Add libPd as a sub-project to your project

The next thing you'll do is add libPd as a sub-project to your own project.  I assume you've already created your project.  Open up pd-for-ios > libpd in Finder.  Here you’ll see a libpd.xcodeproj file.  Drag this file into your project explorer.  It should look something like this:


Step four: Add libPd as a dependency to your project

Now select your project from the project explorer in XCode, select your app under Targets, and select the Build Phase tab.  

Here you're going to add libPd as a dependency for your project, as well as link libPd to your project.  Expand ‘Target Dependencies’ and click ‘+’ to add the libpd-ios dependency.  Next, expand ‘Link With Libraries’ and click ‘+’ to add libpd-ios.a to link the library with your app.  When you're done, it should look something like this:


 Now when you compile your project, it will compile libpd-ios first and embed the library into your compiled project.

Step five: Compile and party!

Hurray! You’ve successfully embeded Pure Data into your iOS app.  Unfortunately this is only half the battle.  There are two significant issues left to address.

How do I use libPd?

I recommend you explore the sample projects to get an idea of how to use libPd.  This will show you how to initialize Pure Data and open a PD patch.  Also, PdTest02 shows the user how to setup the AppDelegate as a PdReceiverDelegate.  This will allow you to receive messages from PD.  If you want to learn more about interacting with libPd, explore the libPd source, with PdBase being especially useful.

How do I add extras?

Vanilla Pure Data contains as few objects as possible to run.  This applies to libPd as well.  As a result, libPd is as lean as possible, which makes it perfect for embedding.  However most (all) Pure Data programmers use objects that aren’t part of Vanilla PD/libPd.  The good news is that libPD supports these objects.  The bad news is this can be a huge source of frustration.


PD Objects come in two formats: .PD files and .c files.

.Pd Files

FX is an audio programmer I work with.  FX uses Pd-Extended to create patches.  Pd-Extended contains a lot of extra objects that FX depends on, for example tof/sample_granule~ and tof/sample_play~.  In order to accommodate FX, I had to add these objects to libPd, and here’s how.

First, download and install the Pd-Extended application from the Pure Data website.  Right-click the app, and select “Show Package Contents”.  Under Contents > Resources you’ll find a folder called extra.  This is where all the fancy “Extended” objects are hiding.  

Now copy the “tof” folder (or whatever objects you’re looking for) into your project folder.  Pure Data expects a certain folder structure.  What this means is when you create a “tof/sample_play~” object in your PD patch, it expects “sample_play~” to be contained in the folder “tof”.  However, by default when you create an iOS app, all your resources get dumped into the resources directory, and don’t retain any folder structure.  To get around this, when you drag the “tof” folder into your project explorer in XCode, select the option “Create folder references for any added folders”.  

Congratulations! You can now use all the tof objects with your embedded libPd application. (Note: I haven’t been able to make sample_shifft~ work, if anybody has any information on this, please let me know).

.c Files

C extras are easy to add.  Simply add the desired c files into your project, this can be done by dragging and dropping them into your project explorer in XCode, preferably into a group with a descriptive name like libpd extras.  

Next you’re going to initialize the new object before you use it.  Let’s pretend you’re trying to add the object lrshift~.  Every pd object has a setup function called [name_of_object]_setup().  For example, lrshift~ has a setup function lrshift_tilde_setup().  You’re going to call this function when you initialize Pure Data, however you have to tell the compiler that it exists first.  Open your AppDelegate.m file, and somewhere before your function definitions add extern void lrshift_tilde_setup(void);.  Now, before you initialize pure data, call lrshift_tilde_setup();.  Do this for any other c objects that you’re using.

Note about extras

I’ve noticed that Pure Data sometimes expects these objects to be contained in a folder.  For example, the PD file may have a line that says “cyclone/lrshift~”.  The problem is that any extras added to libPd with this method essentially become one with the base Pd library, so Pd will fail to initialize them.  To fix this, I simply run a search and replace on all my PD files, and replace any offending lines.  For example “cyclone/lrshift~” becomes “lrshift~”.  I recognize that this may not be the most convenient method and I’m listening for suggestions on how to fix it.

Where do I find extras?

All the extra objects included in PD-Extended can be found in the PD-Extended app.  To find them, download and install Pd-Extended.  Right-click on the app, and select “Show Package Contents”.  Under Contents > Resources there’s a folder called “extra”.  This is where all the extended objects are hiding.

1 comment: