About Andrew Choi
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
Fish Creek MIDI Framework
FCBlog and Patch
Chinese Checkers Program
jyut6 ping3 Cantonese Input Method
Cocoa Sample Programs
Syntax Coloring Using Flex
NSTextField and Undo
Implementing File Import
Launch Application and Open URL
Saving Uncommitted Text Field Edits
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.
Friday December 12, 2003
Ive finished implementing the setup utility described yesterday for editing the name configuration stored in CoreMIDI. NameConfigSetup allows you to set and change the master name document for each device. Each patch bank in the master name document may be overridden with a patch name list in another name document. NameConfigSetup also allows you to edit this information.
A limitation of the current implementation is that it can only correctly edit name information for devices whose master name document has one (custom) device mode. This can easily be extended when necessary. Only a handful of synthesizers among those supported by MOTUs
.midnam files require more than one device modes. None of my synths does.
Thursday December 11, 2003
A Name Configuration Setup Utility
If you study the CoreMIDI 1.3 documentation closely, youll notice that there is already infrastructure to support patch names and patch name lists for MIDI devices through the use of the
kMIDIPropertyNameConfiguration property. I emphasize infrastructure because you have to do everything yourself! Experiments show that if you set this property with a dictionary with the prescribed structure, this data will be persistent and stored in the file
~/Library/Audio/MIDI\ Configurations/Default.mcfg. Calls to get this property will give you back the value you set.
So how do you create the proper dictionary structure and set the
kMIDIPropertyNameConfiguration property with it, or later edit it? It looks like such an editor might eventually be part of AudioMIDISetup, but the good people at Apple havent written it yet! I need to use patch names in my Ensemble interface so Ive started to write one. Heres the main window of a mock up.
The editing functions in it dont work yet. Ill work on this in the next few days.
Wednesday December 10, 2003
I spent a little time learning about alias handles today because in CoreMIDI, the
kMIDIPropertyNameConfiguration property of a device contains alias handles of the master name document and overriding
.midnam documents. Alias handles turned out to be a little tedious to use. A POSIX pathname must be converted into a URL, then into an FSRef, then into an alias (pointed to by a toolbox style Handle). If the alias needs to be stored, it must be converted into an NSData instance. To recover the POSIX pathname, one performs the above steps in reverse.
I wrote a small test program to demonstrate the above steps. The interesting thing about the program is that after it constructs the alias from the pathname of a file given as argument, it waits for the user to type a return. If at this time the file is moved in the Finder, the pathname reconstructed for the file and displayed by the program subsequently will show its new location. Well, thats what aliases are useful for.
Tuesday December 9, 2003
FCM Framework and MidnamUtility Documentation
Here is some documentation for the FCM framework and MidnamUtility. The code is released under the Perl Artistic License. You need Panther and Xcode to build and run them.
The Fish Creek MIDI (FCM) framework can be used to build programs for transferring MIDI sysex messages to and from MIDI devices in Objective-C/Foundation and/or Python. The FCM framework provides a high-level interface that hides the details of the underlying CoreMIDI framework, and allows sysex applications to be designed and implemented much more easily.
To use the FCM framework in a Foundation (or Cocoa) project, first build the
FCM target in the FCM Xcode project (the archive of the project may have a name like
FCM-Python6.tgz). Add the FCM framework to your project, and in your source files that use the FCM classes and methods, import the header file
The Objective-C interface of the FCM framework exposes two classes
FCMClient is a singleton class that represents your applications access to CoreMIDI as a client. The single instance of the class can be obtained by the class method
sharedInstance. This instance can then be used to query the list of sysex devices available in the system by name or by device UID's using the methods
getSysexDeviceDeivceUIDs, respectively. Note that accessing the shared instance for the first time in an application also implicitly initializes the application as a CoreMIDI client. The shared instance also posts a
FCMSetupChanged notification to the default notification center whenever the MIDI setup changes. This can be used to update the lists of sysex devices presented to the user for selection in, say, popup buttons.
FCMSysexDevice instance represents a sysex device, from which you can receive data and to which you can send data. An
FCMSysexDevice can be initialized by name or by device UID. Both send and receive operations are asynchronous. A send is initiated by the instance method
sendData and reception of data automatically begins after an
FCMSysexDevice instance is initialized. Asynchronous operation of course means that once a transfer is started, control returns immediately to the application so progress indicators can be updated, cancel button can be handled, etc. The status of the transfer can checked by the instance methods
NumBytesSent returns -1 if an error has occurred. A send in progress can be canceled by calling
cancelSend. When the expected number of bytes have arrived, or no apparent progress is noticed in an interactive setting, the instance method
receiveData can be called to retrieve the received data. The
FCMSysexDevice immediately becomes ready to receive more sysex data once
The SysExSenderX project demonstrates the use of the Cocoa interface of the FCM framework to implement an interactive MIDI sysex application, complete with progress indicators and cancel buttons.
To use the FCM framework as a Python extension module, first build the
PythonExtension target of the FCM Xcode project. Then copy or move the Mach-O bundle
FCM.so in the directory
build/lib.* to a place where your Python interpreter can find it, or set the environment variable
PYTHONPATH to include the directory containing it. Then at the beginning of your Python modules that use the FCM extension module, add the statement
The FCM extension module provides the module methods
sysexDeviceDeviceUIDs that perform the obvious functions. Currently a Python program is not notified that the MIDI setup has changed except subsequent calls to
sysexDeviceDeviceUIDs will return the current lists.
The FCM extension module also provides the type
SysexDevice, which can be used to define objects that represent sysex devices. The type methods
cancelSend perform the obvious functions. Again sysex messages begin to be collected once the
SysexDevice object is created and the
receive call returns all the sysex messages received up to that point. The type method
close is called when a
SysexDevice object is no longer needed.
Send accepts a Python string argument and
receive returns a Python string. Since Python strings (unlike C strings) may contain null characters, their use for representing MIDI sysex messages, which may contain bytes that are zero, is OK.
In addition to the client and sysex device interfaces, the FCM framework also provides two utility functions
FCMParseXML which convert MIDI name documents to and from their equivalent Foundation collection form.
MidnamUtility (I think I need a fancier name) is a MIDI sysex utility that fetches the names of the current patches from a synthesizer and writes a
.midnam file that represent that patch name list. Users can extend it to handle synthesizers it doesnt already support by writing plug-in modules in Python. MidnamUtility uses the FCM framework for sysex transfers.
The current distribution of MidnamUtility provides plug-in modules for the Yamaha DX7-II, Roland JD-990, Korg Wavestation A/D, E-mu Morpheus, and E-mu Procussion. These (and other) Python modules must be placed in either of the following directories.
The user directory will take precedence when two files of the same name appear in both directories.
To use MidnamUtility, start it up. Select the sysex device from which you wish to fetch patch names in the popup button labeled Sysex Device. Then select the device type from the Device Type popup button. The list of device types correspond to all
<devicetype>.py Python module files the program can find in the two Python module directories. Then click the Get Names button and when sysex transfer is complete, you’ll be presented with a save panel to save the
Each Python plug-in module must implement the function
getNames and variable
GetNames is passed the (string) name of the sysex device and should do whatever necessary to fetch and extract the patch names from it. It should assume that the MIDI client is already initialize, and should not terminate it when it returns.
GetNames should return a list of pairs. Each pair should consist of a (string) patch list name and a list of patches. Each patch is a 3-tuple of (string) patch number, (string) patch name, and (integer) control change number.
XMLTemplate should simply be a variable with a string value that is identical to the output
.midnam file, except with the patch name lists removed. The plug-in modules in the distribution provide examples of how such modules should be implemented.
Monday December 8, 2003
Python Modules for DX7-II, Procussion, and Wavestation
A few modifications were incorporated into this new version of MidnamUtility today. The most important one is that a template is no longer supplied as a plist in the Python module as the value of the variable
plist. Instead, the variable
XMLTemplate must contain a copy of the desired
.midnam output without the PatchNameLists that will be fetched. An XML template is more natural than one in plist format because we can see exactly what the output will look like.
Providing support for XML input requires the MIDI name doc parser as well as the generator I wrote earlier. These are included in this new version of the FCM framework.
I also converted three more Python modules that can be used with MidnamUtility. These are for the Yamaha DX7-II, E-mu Procussion, and Korg Wavestation A/D, respectively. Here's an archive containing these new modules and ones for the JD-990 and Morpheus, converted to define the new XMLTemplate variable. The code for the Wavestation module is particularly interesting because of the complexity of the Wavestations sysex. The Python built-in functions
reduce make it easy to convert nibble strings into the corresponding ASCII patch names. So far the power of the Python language has been more than adequate for implementing these modules.
Search this blog with
Less-Known Facts About Emacs
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
Mac OS X