My OS X Programming Blog
Mac OS X Cocoa and CoreMIDI Programming
About Andrew Choi


MIDI Programs

MIDI File Player (External Device)

MIDI Destination Pop-Up Button

MIDI File Player (Internal Synth)

MusicSequence Sample Code

MIDI File Writer

MIDI Name Document Parser

NameConfigSetup

Fish Creek MIDI Framework

MidnamUtility

SysExSenderX

Other Programs

FCBlogEditor

FCBlog and Patch

Chinese Checkers Program

jyut6 ping3 Cantonese Input Method

Cocoa Sample Programs

Syntax Coloring Using Flex

NSTextField and Undo

NSToolbar

Implementing File Import

Launch Application and Open URL

Saving Uncommitted Text Field Edits

Algorithms

Jazz Chord Analysis as Optimization

Optimal Line Breaking for Music

Optimal Chord Spacing

   

A blog where I will write mostly about programming in Cocoa and CoreMIDI, and experiences from my ports of Emacs and XEmacs to the Mac OS.

Sample Code for Music Sequences in Audio Toolbox
Saturday May 15, 2004

The MusicSequence data type in the Audio Toolbox (which is part of CoreAudio) is really quite easy to use. Here’s some sample code that demonstrates how to construct a music sequence, set its tempo, add a track to the sequence, name the track, add a patch change, add some notes, and append an end of track meta event (so that a player won’t cut off the last few notes), and save that music sequence to a standard MIDI file. And it’s all only 50 or so lines! My own MIDI file writer is a few times more lines than that.

I’m sure once we start doing real-time stuffs with the music player, it’ll get a little harder. But for now that’s all the functionality I’ll need. The big advantage of adding MusicSequence support to my jazz theory classes is these opaque data objects (which are supported directly by system frameworks) can then be passed between my C++ code and Objective C/Cocoa code without the need for conversion. I’m also thinking about changing my “chord grid” objects into CoreFoundation arrays/dictionaries so that can be passed between C++ and ObjectiveC/Cocoa code conveniently.

Music Player and Music Sequence in Core Audio
Friday May 14, 2004

Nothing too fancy to post today. Just a little MIDI file player I’ve thrown together quickly after studying the sample code in /Developer/Examples/CoreAudio/Services/PlaySequence/. It’s just a bit of simplification of that code, and a test for using a MIDI file already stored in an NSData object. That way we don’t have to deal with FSRef’s and FSSpec’s.

I’ve spent the afternoon reading the latest (March 25, 2004) Core Audio documentation. CoreMIDI is still not included. What I noticed was the MusicSequence data type which, if I had noticed that before, may have convinced me not to write my own MIDI file writer. Oh, well...

If one is implementing a program that deals with MIDI sequences, there is very little reason not to use MusicSequence and its associated functions. It handles all the file I/O and playback and record timing for you, which makes the task much easier. It also allows each track of a sequence to be mapped to an external MIDI device or a music device (software synthesizer), which results in quite a flexible MIDI program.

Band-in-a-Box File Import
Wednesday May 12, 2004

Now that I’ve worked out the file import architecture and code, implementing it in my program is just a simple matter of translating the C++ code for reading BiaB files I wrote earlier into Objective C/Cocoa. I’ve done that for both routines: one that reads files written by BiaB 4.0 and above, and one for reading older files. Here’s the chord editor running along side the BiaB demo, both with the same BiaB format file opened. The file import code I posted yesterday has also been integrated. So if an imported file has been edited, the chord editor will prompt the user for saving it in native file format (i.e., the text format I coded up last week) when it is closed or saved.

I haven’t shown an example that demonstrates the benefit of using a chord spacing algorithm before. So here is one.

Notice how BiaB switches to a smaller font size (bar 1, e.g.) or truncates some chord names (bar 3, e.g.) when space is tight. Both methods contribute to the ugliness of the resulting BiaB display in they own ways. Compare that to the nice layout and spacing on the left :-).

Designing a Foreign File Format Import Function
Tuesday May 11, 2004

Many applications have the ability to import files in non-native formats. Unfortunately, the design of user interactions dealing with these files differ from application to application. Even among Apple applications, Mail, e.g., provides an Import Mailboxes... command, TextEdit allows files in foreign formats to be opened using the usual Open... command but asks the user about saving them in a native format when they are closed, the document-based Cocoa application model allows roles (editor, viewer, or none) to be selected for different document types, and filter services can be used to convert among different file formats. Of course I need to provide file import for my program because it can import Band-in-a-Box files.

As usual, I couldn’t find any good sample code for implementing file import. Although the source code for TextEdit is available in /Developer/Examples/AppKit/, one can’t really learn much from it because of how it is written: it doesn’t even use most of the features that are provided “for free” by Cocoa and implements its own! In fact it is quite amusing that source code that messy (1) is provided as sample code, and (2) implements such a commonly-used utility!

The easiest way to implement file import is probably to provide an Import... command and create an untitled document (of the native document type) into which the imported file contents are placed. This method has the disadvantage of requiring the user to specify the name of the file again when the document is saved (a better interface should suggest by default the name of the imported doucment with a different file extension). Another way is to use the editor/viewer mechanism of the Cocoa document-based application. But the method described in the NSDocument FAQ for “reading one type and (internally) automatically converting to another” doesn’t implement a good interface either. Specifically the application will prompt the user to choose the location to save a new, converted file all over again after its fileName and fileType have been changed.

In any case, here’s my clean and simple sample code for implementing file import! It follows the TextEdit interaction model most closely but without the coding mess. It handles two types of files, with suffixes .native and .imported, with a single document type. The method SaveDocument: in NSDocument is overridden to inform the user of the conversion to native format when it needs to be performed. The more interesting part of the code is the overriding of canCloseDocumentWithDelegate:shouldCloseSelector:contextInfo: which allows the user to save a document if necessary when it is closed. I suppose this code also illustrates how much the callback model for implementing GUI’s is messier than the multithread model. But there’s no avoiding the former if one is programming with Cocoa.

May 2004
Sun Mon Tue Wed Thu Fri Sat
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31
Apr  Jul

xml

Search this blog with


Lists

Less-Known Facts About Emacs

Emacs Rants

Chinese Restaurants in Calgary

Calgary/Banff Tourist Attractions

C++ Reading List

Science Fiction Series

Top-10 Reason I Stopped Working on Emacs

Top-10 Types of Questions I Get About Emacs

10 Defining Moments as Programmer


Misc

Carbon XEmacs

Emacs for Mac OS X


Copyright © 2003, 2004, 2005 Andrew Choi (Contact Information). Created with FCBlog