Z-Machine bleeps in Gargoyle

I’m planning on adding support for the Z-Machine’s “Bleeps” (see the Z-Machine Standard §9) to Gargoyle.

This will be as a Glk extension in the vein of Gargoyle’s support for Z-Machine’s colors. I’m providing here my suggested API addition for any feedback. This is a nearly pointless and very small extension, admittedly! But it’d be nice to inch closer to complete Z-Machine support in Gargoyle.

This is not meant as a propsal to add functionality to Glk itself! Such a Z-Machine-specific and niche function shouldn’t be there. Instead, I intend for it to remain an extension as with some other Z-Machine-speficic Gargoyle functions.

The proposed API function:

void garglk_zbleep(glui32 number)

Its description:

This function supports the Z-Machine’s sound bleeps. It can take one of two arguments: 1 (a high-pitched bleep) or 2 (a low-pitched bleep). Any other value is legal, but does nothing. If it implements this function, the Glk library should do its best to bleep, but may be unable to. The bleeps might not actually be at different pitches, or they might not be bleeps at all, but some other sound instead. Or if sound isn’t possible, the Glk library may alert the user a bleep occurred in some other way, such as flashing the terminal. The library, however, must NOT implement bleeping in a way that actively interrupts the user, such as via a dialog box.

This function will not report a status back as to whether or not it was able to do anything. It is not an error for the library to do absolutely nothing: this call is effectively “fire and forget [and hope it does something]”. Under Gargoyle, for example, the user can disable sounds entirely, or can disable bleeps specifically, and this will not be reported to the application. As such, the application should not rely on bleeps to convey important information to the user.

The library must implement bleeps asynchronously: the function call must not wait until a bleep is complete before it returns. A library is free to queue bleeps, have them interrupt each other, or have them play over top of each other. However, bleeps are not permitted to interfere with any other sounds that the game might be playing. They must either play concurrently with the other sound, or not be played at all.

Applications should not assume that bleeps rely on Glk sound support, i.e. it is not necessary (or correct) to check gestalt_Sound2 before bleeping.

As a historical note, different-pitched bleeps occurred at least on MS-DOS and Commodore 128, but on the Macintosh, both bleeps were implemented using the system alert sound (Sosumi, Droplet, Indigo, etc).

If an implementation supports this function, it shall define the macro GLK_MODULE_GARGLKBLEEP.

I intentonally didn’t add a gestalt selector because there’s no reason for it: if the macro is defined, the function exists, and since it’s harmless to call even if the library can’t produce a bleep, there’s no reason to check up front whether it is supported. That is to say, even if the user disabled bleeps, there’s no advantage to avoiding the call.

Since this is currently such a very narrow use case, perhaps it could be worth extending it slightly? Call it “alert” and have it make a sound, flash the terminal, ring the teletype’s bell, or otherwise get the user’s attention in a way that’s entirely up to the implementation? I haven’t seen much need for this in IF, but the \a character did exist for a reason.

I think that would be too unpredictable to be of much use. The Z-Machine feature is very specifically a beep, and not anything else.

As noted by Dannii, this really exists only to support legacy Z-Machine games. However, the proposal more or less does what you say: it’s supposed to bleep, but if the implementation desires, it can do anything to get the user’s attention. However, it’s “supposed” to provided different-pitched bleeps, if at all possible, since this is what is indicated by the Z-Machine Standard.

I added terminal flashing, etc, because of precedent in Frotz: the Unix sound support uses the ncurses beep() function, which will either beep (with \a) or flash the terminal; and the dumb Frotz “sound” code will either visually indicate what happened with text, or try a bell (\a). In truth, though, I don’t see this really gaining traction and I wouldn’t be surprised if only Gargoyle ever implemented it.

I don’t intend or anticipate that this function would be used by anything other than a Z-Machine interpreter for use with @sound_effect.

Is it though? It sounds like Infocom’s Mac interpreter took it as “play the system alert sound”.