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.
100 lines
3.6 KiB
100 lines
3.6 KiB
18 years ago
|
#!/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);
|
||
|
}
|
||
|
}
|
||
|
|