1#!/usr/local/bin/perl 2 3# festival_client.pl - a perl socket client for festival 4# 5# Copyright (C) 1997 6# Kevin A. Lenzo (lenzo@cs.cmu.edu) 7/97 7# All rights reserved. 8# 9# The authors hereby grant permission to use, copy, modify, distribute, 10# and license this software and its documentation for any purpose, provided 11# that existing copyright notices are retained in all copies and that this 12# notice is included verbatim in any distributions. No written agreement, 13# license, or royalty fee is required for any of the authorized uses. 14# Modifications to this software may be copyrighted by their authors 15# and need not follow the licensing terms described here, provided that 16# the new terms are clearly indicated on the first page of each file where 17# they apply. 18# 19# IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY 20# FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 21# ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY 22# DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE 23# POSSIBILITY OF SUCH DAMAGE. 24# 25# THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, 26# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, 27# FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE 28# IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE 29# NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR 30# MODIFICATIONS. 31# 32######################################################################### 33# 34# A good deal of this was taken from the example in the 35# perlipc man page. The rest is simply the Festival-specific 36# stuff. 37 38use IO::Socket; 39 40package Festival; 41 42my ($audio_command, $audio_file, $file_stuff_key); 43my ($host, $port, $kidpid, $handle, $line); 44 45$wave_type = "nist"; # the type of the audio files 46$audio_command = "na_play"; # your local audio play command 47 48# uncomment the next line if your audio command requires a file 49# $audio_file = "/tmp/client_tmp$$.nist"; # temp file for waveforms 50 51$file_stuff_key = "ft_StUfF_key"; # defined in speech tools 52 53$host = shift || 'localhost'; 54$port = shift || 1314; 55if ($host eq "-h") { 56print STDOUT " 57 Usage: 58 59 $0 [<server> [<port>]] 60 61 OR 62 63 $0 -h 64 65 perl client for the Festival text-to-speech server 66 67 Lines that do not begin with a ( are treated as text 68 to be spoken. Those that do begin with a ( are assumed 69 to Scheme commands to festival and are sent without 70 alteration. Use `quit' or `exit' to quit. 71 72 Note that a server must be started before the client 73 will work. 74 75 Use the `-h' (help) option for this message. 76 77"; 78 79 exit(1); 80} 81 82# create a tcp connection to the specified host and port 83 84$handle = IO::Socket::INET->new(Proto => "tcp", 85 PeerAddr => $host, 86 PeerPort => $port) 87 or die " 88 Can't connect to port $port on $host: $! 89 (Are you sure the server is running and accepting connections?) 90 91"; 92 93$handle->autoflush(1); # so output gets there right away 94print STDERR "[Connected to $host:$port]\n"; 95 96# tell the server to send us back a 'file' of the right type 97print $handle "(Parameter.set 'Wavefiletype '$wave_type)\n"; 98 99# split the program into two processes, identical twins 100die "can't fork: $!" unless defined($kidpid = fork()); 101 102# the if{} block runs only in the parent process 103if ($kidpid) { 104 # the parent handles the input so it can exit on quit 105 106 while (defined ($line = <STDIN>)) { 107 last if ($line =~ /^(quit|exit)$/); 108 109 if ($line =~ /^\(/) { 110 # just send it wholesale if it's a ( ) 111 print $handle $line; 112 } else { 113 # otherwise assume it's text to be spoken 114 chomp $line; 115 print $handle "(tts_textall \"$line\" 'file)\n"; 116 } 117 } 118 kill("TERM", $kidpid);# send SIGTERM to child 119} 120# the else{} block runs only in the child process 121else { 122 # the child is forked off to get the results from the server 123 undef $line; 124 while (($line = $remains) || defined ($line = <$handle>)) { 125 undef $remains; 126 if ($line eq "WV\n") { # we have a waveform coming 127 undef $result; 128 if ($audio_file) { 129 open(AUDIO, ">$audio_file"); 130 } else { 131 open(AUDIO, "| $audio_command"); 132 } 133 while ($line = <$handle>) { 134 if ($line =~ s/$file_stuff_key(.*)$//s) { 135 $remains = $1; 136 print AUDIO $line; 137 last; 138 } 139 print AUDIO $line; 140 } 141 close AUDIO; 142 143 if ($audio_file) { 144 # call the command if we weren't piping 145 system("$audio_command $audio_file"); 146 147 # remove the evidence 148 unlink($audio_file); 149 } 150 } elsif ($line eq "LP\n") { 151 while ($line = <$handle>) { 152 if ($line =~ s/$file_stuff_key(.*)$//s) { 153 $remains = $1; 154 print STDOUT $line; 155 last; 156 } 157 print STDOUT $line; 158 } 159 } else { 160 # if we don't recognize it, echo it 161 print STDOUT $line; 162 } 163 } 164} 165