Request for help: JSON protocol for Glk sound

Here’s the protocol I think I’ve settled on.

First output.

export interface StateUpdate {
    ...
    /** Sound channels (new channels, or new operations) */
    schannels?: SoundChannelUpdate[],
}

export interface SoundChannelUpdate {
    /** Sound channel ID */
    id: number,
    /** Sound channel operations */
    ops?: SoundChannelOperation[],
}

export type SoundChannelOperation = PauseOperation | PlayOperation | SetVolumeOperation | StopOperation | UnpauseOperation

export interface PauseOperation {
    op: 'pause',
}

export interface PlayOperation {
    op: 'play',
    /** Notification value */
    notify?: number,
    /** Number of repeats (default: 1) */
    repeats?: number,
    /** Sound resource ID (from a Blorb) */
    snd: number,
}

export interface SetVolumeOperation {
    op: 'volume',
    /** Duration in milliseconds */
    dur?: number,
    /** Notification value */
    notify?: number,
    /** The volume as a number between 0 and 1 */
    vol: number,
}

export interface StopOperation {
    op: 'stop',
}

export interface UnpauseOperation {
    op: 'unpause',
}

This is largely the same as @Hanna proposed above, just with a few props renamed. The main difference is as I wrote above - channel and operation updates are all done together. If you have many channels but only play a sound on one, it will be a little bit verbose as you’ll need to send updates for all those channels, but each channel’s update only needs to include its ID.

Also, play operations may need to send a URL rather than a Blorb resource ID. I’m not sure about this - it wouldn’t work with the sound event below. Rather than sending a URL in the case of non-Blorb resources, it may be better to use the garglk_add_resource_from_file extension.

Events will be updated with:

export type Event = ... | SoundEvent | VolumeEvent

export interface SoundEvent extends EventBase {
    /** Event code */
    type: 'sound',
    /** Sound resource ID which finished playing */
    snd: number,
    /** Notification value */
    notify: number,
}

export interface VolumeEvent extends EventBase {
    /** Event code */
    type: 'volume',
    /** Notification value */
    notify: number,
}