#!/usr/bin/perl

# semaphoreMovie
# This script is a text to semaphore converter - it creates a QuickTime movie
# showing the given message encoded using semaphore flags.
# (http://en.wikipedia.org/wiki/Flag_semaphore).
# The text is read from STDIN or from the files given as command-line arguments.
# The image files are modified versions of those from the above Wikipedia page.
# The sequence of images is turned into a movie using the "qt_tools" available
# from http://omino.com/sw/qt_tools/
#
# Cameron Hayne (macdev@hayne.net)  August 2009

use strict;
use warnings;
use File::Path;

my $wantAnnotated = 0;
my $imageDir1 = 'FlagImages';
my $imageDir2 = 'FlagImagesAnnotated';
my %flags = (
            # letters
            "a" => "Alpha",
            "b" => "Bravo",
            "c" => "Charlie",
            "d" => "Delta",
            "e" => "Echo",
            "f" => "Foxtrot",
            "g" => "Golf",
            "h" => "Hotel",
            "i" => "India",
            "j" => "Juliet",
            "k" => "Kilo",
            "l" => "Lima",
            "m" => "Mike",
            "n" => "November",
            "o" => "Oscar",
            "p" => "Papa",
            "q" => "Quebec",
            "r" => "Romeo",
            "s" => "Sierra",
            "t" => "Tango",
            "u" => "Uniform",
            "v" => "Victor",
            "w" => "Whisky",
            "x" => "X-ray",
            "y" => "Yankee",
            "z" => "Zulu",
            # numbers
            "0" => "Kilo",
            "1" => "Alpha",
            "2" => "Bravo",
            "3" => "Charlie",
            "4" => "Delta",
            "5" => "Echo",
            "6" => "Foxtrot",
            "7" => "Golf",
            "8" => "Hotel",
            "9" => "India",
            # special
            " " => "Ready",
            "#" => "Numeric",
            "@" => "Juliet",
    );

sub usageError()
{
    my $options = "[-annotated]";
    print STDERR "usage: semaphoreMovie $options [filename]\n";
    exit(1);
}

sub handleCommandLineOptions()
{
    use Getopt::Long;

    GetOptions(
                'annotated'     => \$wantAnnotated,
                ) or usage_error();
}


# TODO: need to put a "rest" between doubled-letters in a word
MAIN:
{
    handleCommandLineOptions();

    my $time = time();
    my $seqDir = "Sequence$time";
    my $imageDir = $wantAnnotated ? $imageDir2 : $imageDir1;

    undef $/;  # slurp mode
    # get message in lowercase
    my $messageText = lc(<>);
    # change all non-alphanum to two spaces
    $messageText =~ s/[^a-z0-9]/  /g;
    # put a single space between doubled letters or digits
    $messageText =~ s/([a-z0-9])(?=\1)/$1 /g;
    # insert '#' for alpha to num transition
    $messageText =~ s/([a-z]\s*)(?=[0-9])/$1#/g;
    # insert '@' for num to alpha transition
    $messageText =~ s/([0-9]\s*)(?=[a-z])/$1@/g;
    #print "$messageText\n"; exit;

    my $numChars = length($messageText);
    my $maxDigits =  1 + int(log($numChars) / log(10));

    mkdir $seqDir;
    chdir $seqDir or die "chdir failed: $!\n";
    my $format = "char_%0${maxDigits}d.png";
    my $count = 0;
    foreach my $ch (split(//, $messageText))
    {
        my $filename = sprintf($format, $count++);
        symlink("../$imageDir/$flags{$ch}.png", "$filename")
            or die "symlink failed: $!\n";
    }

    # now convert the sequence of images to a movie
    my $qtExport = '/usr/local/bin/qt_export';
    my $seqRate = 1;
    my $options = " --sequencerate=$seqRate"
                . " --video=mjpa";
    my $inputName = sprintf($format, 0);
    my $outputName = "movie${time}.mov";
    my $command = "$qtExport $options $inputName ../$outputName";
    system($command);
    chdir ".." or die "chdir failed: $!\n";
    rmtree $seqDir;
    print "movie file: $outputName\n";
    system("open $outputName");
}


