Archive for PyObjC

Elementary Bluetooth using PyObjC

Bluetooth connectivity to devices is supported on Mac OS X using Cocoa APIs, so is possible to access from Python. Bluetooth itself opens up a large body of knowledge that I am only starting to investigate.

This article outlines some basics for using Bluetooth in Python.

Bluetooth access is achieved through two frameworks, IOBluetooth and IOBluetoothUI. Neither of these are included in PyObjC by default, so a basic wrapper class makes life easier. (see the PyObjC docs)

Add the following to IOBluetooth.py:


import objc as _objc

_objc.loadBundle('IOBluetooth', globals(),
  bundle_path=u'/System/Library/Frameworks/IOBluetooth.framework')

The loadBundle pattern is very useful, and allows the classes from any Objective C framework to be loaded into the PyObjC bridge. By putting it into a separate Python module, usage becomes less painful.

For example, the most recent device is:


>>> from IOBluetooth import *
>>> devs = IOBluetoothDevice.recentDevices_(1)
>>> devs[0].getNameOrAddress()
u'gmwils 6600'
>>> devs[0].isConnected()
1
>>>

In this case, my Nokia 6600 is still connected in AddressBook.

To create a new connection to a device, Apple provides access to their user interface for Bluetooth management. It is strongly recommended that these controls are used to provide consistency for the user and detailed error handling.

For example, selecting a service from a device with a dialog:


>>> from IOBluetoothUI import *
>>> browser = IOBluetoothServiceBrowserController.serviceBrowserController_(0)
>>> browser.runModal()
-1000
>>> results = browser.getResults()
>>> results[0].getServiceName()
u'Bluetooth Serial Port'
>>>

Note: you will need a IOBluetoothUI wrapper, similar to the IOBluetooth wrapper from earlier.

Useful documentation links:

Birthday Notes

Birthday Notes is an application with two purposes. On one hand it provides an easy way to keep track of people’s birthdays on Mac OS X. The other role it plays is to learn Cocoa programming using Python, Cocoa and PyObjC.

Why bother with yet another birthday tracking tool? Quite simply, most were too difficult to get the information that I wanted. The main aim of Birthday Notes is to provide a list of upcoming birthdays with relevant information.

For example, I rarely think of people’s birthdays in terms of their birth date (eg 1977-08-04). My brain is wired so that I remember that my birthday is on the 4th of August and that I’m currently 28 and turning 29 on my next birthday. Rather than show the birth date, Birthday Notes shows the birthday and the person’s age they turn on that day.

Birthday Notes features integration to Apple’s existing applications for storing data. This means that iSync support comes for free. The current focus is on a maintenance and reporting tool, so you can edit a person’s birthday from within Birthday Notes, but not create or delete. For additional actions, simply double click on the person’s name - they will be revealed in AddressBook.

I like to know some trivia about people’s birthdays, so Birthday Notes includes a bit of useless astrological information.

Birthday Notes is available for download. Requires OS X 10.4 or greater.

Any thoughts, suggestions, bugs or feedback should be sent to gmwils AT pseudofish.com, or posted in comments on this post.

For those interested in the code, it is available under a GPL license. To compile, Python 2.4, a recent build of PyObjC, and icalendar are needed.

Finally, my thanks to those who have been helping with alpha testing. This release marks the start of a public beta.

PyGame on Mac OS X with PyOpenGL

As a result of Richard Jones’s talk at OSDC2005, I decided to install PyGame to play around with.

The demos in the talk were slick, even to the point where PyGame was used as the presentation tool. Much more dynamic than PowerPoint.

Unfortunately, install is where a bit of trouble started. There didn’t seem to be a simple explanation as to how to get it functioning on my Mac. The presentation was great, and on a Mac…

Must be possible!

As with most of these things, the joy is in going down blind alleys, banging your head against (several) walls and making discoveries. The only way to truly learn something. Unfortunately, the pain can’t be totally avoided. Without it, there were no mistakes. No mistakes lead to no need to learn. Or so I kept telling myself.

After several rounds with the wall at the end of the alley, some libraries I built. Some refused to build. Some I later discovered binary packages for.

I’ve included a bunch of links below that point to the required packages. It should be relatively easy to grab everything and have a working PyGame installation.

  1. Python 2.4
  2. PyObjC
  3. Python Numeric
  4. Python Image Library (PIL)
  5. SDL - C library for user handling
  6. SDL_ttf - C library for TrueType fonts
  7. SDL_image - C library for image handling
  8. SDL_mixer - C library for sound
  9. SMPEG - C based Mpeg and MP3 library. (Checkout smpeg from CVS; autoconf; automake; ./configure; make; create framework. )
  10. PyGame
  11. PySDL is now in PyGame - Python binding for SDL

Optional packages:

  1. PyOpenGL - OpenGL bindings for Python
  2. FreeType - TrueType font library, listed as a dependency of SDL_ttf but I have no issues without it (yet?).

If it helps, my /Library/Frameworks looks like:


% ls -d [Ss][^t]* Python.framework
Python.framework/       SDL_mixer.framework/
SDL.framework/          SDL_ttf.framework/
SDL_image.framework/    smpeg.framework/

Useful things are now available in /Developer/Python/pygame, with /Developer/Python/pygame/Examples providing a bunch of examples to test your installation.

A very big grin spread over my face watching the cube rotate from typing:


% python /Developer/Python/pygame/Examples/glcube.py

Application behaviour on last window close

I grew up with Microsoft’s various windowing systems, and learnt the X Windows style of things while at Uni. When I first used a Mac, Apple’s approach of keeping the application alive after its windows are closed felt strange.

Now, having used OS X from early beta stages, I’m more comfortable with the approach and consider it the norm. Unfortunately, Apple is somewhat inconsistent with the behaviour.

It is seemingly on an application by application basis whether or not the application will quit when the main window is closed. System Preferences used to persist but now closes. iTunes stays open, iSync closes and AddressBook stays open!

For my own application, the decision on this has consumed much of my time. The code to make the application quit on window code is quite simple. Add the following two lines to the application delegate:


def applicationShouldTerminateAfterLastWindowClosed_(self, sender):
    return True

The Apple app that is closest to my own is AddressBook, so when in doubt I have emulated the AB behaviour. Partially for the benefit of users and partly for my own sanity.

As I start designing new applications, I end up with the same problem of which behaviour to choose. My default is to persist the application unless I get a large number of user complaints. To choose otherwise? I may as well write Windows programs.

Evening at Adler - Some guys talking about the Mac

After watching the Evening at Adler video, I can safely say that it is a must see for anyone developing software for the Apple platform. DB managed to assemble the who’s who of Mac software development for a round table chat.

Inspirational and informative, with a touch of controversy and some laugh out loud comedic moments. Can’t go wrong really. Although I suspect the background music was chosen for the closing visuals.