You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
99 lines
3.6 KiB
99 lines
3.6 KiB
#!/usr/bin/perl |
|
## |
|
## asterisk-clock.pl -- Asterisk PBX Accurate Talking Clock |
|
## Copyright (c) 2007 Chris Walton |
|
## Copyright (c) 2008 Ralf S. Engelschall <rse@engelschall.com> |
|
## License: GPL (version 2 or higher) |
|
## |
|
## This script will generate a 1.5s beep at 0, 15, 30, and 45 seconds |
|
## past each minute. It uses sub-second time delays in order to be as |
|
## accurate as possible. The time is annoumced in English at 11 seconds |
|
## before the beep. Warning "blips" play and 2 seconds and 1 second |
|
## before the beep. |
|
## |
|
## 1st PASS example... assume program starts at 5.5 seconds past the minute: |
|
## ---------------------------------------------------------------------------- |
|
## 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
## ->BLIP>BLIP>BLIP>BLIP>BLIP>BLIP>BLI>BLIP>BLIP>BEEP |
|
## normal operation (loop): |
|
## ---------------------------------------------------------------------------- |
|
## 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
## BEEP--->SILENCE----->TIME_ANNOUNCEMENT_FOLLOWED_BY_SILENCE----->BLIP>BLIP>BEEP |
|
## |
|
|
|
use Time::HiRes qw(usleep gettimeofday); |
|
|
|
my $blip = "!523/20,!0/980"; # 20ms blip followed by 980ms silence. |
|
my $beep = "!415/1500"; # 1.5s beep. |
|
my $silence = "!0/500"; # 0.5s silence. |
|
|
|
# turn off output buffering to stop dead lock. |
|
$| = 1; |
|
|
|
sub status { |
|
# AGI function status is avaialbe on STDIN |
|
my $cmd = shift; |
|
my $status = <STDIN>; |
|
if ($status !~ m/^200 result=0/) { |
|
print STDERR "$cmd returned with bad status ($status)\n"; |
|
exit(-1); |
|
} |
|
} |
|
|
|
# STDIN will initially contain assorted channel information. Discard it all. |
|
while (<STDIN>) { |
|
chomp; |
|
last unless ($_); |
|
} |
|
|
|
# Answer the channel |
|
print "ANSWER\n"; |
|
status("Exec Answer"); |
|
|
|
while (1) { |
|
my ($seconds, $microseconds) = gettimeofday(); |
|
|
|
# sleep until the next second rolls around. |
|
usleep(1000000 - $microseconds); |
|
|
|
# calculate number of seconds left before the beep. |
|
my $time_til_beep = 14 - ($seconds % 15); |
|
|
|
if ($time_til_beep < 11 ) { |
|
# Insufficient time to announce the time; just play blips. |
|
# This should only occur on first pass. |
|
print "EXEC PlayTones ", ("$blip," x $time_til_beep), $beep, "\n"; |
|
status("Exec PlayTones"); |
|
|
|
# Sleep while the blips and beep are playing. |
|
usleep($time_til_beep * 1000000 + 1500000); |
|
} else { |
|
# We have sufficient time to announce what the time will be at the beep. |
|
my $time_at_beep = $seconds + $time_til_beep + 1; |
|
|
|
# Sleep until 11 seconds before the beep and then announce the time. |
|
usleep(($time_til_beep - 11) * 1000000); |
|
print qq{STREAM FILE at-tone-time-exactly ""\n}; |
|
status("Stream File"); |
|
print qq{SAY DATETIME $time_at_beep "#" "IM'vm-and'S'seconds'\n}; |
|
status("Say DateTime"); |
|
|
|
# We need to get the time again because we don't know how long |
|
# the announcement took to play. |
|
($seconds, $microseconds) = gettimeofday(); |
|
|
|
# Now sleep until 2.5 seconds before the beep. |
|
my $delay = 12500000 - $microseconds - (($seconds % 15) * 1000000); |
|
next if ($delay < 0); # abort if annoucment took too long to play. |
|
usleep($delay); |
|
|
|
# Now play two warning blips followed by the beep. |
|
# Preceeding the blips with .5s silence ensures the 1st blip is heard. |
|
print "EXEC PlayTones $silence,$blip,$blip,$beep\n"; |
|
status("Exec PlayTones"); |
|
|
|
# Sleep while the blips and beep are playing. |
|
usleep(4000000); |
|
} |
|
} |
|
|
|
|