REM
REM Implement a BEEP over the hardware PC speaker.
REM Currently Linux only - tested with Ubuntu 9.04
REM
REM (c) PvE - GPL - July 11, 2009.
REM Improved error handling - Oct 11, 2009.
REM
REM ---------------------------------------------------------- Manual
REM
REM Include this file into your program with: INCLUDE "beep.bac"
REM
REM It implements two calls: 'BEEP' and 'SHUT'.
REM
REM 1. BEEP (frequency, time)
REM
REM Let the hardware PC speaker sound the frequency for a duration
REM of time.
REM
REM 2. SHUT
REM
REM Shutdown all sound pending on the hardware PC speaker.
REM
REM
REM See also 'piano.bac' for an example on usage of the BEEP INCLUDE.
REM
REM ---------------------------------------------------------- Frequencies
REM
REM TABLE OF MUSICAL NOTE FREQUENCIES (Hz)
REM
REM Octave 0 1 2 3 4 5 6 7
REM Note
REM C 16 33 65 131 262 523 1046 2093
REM C# 17 35 69 139 277 554 1109 2217
REM D 18 37 73 147 294 587 1175 2349
REM D# 19 39 78 155 311 622 1244 2489
REM E 21 41 82 165 330 659 1328 2637
REM F 22 44 87 175 349 698 1397 2794
REM F# 23 46 92 185 370 740 1480 2960
REM G 24 49 98 196 392 784 1568 3136
REM G# 26 52 104 208 415 831 1661 3322
REM A 27 55 110 220 440 880 1760 3520
REM A# 29 58 116 233 466 932 1865 3729
REM B 31 62 123 245 494 988 1975 3951
REM
REM ---------------------------------------------------------- Initialize
REM Check on the availability of ioctl
TRAP LOCAL
CATCH GOTO beep_print_message
REM Make sure X reacts on bell
SYSTEM "xset b on 2>/dev/null"
REM Get the system call for console environment
IMPORT "ioctl" FROM "libc.so" TYPE int
REM Define values for console environment
DEF FN beep_KIOCSOUND = DEC("4B2F")
DEF FN beep_KDMKTONE = DEC("4B30")
CONST beep_DEVICE = 1
CONST beep_X86_oscillator = 1193180
REM Flag that we use X environment
beep_NoUseX = 0
REM Get the system calls for an X environment
CATCH GOTO beep_No_X_Environment
IMPORT "XOpenDisplay" FROM "libX11.so.6" TYPE long
IMPORT "XGetKeyboardControl" FROM "libX11.so.6" TYPE void
IMPORT "XChangeKeyboardControl" FROM "libX11.so.6" TYPE void
IMPORT "XCloseDisplay" FROM "libX11.so.6" TYPE void
IMPORT "XBell" FROM "libX11.so.6" TYPE void
IMPORT "XFlush" FROM "libX11.so.6" TYPE void
REM Define values for the X environment
CONST beep_KBBellPitch = 1 << 2
CONST beep_KBBellDuration = 1 << 3
RECORD beep_XKeyboardState
LOCAL key_click_percent TYPE int
LOCAL bell_percent TYPE int
LOCAL bell_pitch, bell_duration TYPE unsigned int
LOCAL led_mask TYPE unsigned long
LOCAL global_auto_repeat TYPE int
LOCAL auto_repeats[32] TYPE char
END RECORD
RECORD beep_XKeyboardControl
LOCAL key_click_percent TYPE int
LOCAL bell_percent TYPE int
LOCAL bell_pitch TYPE int
LOCAL bell_duration TYPE int
LOCAL led TYPE int
LOCAL led_mode TYPE int
LOCAL key TYPE int
LOCAL auto_repeat_mode TYPE int
END RECORD
REM ---------------------------------------------------------- Implementation
REM The BEEP function
SUB BEEP(NUMBER freq, NUMBER duration)
LOCAL result, display
IF freq > 0 THEN
REM Run the beep on the console
result = ioctl(beep_DEVICE, beep_KIOCSOUND, beep_X86_oscillator / freq)
IF result < 0 THEN
REM Console did not succeed, try X environment
IF ISFALSE(beep_NoUseX) THEN
display = XOpenDisplay(0)
XGetKeyboardControl(display, ADDRESS(beep_XKeyboardState))
beep_XKeyboardControl.key_click_percent = 0
beep_XKeyboardControl.bell_percent = 0
beep_XKeyboardControl.bell_pitch = freq
beep_XKeyboardControl.bell_duration = duration
beep_XKeyboardControl.led = 0
beep_XKeyboardControl.led_mode = 0
beep_XKeyboardControl.key = 0
beep_XKeyboardControl.auto_repeat_mode = 0
XChangeKeyboardControl(display, beep_KBBellDuration | beep_KBBellPitch, ADDRESS(beep_XKeyboardControl))
XBell(display, 100)
XFlush(display)
SLEEP duration
XChangeKeyboardControl(display, beep_KBBellDuration | beep_KBBellPitch, ADDRESS(beep_XKeyboardState))
XCloseDisplay(display)
ELSE
PRINT "Cannot use PC speaker on this machine!"
END IF
ELSE
REM Stop the beep on the console
SLEEP duration*2
ioctl(beep_DEVICE, beep_KIOCSOUND, 0)
END IF
END IF
END SUB
REM The SHUT function
SUB SHUT
LOCAL result, display
REM Stop the beep on the console
result = ioctl(beep_DEVICE, beep_KIOCSOUND, 0)
IF result < 0 THEN
REM Console did not succeed, try X environment
IF ISFALSE(beep_NoUseX) THEN
display = XOpenDisplay(0)
XFlush(display)
XCloseDisplay(display)
ELSE
PRINT "Cannot use PC speaker on this machine!"
END IF
END IF
END SUB
REM Goto end of include file
GOTO beep_END
REM ---------------------------------------------------------- Error handling
REM Call 'ioctl' not found
LABEL beep_print_message
PRINT "IOCTL is not available on this platform! Check if 'libc.so' exists."
END
REM We will not use the X environment
LABEL beep_No_X_Environment
GLOBAL beep_NoUseX = 1
PRINT "No X"
RESUME
LABEL beep_END
TRAP SYSTEM
CATCH RESET