In this tutorial we are going to take an existing ObjC application and add Python and PyObjC to it. One of the reasons why you may want to do this is because some things are much simpler in Python than in ObjC, mainly due to the rich library Python has.
To follow the tutorial you need:
- PyObjC 1.3.1
- py2app 0.2 or later (included in the binary installer for PyObjC)
- Python 2.3 or later (note: PyObjC is NOT compatible with MacPython-OS9)
- Mac OS X 10.3 or later
- Xcode Tools
If you do not have a /Developer
folder, then you do not have Xcode Tools
installed. See Getting the Xcode Tools.
The application we are going to modify is Apple's SimpleComboBox example. This example shows you how to use combo boxes, but that is not what interests us right now: the application pretends to be a database application that allows you to keep notes (such as track list) for your CD collection. With such an application it feels silly that even though you want to type notes on the CD you are currently playing in iTunes you still have to retype album title, artist and genre. This is what we are going to fix: we are going to add a button "ask iTunes", which will use Python's AppleScript support to ask iTunes about the currently playing track and fill in the fields for you.
Follow these steps:
/Developer/Examples/AppKit/SimpleComboBox
to work on.
Let's call this SimpleComboBoxPlus
:$ cp -R /Developer/Examples/AppKit/SimpleComboBox SimpleComboBoxPlus
From this point on, all shell commands take place from this
SimpleComboBoxPlus
folder.
CDInfoDocument.nib
. Select the Class View, NSObject
, subclass
as ITunesCommunication
. Give the class an askITunes:
action.
Instantiate the class as object ITunesCommunication
. This wll be the
class that we write in Python.askITunes:
action of the
ITunesCommunication
object.ITunesCommunication
src/ITunesCommunication_1.py
to ITunesCommunication.py
.setup.py
with the following contents:from distutils.core import setup import py2app setup( plugin = ['ITunesCommunication.py'] )
You may also copy this file from src/setup.py
.
$ python setup.py py2app -A
Note that we use the -A
argument to create an alias plugin bundle at
dist/ITunesCommunication.py
. Alias bundles contain an alias to the
main script (ITunesCommunication.py
) and symlinks to the data files
(none in this case). This allows us to keep working on the source files
without having to rebuild the application. This alias bundle is similar
to a ZeroLink executable in Xcode - it is for DEVELOPMENT ONLY, and will
not work on other machines.
dist/ITunesCommunication.plugin
to the Resources folder in your
Xcode project. You can do this by ctrl-clicking the Resources folder
and choosing "Add Existing Files...". Make sure to choose
"Create Folder References for any added folders".main.m
, it is in the "Other Sources" folder in your Xcode
project, and change the main(...) function to the following:int main(int argc, const char *argv[]) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSString *pluginPath = [[NSBundle mainBundle] pathForResource:@"ITunesCommunication" ofType:@"plugin"]; NSBundle *pluginBundle = [NSBundle bundleWithPath:pluginPath]; [pluginBundle load]; [pool release]; return NSApplicationMain(argc, argv); }
You may also copy a full main.m from src/main.m
. This code ensures
that our ITunesCommunication plugin is loaded before the nib
files.
iTunes.app
. This leads to the following hefty command line
which you should run in the SimpleComboBoxPlus
directory:$ cd SimpleComboBoxPlus $ pythonw -c "from gensuitemodule import main;main()" \ --output iTunes --creator hook --resource \ /Applications/iTunes.app/Contents/Resources/iTunes.rsrc
ITunesCommunication.py
to actually communicate
with iTunes. We cop out and copy it from src/ITunesCommunication_2.py
.$ rm -rf dist $ python setup.py py2app
Then, from Xcode, clean your project (shift-cmd-K), switch to Deployment mode, and rebuild.
There a several projects that improve upon the built-in AppleScript support (or to be more precise "application scripting support"). One of those is AppScript.
When you have this module installed you can replace the contents of
ITunesCommuncation.py
with src/ITunesCommunication_AppScript.py
,
and you can skip step 13 entirely.