#!/usr/bin/perl -w
#
# Run festival in text to speech mode, as a server. 

use IO::Socket;
use IO::Select;
use POSIX;

my $port=5001;

my $server= IO::Socket::INET->new(
        LocalPort => $port,
	Proto => 'tcp',
	Listen => 10,
	Reuse => 1,
) || die "Error binding server socket: $@\n";

my $select=IO::Select->new($server);

open (FESTIVAL,"|festival --tts @ARGV") || die "Error starting festival :$!\n";
FESTIVAL->autoflush(1);

while (1) {
	foreach my $client ($select->can_read(1)) {
		if ($client == $server) {
			# New connection.
			$client=$server->accept;
			$select->add($client);
		}
		else {
			# Read data from client.
			$data='';
			my $rv=$client->recv($data,POSIX::BUFSIZ, 0);
			unless (defined $rv && length $data) {
				# EOF from client.
				$select->remove($client);
				close $client;
			}
			
			$inbuffer{$client}.=$data;
			
			# Do we have a full line of data?
			while ($inbuffer{$client}=~s/(.*\n)//) {
				print FESTIVAL $1;
				# Festival will not say a line of text until it
				# sees the end of a sentance or until it sees
				# another word. Since we won't want it waiting
				# on another word, use this trick to make it speak
				# immediatly.
				print FESTIVAL "\n.\n";
			}
		}
	}
}
