Thursday, 21 October 2010

Using CoreMIDI in iOS (an example)

In iOS 4.2 the CoreMIDI framework is dropping into the standard operating system. MIDI connectivity using generic class-compliant USB MIDI hardware will be available to all.

It's not a big framework, with a handful of pure-C APIs. But its affect will be profound. What was previously only possible using Akai's AkaiConnect SDK (which is a very nice Objective-C API) or Line 6's MIDI Mobilizer SDK will be available to all.

From what I can see, the iOS CoreMIDI version is going to be the exact same API as the Mac OS desktop variant. I expect developer take-up of this API to be far faster than for the existing two (non-standard) iOS MIDI interface APIs. Pretty soon every iPhone synth app will support Apple's generic MIDI API.

That is, if they can work out how to.

CoreMIDI isn't the best documented API (this is all you get: a list of typedefs and functions). Fortunately, the headers are well-commented and the API is mercifully simple and sensible. However, with no compelling examples (that I could find) it takes a little digging to work out how to use CoreMIDI.

So here I present a very simple example project, with a reusable Objective-C MIDI interface class. With this code, you can get up to speed with CoreMIDI quickly. Indeed, if you just paste my MidiInput class into your synth app you'd be good to go.

Grab it from the GitHub project here. (Update note: the repo master used to be hosted on Gitorious here but we've moved to GitHub in these enlightened times)

Please let me know if you find it useful, or if you use it in your own projects.


Integrating CoreMIDI in your application

First, you need to decide if you want your app to support devices running iOS versions before 4.2. Since CoreMIDI is only introduced in 4.2, you have to jump through a few hoops to keep your app running on earlier versions:
  • Weakly link to the CoreMIDI framework, so on OS versions without it your application will still launch. (You do this by going to your application's target in the Xcode tree view, selecting "Get info", and in the "General" tab's "Linked libraries" section ensuring that CoreMIDI is set to "Weak" not "Required".)
  • Including CoreMIDI functionality conditionally. The best way to do this is inspect the kCFCoreFoundationVersionNumber variable and only initialise your MIDI handling if the value represents iOS 4.2 or later. (See the iOS version detection header file in my example project for an elegant way to do this).

A demonstration of all of this is available in my example project.


Using CoreMIDI

CoreMIDI itself isn't too complex if you're happy to read the headers and work out what's going on. You need a basic grasp of how Mac OS's Core Foundation works, to understand lifetime management issues and to access string properties, etc.

CoreMIDI has a few basic concepts: most importantly clients, devices (with endpoints) and ports. The C APIs let you enumerate these, and register a notification to keep abreast of changes in MIDI connection state.

MIDI inputs are "sources" in CoreMIDI. MIDI outputs are "destinations".

Given those basic facts, you should be able to read through my MidiInput class and figure out what's going on.


Parsing MIDI

My example program just spits out a stream of binary MIDI data. I'm not showing any parsing of the MIDI data stream here. This parsing isn't rocket science, but is another step you have to perform.

Contact me if you want to know more about parsing MIDI.


Learning: Some Practical Ideas To Help You Learn

A I wind down my blog series on software developers learning, I present some practical ideas to help you improve your learning:

  • Cultivate a healthy set of attitudes: take responsibility for your learning.

  • Learn one programming language per year. (This is excellent advice in The Pragmatic Programmer that is still very valid today.)

  • Scratch an itch! (What are you curious about? Consider something “leftfield”, not programming-related. Ensure that at all times you have something you're learning about that isn't directly related to your day job).

  • Read at least one book every two months (Read more if you want, but set some kind of benchmark to aim for).

  • Look after your learning machine – get good nutrition, and plenty of rest. Avoid stress. Have fun!

  • Build mental maps as you learn.

  • Try to use both sides of your brain.

  • Perform deliberate practice & exercise as you learn.

  • Network: actively learn from others, and seek to teach/mentor others.

  • Enjoy learning. This stuff is fun.

  • Apply any new knowledge cautiously.


Conclusion

You have to take responsibility for your own learning. It's not up to your employer, your state education system, an assigned mentor, or any other person.

You are in charge of your own learning. It's important to continually improve your skills to improve as a developer. And to do that you have to learn to learn. To make it rewarding you have to learn to love doing it.

Learn to live to love to learn.


Questions to ponder

  • When were you last in a situation that required learning?

  • How did you approach it?

  • How successful were you?

  • How quickly did you learn?

  • How could you have performed better?

  • Did you learn, then work, or learn as you worked?

  • Which do you think is most effective?

Wednesday, 20 October 2010

Write Less Code!

It's a sad fact that in our modern world that there's simply too much code. I can cope with the fact that my car engine is controlled by a computer, there's obviously software cooking the food in my microwave, and it wouldn't surprise me if my genetically modified cucumbers had an embedded micro controller in them. That's all fine; its not what I'm obsessing about. I'm worried about all the unnecessary code out there.

There's simply too much unnecessary code kicking around. Like weeds, these evil lines of code clog up our precious byes of storage, obfuscate our revision control histories, stubbornly get in the way of our development, and use up precious code space, choking the good code around them.

Why is there so much unnecessary code? Perhaps it's due to genetic flaws. Some people like the sound of their own voice. You've met them; you just can't shut them up. They're the kind of people you don't want to get stuck with at parties. Yada yada yada. Other people like their own code too much. They like it so much they write reams of it. { yada->yada.yada(); } Or perhaps they're the programmers with misguided managers who judge progress by how many thousands of lines of code have been written a day.

Writing lots of code does not mean that you've written lots of software. Indeed, some code can actually negatively affect the amount of software you have – it gets in the way, causes faults, and reduces the quality of the user experience. The programming equivalent of anti-matter.

Some of my best software improvement work has been by removing code. I fondly remember one time when I lopped literally thousands of lines of code out of a sprawling system, and replaced it with a mere ten lines of code. What a wonderfully smug feeling of satisfaction. I suggest you try it some time.

Why should we care?

So why is this phenomenon bad, rather than merely annoying? There are many reasons why unnecessary code is the root of all evil. Here are a few headlines:

  • Writing a fresh line of code is the birth of a little lifeform. It will need to be lovingly nurtured into a useful and profitable member of software society. Then you release the product.

Over the life of the software system, that line of code needs maintenance. Each line of code costs a little. The more you write, the higher the cost. The longer they live, the higher the cost. Clearly, unnecessary code needs to meet a timely demise before it bankrupts us.

  • More code means there is more to read – it makes our programs harder to comprehend. Unnecessary code can mask the purpose of a function, or hide small but important differences in otherwise similar code.

  • The more code there is, the more work required to make modifications – the program is harder to modify.

  • Code harbours bugs. There more code you have, the more places there are for bugs to hide.

  • Duplicated code is particularly pernicious; you can fix a bug in one copy of the code and, unbeknown to you, still have another thirty two identical little bugs kicking around elsewhere.

Unnecessary code comes in many guises: unused components, dead code, pointless comments, unnecessary verbosity, and so on. In a future post, I'll look at some of these pernicious beasties in a little more detail.

Tuesday, 19 October 2010

Learning: Mapping your learning journey


In the last few posts on learning I've been reviewing a number of tools that help us, as software developers, learn.The final tool we'll look at in our arsenal is a powerful old favourite: the mind map. Mind maps are a powerful outlining technique that appeases the left brain's linear organisational fetish whilst satisfying the right brain's spatial, relational desires.

Mind maps are structured outlines in which you start with a key concept in the middle and add information around it forming a web. You can add extra relations between items, and freely use colour, illustration, size and position to highlight extra information.

I often produce mind maps for talks and articles I'm writing. Being an unashamed sad geek, I tend to produce these electronically (I used FreeMind which works on Windows, Mac, and Linux). Then I can keep them under source control and version them alongside my articles.

However, many people claim that you will miss the full benefit of the mind mapping technique by doing this. The more visceral, physical act of creating a hand-written version helps you explore and retain information. By laying out the relations yourself rather than relying on a machine to typeset the “document” for you, you consider inter-relations and build a tangible picture in your mind that will aid later recall.

Next time you're learning, why not try to record knowledge in a mind maps you go? When investigating a learning route and working out what you need to know, record your findings in a mind map.

Use mind maps to catalogue information. They are a proven, powerful tool.

Thursday, 30 September 2010

A UITableView with an "empty" view

Most every iOS application that presents a list of information is built around the UITableView class. It's a central part of the iPhone UI arsenal.

The really polished apps use this class particularly well. Look at the iPod application, for example. When there is nothing to display in a table view, the iPod app shows a placeholder view with a pretty icon and some text explaining why the list is empty:


It's these neat little UI touches that set a truly great application apart from a merely adequate one.

I want one of those

It's not rocket science to code such UI behaviour, but why do that when someone's already done it for you?

Mosey on over to the TableViewWithEmptyView Gitorious project and grab my code from there.

Most of that project's files comprise the requisite scaffolding to provide an example demonstrating the class. To use the class in your own project you need only copy over the PGTableViewWithEmptyView.h and PGTableViewWithEmptyView.m files.

Using the class is simple. It works exactly like a standard UITableView, but has one extra property emptyView. Assign this property the UIView you want displayed when there are no items in the table. The rest happens automatically for you.

The empty view fades in and out smoothly for added UI chintz.

To make things even easier, you can wire all this up in your XIB file, so your code need never mention the PGTableViewWithEmptyView class itself. Now that's magic.

I'd be grateful to hear from you if you use this class. Please also feel free to send me any suggestions, improvements, or bug reports.

Wednesday, 29 September 2010

Building a Boost framework for iOS (iPhone, iPad, etc)

Several Boost versions have ticked past since I last posted about building a Boost framework for use with the iPhone. Each version of Boost requires subtly different build steps, and each version better supports building iPhone versions out of the box.

The good news: Boost 1.44.0 builds for iPhone a lot more easily than previous versions.
The bad news: making a framework is still not easy.

But first, why?

First, let's answer the obvious question: Why would you want to bother building a framework at all?

Quite simply: to make your life easier.

Using the native Boost build, you (may) need to link against a number of different Boost libraries in your application. And then you need to do a clever dance to ensure you link against either the i386 (simulator) or armv6/armv7 (iPhone devices) versions, depending on your build configuration.

That is tedious and annoying, and not the way it should be. Other Apple "libraries" are provided as a "framework" which you just need to mention once in Xcode, and then the build system works out how to link to the correct version and how to find the right headers.

So, if we can turn Boost into a framework life would be so much easier.

And that's what I have done.

Pete: Doing all the hard work to save literally... some... people all the hassle.


Executive summary

Now, you can do it too.

Just run the script you'll find in Gitorious here: http://gitorious.org/boostoniphone/boostoniphone

Download yourself boost_1_44_0.tbz into the same directory, run the script. Make a cuppa. Make another cuppa. And then admire your new shiney Boost framework.

Use it like any other framework. Draggy droppy. Happy happy.


What changed?

For the hardcore faithful who care about htese things, here's what's changed since my last script version:

  • Boost now builds for iOS far more easily (I think this changed for the better in 1.43.0). Now, you just need to write some gibberish in a user-config.jam and run a boostrap script. That is a darned site easier than it used to be.
  • To make it build for the simulator, you still need to invent some missing header files.
  • But the biggest hassle in this version was creating the final universal library file. Since the ARM builds themselves are now fat archives (including an armv6 and armv7 version of each .o file) I needed to work out how to make a functional uber-lib file. Because Apple's binutils are not useful GNU ones, their ar is braindead. The only way to make a correctly functioning library (that I could find) was to un-lipo the fat ARM binaries, un-ar each archive, link all the original .os into an uber library, than lipo up each of those. Does that sound painful? Yes. It hurt.

Monday, 27 September 2010

Learning: A cunning plan...

In the common work scenario you start from ground zero and need to get up to speed with something in super-fast time. You need to pick up a new codebase, a new set of technologies, and a new problem domain. And be effective and productive almost immediately.

This is rarely possible. But you can be effective fairly rapidly as long as you recognise that you are starting out at the novice Dreyfus level (remember our look at the Dreyfus Model of Skills Acquisition?). In order to be effective at this point you must find a good set of rules to follow, since novices rely on rules to get work done.

But you want to progress beyond novice level, don't you?

In order to learn effectively you need to put in place a considered learning plan. Now, if I wanted to get from my home in Cambridge to visit a friend in Inverness, I wouldn’t just jump in the car and set off. I’d need to plan a route first. I wouldn’t even set up my satnav and follow its instructions. Should I really trust a device to know best?Does it know how I prefer to travel, any particularly busy roads at this time of year, which roads the authorities have decided to perform military assaults on today, etc? Similarly, does a teacher know better about how to get me from here to knowledge?

So I'd have to carefully plan a route first. Maybe getting in the car isn’t actually the best way to get to Inverness – perhaps I should instead fly there, and hire a car at the other end.

Put in place a deliberate learning plan.

So how might we apply this practically to our learning? Start by recognising exactly what you do know right now. Determine what you need to know. Weigh up the possible routes to get there: books, courses, web research, podcasts, etc.

Then determine two or three waypoints along the way you can purposefully aim for. Don't aim too far into the future, as once you have learnt more you may need to re-plan your learning route. Work out how to learn enough to get to those first waypoints. Work out exactly how you'll know when you've got there. (Consider this Test Driven Learning – work out some tests (katas, specific tasks, etc) that will prove you know something. You can use these same tests in the future to check for regressions in your learning). Then once you have a specific plan in place, begin learning.

Planning and executing a learning journey will make your work more focussed and directed. It may prevent you from wasting time by browsing for far too general information on the web, or reading all of a book when only two chapters in the middle are relevant.