#!/usr/bin/env perl

# Copyright (c) 2009, Douglas Haber
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#     * Redistributions of source code must retain the above copyright
#       notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above 
#       copyright notice, this list of conditions and the following
#       disclaimer in the documentation and/or other materials provided
#       with the distribution.
#     * The names names of the authors may not be used to endorse or
#       promote products derived from this software without specific
#       prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND ITS
# CONTRIBUTERS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ITS
# CONTRIBUTERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.

# Audible Ping
#  This script wraps around ping and produces a sound with
#  the pitch based on the latency.

use Audio::DSP;
use strict;

my $DSP;

sub init {
    $DSP = new Audio::DSP(buffer   => 4096,
			  channels => 1,
			  format   => 8,
                          rate     => 16000);

    if(!$DSP->init()) { die "ERROR:  Init failed!\n"; }
    open(FD,"ping @ARGV|") || die "ERROR: Couldn't start ping\n"; 
    $SIG{INT} = 'sigint';
}

sub sigint {
    while(<FD>) { print $_; }
    exit(@$>>8);
}

sub fini {
    $DSP->close();
    close(FD);
}

sub play {
    my ($freq) = @_;
    my $buf = '';

    $freq  += 20;  # Pinging the loopback or local machines 
                   # should make noise

    for(1 .. 1000) {
       $buf .=  int(sin(6.28 * ($_ % $freq ) / 160) * 127);
    }

    $DSP->dwrite($buf);
    $DSP->sync();
}

sub main {
    init();

    while(<FD>)
    {
	my ($time) = $_ =~ /time=([\d\.]+) ms$/;
	print $_;
	if($time >= 0) { play($time); }
    }

    fini();
}

main();