nick@cs.edinburgh.ac.uk (Nick Rothwell) (02/21/91)
>Would someone (Nick...) like to expound upon the benefits of using Apple's >MIDI Manager, what it is, what it does, and how one gets it? I can't seem to >find mention of it in any of the Apple literature I have, nor is it listed on >Apple's confidential price list. Well, I'll reply to the THINK C list as well as EMUSIC - it might be of interest there as well. What the hell, I'll fire this off to rec.music.synth and the Mac newsgroups as well. That way, NOBODY will EVER have to ask about MIDI Manager again. Right? Check... Non-Mac people might find this interesting as an overview of how to do MIDI cleanly in a hardware independent manner, and how to provide a clean abstract interface to the system services required by a MIDI application and MIDI working environment. Well, how one gets it for a start. Via APDA, I believe. Actually, I managed to find MIDI Manager 2.0 on an FTP site somewhere with the Lime notation software. Apple haven't publicised it because they're still tied up in a lawsuit with Apple Corp., the Beatles' record company. There are three releases: 1.1, 1.2 and 2.0. 1.1 was the initial release (1.0 never made it out the door). 1.2 fixed the odd bug, but rendered MM useable only on machines with 256K ROM's, so the Mac Plus was out. 2.0 presumably has extra features, but I don't have any documentation for it, so I don't know about them. All I know is that it seems a lot more efficient. MOTU's Performer under MM1.2 was pretty sluggish even on an SE/30. Performer under MM2.0 is fine. I don't know if MM2.0 runs on a Plus or not. What is it? Well, the first MIDI routines for the Mac were the usual read-a-byte write-a-byte kind of thing. Various buggy versions of Kirk Austin's assembly code were floating around all over the place, and even today there are still lots of roll-your-own MIDI driving routines (HyperMIDI, MIT toolkit, and so on). These are Bad News. Let me explain why. [AN ASIDE: Macintoshes have two serial ports, which support RS424 (I think - the balanced-pair hardware spec. anyway). These are identical (modulo processor interrupt priority) and plenty fast enough to run at MIDI speeds; after all, they take AppleTalk in their stride. You need some hardware to generate MIDI from RS424; you have to convert voltages, nail one half of the RS424 to ground, build the current loop, and opto-isolate the input. In addition, the interface provides the 1MHz (usually) signal to clock the UART, rather than having the Mac try to invent a suitable baud-rate. So, a Mac can support two independent MIDI Ins and Outs for 32 channels each way if you use the serial ports; if you want more than that, you can pull tricks like using a multiplexing protocol - this is what MOTU do for their MIDI Time Piece, using an otherwise undefined MIDI Status Byte to signify cable number. So, a MIDI interface is just a box of cheap electronics. I built a dual-port MIDI interface with bi-colour activity LED's for about $20. If you don't want to do that, feel free to pay Opcode $200 for something similar. I don't know of any incompatibilities of the sort you can get with weird mutant MP401 clones on the PC.] Anyway: why not roll your own MIDI routines? o Hardware dependency. Sure, your routines worked fine on the Mac 512K, but for some reason they can't handle the auto sleep routines on the Portable (ain't that right Marc?). 'Nuff said? o Software parsing of MIDI. It's a real hassle, especially if you want to do it right and not fall flat when faced with embedded realtime bytes. And if you want to read and convert MIDI Time Code and yes run fast enough to handle full-speed SysEx dumps from samplers, then it gets to be a headache. o Hardware independence. MIDI is not always going to mean the two serial ports on the back of your Mac. There are now expansion cards for the Mac that require to get MIDI feeds from Mac sequencers. And I don't see why everybody should extend their applications to handle those, or MOTU's MTP, or any new gizmo which comes along. In fact, a MIDI program shouldn't know or care whether it's talking to a serial port, a plug-in card, another MIDI program, or itself; the MIDI data transfers and timing functions should work regardless. Abstraction's a wonderful thing. o Asynchronous communication. Your wonderful ReadAByte/WriteAByte echo routine is going to sound rather silly if everything hangs for a few seconds when you change layers under MultiFinder or open the Control Panel. MIDI communication should be running all the time, in real time, and not be tied to the event loop. (I know. I've done that. It's not pleasant.) o Software cooperation. I don't want my MIDI program to reprogram the serial ports and shoot AppleTalk through the head. Nor should it interfere with other programs I'm running. In this age of MultiFinder and true multitasking (shut up) a number of MIDI programs should, if not actually communicate, then at least stay out of each others' way. Of course, it would be ideal if programs could communicate with each other. That way you can build MIDI systems out of smaller components. o Timing functions. ReadAByte/WriteAByte MIDI routines are rather hopeless for tying a sequencer to MIDI Time Code coming in off a SMPTE-striped tape. Try it if you don't believe me. So, MIDI Manager solves all these problems. It's an Apple product, which means that (in theory) everyone has it and so every piece of software should be using it. Just like the rest of the Toolbox. Why doesn't everyone have it? Why haven't you even heard of it? Beats me. Ask the lawyers. What do you get? There's a MIDI Manager INIT - this provides the traps for the MIDI Manager, and a Sound Manager trap to say that MM is installed and running. There's the Apple MIDI Driver - this is the link between the MIDI Manager and the serial ports. The AMD will drive either or both ports at one of three clock speeds (depending on your interface), and provides some timecode services. Other vendors will provide alternative drivers for their hardware (I'm eagerly awaiting MOTU's 8 x 8 MTP driver). And there's the PatchBay, which lets users graphically connect applications to each other and the ports. In fact, the PatchBay can be written using the MIDI Manager traps - there's nothing magical about it. (Well, almost nothing.) Suppose you want to write a MIDI Manager application. Well, when it starts up, it has to sign into the MIDI Manager (having verified that MM is installed), and it has to sign out when it's finished. MIDI Manager loads the port drivers when the first application signs in, and drops them when the last application signs out. When your application signs in it provides a name and an icon. This is what PatchBay uses to display your application to the user. To do anything useful, you have to create some communication ports and tell MIDI Manager about them. There are three kinds: Input ports: these are created with hook routines which are called when MIDI data arrives for your application. Output ports: you use these to output MIDI data. Timing ports: these are tied to timebases (either internally generated or externally linked) and provide timestamps for MIDI data. You can have as many ports of whichever kind as you want. These are presented in PatchBay; the user can then connect them together so that your application ends up talking to serial ports, other applications, whatever. Or, you can attach yourself to specific ports (which may still be awaiting creation). There are interface guidelines for this. The user can attach input and output ports in pairs using PatchBay; data flows from output to input. In addition, data can be sent from one output to several inputs, or from several outputs to one input (MIDI Manager does the merging). The time ports allow applications to synchronise, so that a master application (say, a timecode generator) can lock a slave application (say, a sequencer). The Apple MIDI Driver provides time ports which read real timecode from the outside world. I won't go into the timing functions since they're rather complex. Input and output is easier. Output is simple - to output a message, put it into a buffer and send it. Long messages (SysEx's) are flagged with continuation bits. Messages can be queued for future transmission using the time port features; this is dead handy, since it means you can avoid SCC overruns by staggering transmission timestamps. By being a little more clever, you can do your own output buffering and have asynchronous service routines send stuff out when required - see my example code for details. It's great to be able to queue an entire SysEx bank dump for transmission over the next 30 seconds and then forget about it - the application happily keeps going, responding to the user, regardless, as the data goes out under remote control. Input is asynchronous. You don't ask for the next message (well, you can, but it's not cool). Instead, your read hook is called at interrupt time when something arrives. You then get to deal with it then and there regardless of what your application is doing otherwise, even if some other application is frontmost under MultiFinder. Or, you can reject a message and ask to see it again later when you're not busy. MIDI Echo is easy (the readhook just sends the message out immediately); more complicated things require work since the read hook isn't running in a first-class environment - you don't have the usual access to globals, the ToolBox, and so on. But, with a little thought, and a few semaphores, it's not too difficult. If you have time ports, you can set up timer routines which you interface to much like read hooks. I don't think there's much more to say. I love MIDI Manager. It's nice to see Performer and Anodyne (my MIDI generic editor/librarian) pass data to each other and update their progress bargraphs in parallel. There are some subtleties to do with giving each application access to its event loop every now and then, but nothing difficult for your average Mac power programmer. MIDI Manager tends to choke on extremely dense SysEx messages. For example, I can capture a D-50 bank dump easily (it's a set of 200-odd byte SysEx messages with timing gaps) but the VFX sends a single 65K message which is a hassle. The problem is probably that my read hook is a fairly ordinary C procedure. If I wanted top-notch performance I'd have to assembly-code the thing. Can't think of much more to say, really, apart from: APPLE: publicise and distribute the damn thing, and everybody else: use it, dammit. Nick. -- Nick Rothwell, Laboratory for Foundations of Computer Science, Edinburgh. nick@lfcs.ed.ac.uk <Atlantic Ocean>!mcsun!ukc!lfcs!nick ~~ ~~ ~~ ~~ Captain Waldorf has analogue filters. You do not. ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ Do not try to imitate them or any of their actions. ~~ ~~ ~~ ~~