#!/Perl
use strict;
use warnings;
use Win32::OLE;
use Data::Dumper;

$| = 1;
# just for LOG FILE ouput ...
my ($LOG);
my $write_log = 0;
my $verb = 1; # increase to 9 to see more output
my $outfile = "temp.$0.txt"; # note name of perl file used as base
if ( open( $LOG, ">$outfile" ) ) {
    $write_log = 1; # we have a LOG file
} else {
    $write_log = 0;
    prt( "WARNING: Unable to open $outfile LOG ...\n" );
}

# from : http://public.activestate.com/authors/jandubois/Perl/TPC3/fun.html
# found these tit-bits ... and later used some of the ideas indicated ...
# like the DESTROY, I used to build a 'cycle()' service, letting the speech continue
#package Speech;
#sub TIEHANDLE {
#      my $voice = Win32::OLE->new('Speech.VoiceText');
#      $voice->Register('', 'Perl');
#      bless \$voice => shift;}
#sub PRINT {
#      my $voice = shift;
#      my $text = join('', @_);
#      print STDOUT $text, "\n";
#      $$voice->Speak($text, 0); }
#sub DESTROY {
#      my $voice = shift;
#      sleep(1) while $$voice->IsSpeaking;}
#package main;
#tie *SPEECH, 'Speech'; END {untie *SPEECH}
#print SPEECH "It is now ", scalar localtime;
#
# prerequisits -
# downloaded from : http://www.microsoft.com/msagent/downloads/user.asp#tts
# dtemp\msspeech - actcnc.exe lhttseng.exe MSagent.exe spchapi.exe
# ran all of these ... not sure exactly what was installed ...
# now I can at least get the voice engine ...
# more from : http://www.microsoft.com/downloads/details.aspx?FamilyId=5E86EC97-40A7-453F-B0EE-6583171B4530&displaylang=en#filelist
# downloaded and installed the SpeechSDK511.exe
# which points to more at : http://www.microsoft.com/downloads/details.aspx?familyid=1194ED95-7A23-46A0-BBBC-06EF009C053A&displaylang=en
# I loaded, converted to MSVC8 (Microsoft Visual C/C++ NET 2005 Express) the 'SimpleTTS.vb' sample,
# and it ran fine ... saw SpeechLib.SpVoice in this VB application sample, and tried it -
#my $voice = Win32::OLE->new('SpeechLib.SpVoice') or die "Unable to get voice engine ...\n". Win32::OLE->LastError() . "\n";
# BUT IT FAILED ...
# but this continues to work ...
my $voice = Win32::OLE->new('Speech.VoiceText') 
or die "Unable to get voice engine ...\n". Win32::OLE->LastError() . "\n";
# tried all sorts of things like ...
#$voice->{Enabled} = 1;
#$voice->{IsSpeaking} = 0;
#cycle($voice);
# read again that you need to do Register first ...
$voice->Register('', 'Perl');
##bless \$voice => shift;
prt( "Got voice $voice ". Dumper( $voice ) . "\n" );
# NOW Dumper shows -
# Got voice Win32::OLE=HASH(0x18361d0) $VAR1 = bless( {
#                 'Speed' => 150,
#                 'Enabled' => 1,
#                 'IsSpeaking' => 0
#               }, 'Win32::OLE' );
# where as previously it showed each item as 'undef' ...
# **** IT IS WORKING FINE ****
###$voice->Speak("It is now ". scalar localtime, 0);
my $orgspd = 150;
# the speech engine REMEMBERS changes to this speed parameter - it started at 150, so
$voice->{Speed} = $orgspd;
vprt( $voice, "Speed: ".$voice->{Speed}.". It is now ", scalar localtime );
prt( "Played $voice ". Dumper( $voice ) . "\n" );
prt( "Try some 'Speed' changes ...\n" );
$voice->{Speed} = 100; # slower = TOO SLOW
vprt( $voice, "Speed: ".$voice->{Speed}.". It is now ", scalar localtime );
prt( "That made it SLOWER, and I already thought it was TOO SLOW, so ...\n" );
$voice->{Speed} = 250; # fast = TOO FAST
vprt( $voice, "Speed: ".$voice->{Speed}.". It is now ", scalar localtime );
$voice->{Speed} = 200; # I like about this ...
vprt( $voice, "Speed: ".$voice->{Speed}.". It is now ", scalar localtime );
vprt( $voice, "Now headed for exit ...");
exit;

# I note from : http://cpan.uwinnipeg.ca/htdocs/Win32-SAPI4/Win32/SAPI4.pm.html
# that there is another module for 'speech' ...
# use Win32::SAPI4;
#    my $vt   = Win32::SAPI4::VoiceText->new();
#    my $dss  = Win32::SAPI4::DirectSpeechSynthesis->new();
#    my $dsr  = Win32::SAPI4::DirectSpeechRecognition->new();
#    my $vtel = Win32::SAPI4::VoiceTelephony->new();    
#    my $vd   = Win32::SAPI4::VoiceDictation->new();
#    my $vc   = Win32::SAPI4::VoiceCommand->new();
# PREREQUISITES
# The Microsoft Speech API 4.0. It can be downloaded for free from http://www.microsoft.com/speech
# (go to the 'old versions' and find the 4.0 version)
# and at : http://cpan.uwinnipeg.ca/htdocs/Win32-SAPI5/Win32/SAPI5.html
#use Win32::SAPI5;
#    my $object = Win32::SAPI5::SpVoice->new();
#    my $object = Win32::SAPI5::SpNotifyTranslator->new();
#    my $object = Win32::SAPI5::SpObjectTokenCategory->new();
#    my $object = Win32::SAPI5::SpObjectToken->new();
#    my $object = Win32::SAPI5::SpResourceManager->new();
#    my $object = Win32::SAPI5::SpStreamFormatConverter->new();
#    my $object = Win32::SAPI5::SpMMAudioEnum->new();
#    my $object = Win32::SAPI5::SpMMAudioIn->new();
#    my $object = Win32::SAPI5::SpMMAudioOut->new();
#    my $object = Win32::SAPI5::SpRecPlayAudio->new();
#    my $object = Win32::SAPI5::SpStream->new();
#    my $object = Win32::SAPI5::SpSharedRecoContext->new();
#    my $object = Win32::SAPI5::SpInprocRecognizer->new();
#    my $object = Win32::SAPI5::SpSharedRecognizer->new();
#    my $object = Win32::SAPI5::SpLexicon->new();
#    my $object = Win32::SAPI5::SpUnCompressedLexicon->new();
#    my $object = Win32::SAPI5::SpCompressedLexicon->new();
#    my $object = Win32::SAPI5::SpPhoneConverter->new();
#    my $object = Win32::SAPI5::SpNullPhoneConverter->new();
#    my $object = Win32::SAPI5::SpTextSelectionInformation->new();
#    my $object = Win32::SAPI5::SpPhraseInfoBuilder->new();
#    my $object = Win32::SAPI5::SpAudioFormat->new();
#    my $object = Win32::SAPI5::SpWaveFormatEx->new();
#    my $object = Win32::SAPI5::SpInProcRecoContext->new();
#    my $object = Win32::SAPI5::SpCustomStream->new();
#    my $object = Win32::SAPI5::SpFileStream->new();
#    my $object = Win32::SAPI5::SpMemoryStream->new();
#######################################################
#
# Partial OLE Class List use Win32::OLE; use Win32::OLE qw(in valof with OVERLOAD EVENTS);
# use Win32::OLE::Const 'Microsoft DAO';
# use Win32::OLE::Const 'Microsoft ActiveX Data Objects';
# my $Access = Win32::OLE->new('Access.Application', 'Quit');
# my $Conn = Win32::OLE->new('ADODB.Connection'); # creates a connection object
# my $RS = Win32::OLE->new('ADODB.Recordset');    # creates a recordset object
# use Win32::OLE::Variant;
# use Win32::OLE::Const 'Microsoft Excel';
# use Win32::OLE::NLS qw(:DEFAULT :LANG :SUBLANG);
# my $Excel = Win32::OLE->new('Excel.Application', 'Quit');
# my $IE  = Win32::OLE->new("InternetExplorer.Application")
# Win32::OLE->WithEvents($IE,\&Event,"DWebBrowserEvents2");
# Win32::OLE->MessageLoop(); Win32::OLE->QuitMessageLoop();
# Win32::OLE->SpinMessageLoop;
# my $Count = Win32::OLE->EnumAllObjects(sub { });
# my $Class = Win32::OLE->QueryObjectType($Object);
# my $voice = Win32::OLE->new('Speech.VoiceText') 
# use Win32::OLE::Const 'Microsoft Word';
# my $Word = Win32::OLE->new('Word.Application', 'Quit');
# my $wd = Win32::OLE::Const->Load("Microsoft Word 8.0 Object Library");
# $wd = Win32::OLE::Const->Load("Microsoft Word 9.0 Object Library");
# $wd = Win32::OLE::Const->Load("Microsoft Word 10.0 Object Library");
# $enumerate = new Win32::OLE::Enum($paragraphs);
# Collections - Characters Words Sentences Paragraphs Sections HeadersFooters 
# my $xmlDoc = Win32::OLE->new('MSXML2.DOMDocument.3.0') or mydie( "new() failed" );
# All the 'classes' appear to be enumerated in the registry, under HKEY_CLASSES_ROOT
#
##########################################################################################
#### SUBS BELOW
###############

sub cycle {
      my $v = shift;
      ###sleep(1) while $$v->IsSpeaking;
      sleep(1) while $v->IsSpeaking;
}

sub vprt {
      my $v = shift;
      my $t = join('', @_);
      # print STDOUT $t, "\n";
      prt( "$t\n" ); # show the text being SPOKEN ...
      $v->Speak($t, 0); # SPEAK THE TEXT
      ###$$v->Speak($t, 0);
	  cycle($v);
}

################################
### output and log file
sub wlog {
	my $ml = shift;
	print $LOG $ml;
}

sub prt {
	my $m = shift;
	if ($write_log) {
		wlog($m);
	}
	print $m;
}

sub prtv9 {
	my $ms = shift;
	if ($verb > 8) {
		prt($ms);
	}
}

sub mydie {
	my $msg = shift;
	if ($write_log) {
		wlog($msg);
	}
	die $msg;
}

# eof - autosp01.pl

