#!/usr/bin/perl
#!/usr/bin/perl -d:ptkdb

###############################################################################
#
# tts.pl -  Text To Speech
#
# Copyright (C) 2009  Rainer Walther  (rainerwalther-mail@web.de)
#
# Creative Commons Lizenz mit den Zusaetzen (by, nc, sa)
#
# Es ist Ihnen gestattet: 
#     * das Werk vervielfältigen, verbreiten und öffentlich zugänglich machen
#     * Abwandlungen bzw. Bearbeitungen des Inhaltes anfertigen
# 
# Zu den folgenden Bedingungen:
#     * Namensnennung.
#       Sie müssen den Namen des Autors/Rechteinhabers in der von ihm festgelegten Weise nennen.
#     * Keine kommerzielle Nutzung.
#       Dieses Werk darf nicht für kommerzielle Zwecke verwendet werden.
#     * Weitergabe unter gleichen Bedingungen.
#       Wenn Sie den lizenzierten Inhalt bearbeiten oder in anderer Weise umgestalten,
#       verändern oder als Grundlage für einen anderen Inhalt verwenden,
#       dürfen Sie den neu entstandenen Inhalt nur unter Verwendung von Lizenzbedingungen
#       weitergeben, die mit denen dieses Lizenzvertrages identisch oder vergleichbar sind.
# 
# Im Falle einer Verbreitung müssen Sie anderen die Lizenzbedingungen, unter welche dieses
# Werk fällt, mitteilen. Am Einfachsten ist es, einen Link auf diese Seite einzubinden.
# 
# Jede der vorgenannten Bedingungen kann aufgehoben werden, sofern Sie die Einwilligung
# des Rechteinhabers dazu erhalten.
# 
# Diese Lizenz lässt die Urheberpersönlichkeitsrechte unberührt.
# 
# Weitere Details zur Lizenzbestimmung gibt es hier:
#   Kurzform: http://creativecommons.org/licenses/by-nc-sa/3.0/de/
#   Komplett: http://creativecommons.org/licenses/by-nc-sa/3.0/de/legalcode
#
###############################################################################
# 2009-08-08 0.0.1 rw created
# 2010-07-01 0.5.0 rw TTS system messages closer to current situation
#
###############################################################################

$Version{'tts.pl'} = "0.5.0 - 2010-07-01";

# Packages
use threads;                # http://search.cpan.org/~jdhedden/threads-1.72/threads.pm
                            # http://perldoc.perl.org/threads.html
use threads::shared;        # http://search.cpan.org/~jdhedden/threads-shared-1.28/shared.pm
use Thread::Queue;          # http://search.cpan.org/dist/Thread-Queue-2.11/lib/Thread/Queue.pm
use Time::HiRes qw(usleep); # http://search.cpan.org/~jhi/Time-HiRes-1.9719/HiRes.pm

# eSpeak software required, download from: http://espeak.sourceforge.net/

# Queues for Sending Mesages to TTS Thread
$TtsSendQueueLow    = Thread::Queue->new(); # for low prio messages
$TtsSendQueueMedium = Thread::Queue->new(); # for medium prio messages
$TtsSendQueueHigh   = Thread::Queue->new(); # for high prio messages

share (%System);
share (%MkOsd);

$TtsMute = 0;   # Mute audio switch

# Main loop, never ending
sub TtsLoop()
    {

    # say hello

    # Parameter
    local $Program = $Cfg->{'tts'}->{'Program'}  || "C:/Program Files/eSpeak/command_line/espeak.exe";
    local $Options = $Cfg->{'tts'}->{'Options'}  || "-v de -a 200 -b";
    local $Welcome = $Cfg->{'tts'}->{'Welcome'}  || "Starte Mischn Kockpit";   

    if ( ! -f $Program )
        {
        print "TTS: Program \"$Program\" does not exist. Exit\n";
        return;
        }

    # say hello
    &TtsCall ($Welcome);

    while ( 1 )
        {	
        # process all High prio Messages
        while ( $TtsSendQueueHigh->pending() > 0 )
            {
            my $Text = $TtsSendQueueHigh->dequeue(1);
            &TtsCall($Text);
            }

        # process all Medium prio Messages
        while ( $TtsSendQueueMedium->pending() > 0  and
                $TtsSendQueueHigh->pending() == 0 )
            {
            my $Text = $TtsSendQueueMedium->dequeue(1);
            &TtsCall($Text);
            }

        # Check Low prio Messages one by one
        if ( $TtsSendQueueLow->pending() > 0  and
             $TtsSendQueueMedium->pending() == 0  and
             $TtsSendQueueHigh->pending() == 0 )
            {
            my $Text = $TtsSendQueueLow->dequeue(1);
            &TtsCall($Text);
            }

        usleep (100000); # 100ms
        }
    } 


# call TTS program
sub TtsCall()
    {
    my ($Text) = @_;

    # Eval, if Text is function Call "&Fct()";
    if ( substr($Text, 0, 1) eq "&" )
        {
        $Text = eval "$Text";
        }

    my $Cmd = "\"$Program\" $Options \"$Text\"";
    system $Cmd;
    }


# Add Text to TTS-Queue
sub TtsSpeak ()
    {
    my ($Prio, $Text) = @_;

    if ( ! $TtsMute  and  $Cfg->{'tts'}->{'Active'} =~ /y/i )
        {
        if ( $Prio eq 'HIGH' ) 
            {
            $TtsSendQueueHigh->enqueue($Text);
            }
        elsif ( $Prio eq 'MEDIUM' ) 
            {
            $TtsSendQueueMedium->enqueue($Text);
            }
        else
            {
            $TtsSendQueueLow->enqueue($Text);
            }
        }
    }
	

# Clear pending Messages
sub TtsClear ()
    {
    my  ($Prio) = @_;

    while ($Prio eq 'HIGH'  and  $TtsSendQueueHigh->pending() >0 )
        {
        $TtsSendQueueHigh->dequeue();
        }
    while ($Prio eq 'MEDIUM' and $TtsSendQueueMedium->pending() >0 )
        {
        $TtsSendQueueMedium->dequeue();
        }
    while ($Prio eq 'LOW' and $TtsSendQueueLow->pending() >0 )
        {
        $TtsSendQueueLow->dequeue();
        }
    }

# Mute TTS
sub TtsMute ()
    {
    my ($Param) = @_;

    $TtsMute = $Param;
    }


# TTS evalution functions
sub TtsAltitude
    {
    if ( $System{'Alt'} < 0 )
        {
        return sprintf ("$Translate{'TtsAltitudeNegative'}", abs($System{'Alt'}) );
        }
    else
        {
        return sprintf ("$Translate{'TtsAltitude'}", $System{'Alt'} );
        }
    }


sub TtsFlightTime
    {
    my $Min = int ( ($System{'MkFlyingTime'} +1) / 60);
    my $Sec = int ( ($System{'MkFlyingTime'} +1) % 60);
    my $Text = sprintf ("$Translate{'TtsFlightTimeMinSec'}", $Min, $Sec);
    if ( $Min == 0 )
        {
        $Text = sprintf ("$Translate{'TtsFlightTimeSec'}", $Sec);
        }
    return $Text;
    }

sub TtsUBat
    {
    my ($Volt, $Tenth) = split '\.', $System{'UBat'};
    return sprintf ("$Translate{'TtsBattery'}", $Volt, $Tenth);
    }

sub TtsHomeDist
    {
    return sprintf ("$Translate{'TtsHomeDist'}", int ($System{'HomeDist'} + 0.5) );
    }

sub TtsTargetDist
    {
    return sprintf ("$Translate{'TtsTargetDist'}", int ($System{'TargetDist'} + 0.5) );
    }

sub TtsSatsInUse
    {
    return sprintf ("$Translate{'TtsSatellite'}", $MkOsd{'SatsInUse'});
    }

# Hauptprgramm
#	

if ( $0 =~ /tts.pl$/i )
    {
    # Program wurde direkt aufgerufen
    &TtsLoop();

    # should never exit
    }
	
1;

__END__
