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

#!/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);
}
}