This is the program I use to run shows off my laptop at a theater. It was originally written for a production of "A Few Good Men" which required precise synchronization between the sound and audio, and has now grown to support a moving-head light (MHL) and nearly everything else I need to do to make a show as simple for the operator as "press the space bar at the right time".
There is a helper program that's a useful program in its own right, called Effects, which just uses ALSA to play SFX when a key is pressed. It reads a configuration file, where each line is a character to listen for followed by a tab and then the name of the audio file to play (there's also support for auto-follow; see the source). Files are loaded into memory at program start time, to avoid a processing delay during a show. Sound files are assumed mono native-endian 16-bit 44.1kHz samples, but it will convert .mp3 and some other file types to that format if necessary. (Mono is forced because the speaker separation in the Second Story Theater makes stereo SFX a bad idea.)
The files below comprise the runner program itself:
You'll need to make a cues.tsv file for your show, which is a tab-delimited file with cue#, looks (one or more named looks separated by a plus sign for HTP, or blank to say "use the look from the previous line"), what SFX to run, fade time for the lights, page number in the script, and a free-form cue field to tell the operator when to hit the space bar.
An AccuSpotPro moving-head light (MHL) is supported at address 100, but if you aren't using one in your show that support won't get in the way.
The program as a whole is pretty much totally undocumented, and it's in a constant state of flux as I add things or modify things to fit any odd requirements of the shows I do, so if you want to use the program or have any questions about it please send me an email and I'll be happy to help you out.
This program is designed to interface with a DMX widget. The widget acts as a USB serial device. The "escape" character is 254 (0xFE). For transmit, escape followed by 0 (0x00) sends a break, and escape followed by 1 (0x01) sends 0xFE as a byte. Sending multiple escape bytes together is equivalent to sending one, so the device can't get out of sync. On receive, escape+0x00 means break, escape+0x01 means 0xFE, and escape+0x02 means error/corruption.