1#
2# $Id: Vgetty.pm,v 1.4 2002/02/20 17:34:35 gert Exp $
3#
4# Copyright (c) 1998 Jan "Yenya" Kasprzak <kas@fi.muni.cz>. All rights
5# reserved. This package is free software; you can redistribute it and/or
6# modify it under the same terms as Perl itself.
7#
8
9package Modem::Vgetty;
10
11use FileHandle;
12use POSIX;
13use strict;
14
15use Carp;
16
17use vars qw($testing $log_file $VERSION);
18
19$VERSION='0.03';
20$testing = 0;
21$log_file = '/var/log/voicelog';
22
23my @event_names = qw(BONG_TONE BUSY_TONE CALL_WAITING DIAL_TONE
24	DATA_CALLING_TONE DATA_OR_FAX_DETECTED FAX_CALLING_TONE
25	HANDSET_ON_HOOK LOOP_BREAK LOOP_POLARITY_CHANGE NO_ANSWER
26        NO_CARRIER
27	NO_DIAL_TONE NO_VOICE_ENERGY RING_DETECTED RINGBACK_DETECTED
28	RECEIVED_DTMF SILENCE_DETECTED SIT_TONE TDD_DETECTED
29	VOICE_DETECTED UNKNOWN_EVENT);
30
31
32
33sub new {
34	my ($class, $infd, $outfd, $pid) = @_;
35	my $self = bless {}, $class;
36
37        $infd  ||= $ENV{'VOICE_INPUT'};
38        $outfd ||= $ENV{'VOICE_OUTPUT'};
39        $pid   ||= $ENV{'VOICE_PID'};
40
41
42	$self->{'IN'} = FileHandle->new_from_fd( $infd, "r" )
43		|| return;
44	$self->{'OUT'} = FileHandle->new_from_fd( $outfd, "w" )
45		|| return;
46	$self->{'IN'}->autoflush;
47	$self->{'OUT'}->autoflush;
48
49        $self->{'PIPE_BUF_LEN'} = POSIX::_POSIX_PIPE_BUF ;
50
51	$self->{'PID'} = $pid;
52	$self->{'LOG'} = FileHandle->new();
53
54	if ($testing > 0) {
55		$self->{'LOG'}->open(">>$log_file") || return undef;
56		$self->{'LOG'}->autoflush;
57		$self->{'LOG'}->print("-----------\n### Pid $$ opening log\n----------\n");
58	}
59        $self->{'EVENTS'} = { map { $_ => {} } @event_names };
60
61	$self->init();
62
63        return $self;
64
65}
66
67
68# The basic two functions (a low-level interface);
69sub receive {
70	my $self = shift;
71	my $input;
72	while(1) {
73		$input = $self->{IN}->getline;
74		chomp $input;
75		$self->{LOG}->print("received: $input\n") if $testing > 0;
76		last unless defined $self->{EVENTS}->{$input};
77		# Handle the event:
78		my $dtmf = '';
79		if ($input eq 'RECEIVED_DTMF') {
80			$dtmf = $self->{IN}->getline;
81			chomp $dtmf;
82			$self->{LOG}->print("DTMF $dtmf\n") if $testing > 0;
83		}
84		for (keys %{$self->{EVENTS}->{$input}}) {
85			$self->{LOG}->print("Running handler $_ for event $input\n") if $testing > 0;
86			&{$self->{EVENTS}->{$input}->{$_}}($self, $input, $dtmf);
87			$self->{LOG}->print("Handler $_ for event $input finished.\n") if $testing > 0;
88		}
89	}
90	$input;
91}
92
93sub send {
94	my $self = shift;
95	my $output = shift;
96	$self->{OUT}->print("$output\n");
97	kill PIPE => $self->{PID};
98	$self->{LOG}->print("sent: $output\n") if $testing > 0;
99}
100
101sub expect {
102	my $self = shift;
103        $self->{LOG}->print("expecting: ", (join '|', @_), "\n")
104	    if $testing > 0;
105	my $received = $self->receive || return undef;
106	for my $expected (@_) {
107		return $received if $received eq $expected;
108	}
109	return undef;
110}
111
112sub waitfor {
113	my $self = shift;
114	my $string = shift;
115        while (($self->expect($string) || "") ne $string) { }
116}
117
118sub chat {
119	my $self = shift;
120	my @chatscript = @_;
121	my $received = 0;
122	for my $cmd (@chatscript) {
123		$received = 1 ^ $received;
124		next if $cmd eq '';
125		if ($received == 1) {
126			return undef unless $self->expect($cmd);
127
128		} else {
129			$self->send($cmd);
130		}
131	}
132	return 1;
133}
134
135# Initial chat
136sub init {
137	my $self = shift;
138	$self->chat ('HELLO SHELL', 'HELLO VOICE PROGRAM', 'READY');
139#	$self->chat ('HELLO SHELL', 'HELLO VOICE PROGRAM');
140
141        return $self;
142}
143
144# Setting the voice device
145sub device {
146	my $self = shift;
147	my $dev = shift;
148        $self->{LOG}->print("attempting to set device $dev") if $testing;
149	$self->chat ('', "DEVICE $dev", 'READY') || return undef;
150	$self->{DEVICE}=$dev;
151        $self->{LOG}->print("sucessfully set device $dev") if $testing;
152}
153
154sub shutdown {
155	my $self = shift;
156	$self->chat ('', 'GOODBYE', 'GOODBYE SHELL');
157	$self->{IN}->close;
158	$self->{OUT}->close;
159	$self->{LOG}->close if $testing > 0;
160}
161
162sub DESTROY {
163	my $self = shift;
164	$self->shutdown;
165}
166
167sub enable_events {
168	my $self = shift;
169	$self->chat ('', 'ENABLE EVENTS', 'READY');
170}
171
172sub disable_events {
173	my $self = shift;
174	$self->chat ('', 'DISABLE EVENTS', 'READY');
175}
176
177sub beep {
178	my $self = shift;
179	my $freq = shift;
180	my $len = shift;
181	$self->chat ('', "BEEP $freq $len", 'BEEPING');
182}
183
184sub dial {
185	my $self = shift;
186	my $num = shift;
187	$self->chat ('', "DIAL $num", 'DIALING');
188}
189
190sub getty {
191	my $self = shift;
192	$self->chat ('', 'GET TTY') || return undef;
193	my $id = $self->receive;
194	$self->expect ('READY') || return undef;
195	return $id;
196}
197
198sub modem_type {
199#	To be implemented in vgetty first.
200	return undef;
201}
202
203sub autostop {
204	my $self = shift;
205	my $arg = shift;
206	$self->chat ('', "AUTOSTOP $arg", 'READY');
207}
208
209sub play {
210	my $self = shift;
211	my $file = shift;
212	$self->chat ('', "PLAY $file", 'PLAYING');
213}
214
215sub record {
216	my $self = shift;
217	my $file = shift;
218	$self->chat ('', "RECORD $file", 'RECORDING');
219}
220
221sub wait {
222	my $self = shift;
223	my $sec = shift;
224	$self->chat ('', "WAIT $sec", 'WAITING');
225}
226
227sub stop {
228	my $self = shift;
229	$self->send ('STOP'); # Nechceme READY.
230}
231
232sub add_handler {
233	my $self = shift;
234	my $event = shift;
235	my $name = shift;
236	my $func = shift;
237	if (!defined($self->{EVENTS}->{$event})) {
238		$self->{LOG}->print("add_handler: unknown event $event\n")
239			if $testing > 0;
240		return undef;
241	}
242	$self->{EVENTS}->{$event}->{$name} = $func;
243}
244
245sub del_handler {
246	my $self = shift;
247	my $event = shift;
248	my $name = shift;
249	if (!defined($self->{EVENTS}->{$event})) {
250		$self->{LOG}->print("del_handler: unknown event $event\n")
251			if $testing > 0;
252		return undef;
253	}
254	if (!defined($self->{EVENTS}->{$event}->{$name})) {
255		$self->{LOG}->print("del_handler: trying to delete nonexistent handler $name\n")
256			if $testing > 0;
257	} else {
258		delete $self->{EVENTS}->{$event}->{$name};
259	}
260}
261
262sub play_and_wait {
263	my $self = shift;
264	my $file = shift;
265	$self->play($file);
266	$self->waitfor('READY');
267}
268
269#####################################################################
270# The readnum routine, its private variables and the event handler. #
271#####################################################################
272
273my $_readnum_number = ''; # The number itself. Filled in by the event handler.
274my $_readnum_timeout = 10; # The value of the timeout. Fileld in by readnum.
275my $_readnum_in_timeout = 1; # 'READY' from timeout or from the '#' key?
276
277# Event handler. Just adds key to the $_readnum_number.
278sub _readnum_event {
279	my $self = shift;
280	my $input = shift; # Unused. Should be 'RECEIVED_DTMF'.
281	my $dtmf = shift;
282
283	if ($dtmf eq '#') { # Stop the reading now.
284		$_readnum_in_timeout = 0;
285		$self->stop;
286		$self->{LOG}->print("_readnum_event(): Got #; stopping\n");
287		return;
288	}
289	$_readnum_number .= $dtmf;
290	$self->stop;
291	$self->expect('READY');
292	# Restart the wait again.
293	$_readnum_in_timeout = 1;
294	$self->wait($_readnum_timeout);
295}
296
297sub readnum {
298	my $self = shift;
299	my $message = shift;
300	my $timeout = shift;
301	my $times = shift;
302	$_readnum_number = '';
303	$_readnum_in_timeout = 1;
304	$_readnum_timeout = $timeout if $timeout != 0;
305	$times = 3 if $times == 0;
306
307	# Install the handler.
308	$self->add_handler('RECEIVED_DTMF', 'readnum', \&_readnum_event);
309	while($_readnum_in_timeout != 0 && $_readnum_number eq ''
310		&& $times-- > 0) {
311		$self->play_and_wait($message);
312		last if $_readnum_in_timeout == 0;
313		while ($_readnum_in_timeout != 0) {
314			$self->wait($_readnum_timeout);
315			$self->expect('READY');
316		}
317	}
318	return undef if $times < 0;
319	$self->del_handler('RECEIVED_DTMF', 'readnum');
320	$self->stop;
321	$self->expect('READY');
322	$_readnum_number;
323}
324
3251;
326
327__END__
328
329=head1 NAME
330
331Modem::Vgetty - interface to vgetty(8)
332
333=head1 SYNOPSIS
334
335	use Modem::Vgetty;
336	$v = new Modem::Vgetty;
337
338	$string = $v->receive;
339	$v->send($string);
340	$string = $v->expect($str1, $str2, ...);
341	$v->waitfor($string);
342	$rv = $v->chat($expect1, $send1, $expect2, $send2, ...);
343
344	$ttyname = $v->getty;
345	$rv = $v->device($dev_type);
346	$rv = $v->autostop($bool);
347	$rv = $v->modem_type; # !!! see the docs below.
348
349	$rv = $v->beep($freq, $len);
350	$rv = $v->dial($number);
351	$rv = $v->play($filename);
352	$rv = $v->record($filename);
353	$rv = $v->wait($seconds);
354	$rv = $v->play_and_wait($filename);
355	$v->stop;
356
357	$v->add_handler($event, $handler_name, $handler);
358	$v->del_handler($event, $handler_name);
359	$v->enable_events;
360	$v->disable_events;
361
362	$number = $v->readnum($message, $tmout, $repeat);
363
364	$v->shutdown;
365
366=head1 DESCRIPTION
367
368C<Modem::Vgetty> is an encapsulation object for writing applications
369for voice modems using the B<vgetty(8)> or B<vm(8)> package. The answering
370machines and sofisticated voice applications can be written using this
371module.
372
373=head1 OVERVIEW
374
375I<Voice modem> is a special kind of modem, which (besides the normal
376data and/or fax mode) can communicate also in voice mode. It means
377it can record sounds it hears from the phone line to the file,
378Play-back recorded files, it can beep to the line, and it can detect
379various standard sounds coming from the line (busy tone, silence,
380dual tone modulation frequency (DTMF) keypad tones, etc).
381An example of the voice modem can be the ZyXEL U1496, US Robotics
382Sportster (not Courier), etc.
383
384To use this software with the voice modem you need to have the
385B<vgetty(8)> package installed. B<Vgetty> is distributed as a part of
386B<mgetty> package. In fact, B<vgetty> is a B<mgetty(8)> with the voice
387extensions. Vgetty has some support for scripting - when it receives
388an incoming call, it runs a voice shell (it is program specified in
389the B<voice.conf> file) as its child process, establishes the read
390and write pipes to it, and tells it the number of the appropriate
391descriptors in the environment variables. Voice shell can now
392communicate with B<vgetty>. It can tell B<vgetty> "Play this file",
393or "Record anything you hear to that file", or "Notify me when
394user hangs up", etc. Sophisticated voice systems and answering
395machines can be build on top of B<vgetty>.
396
397B<mgetty> (including the B<vgetty>) is available at
398the following URL:
399
400	ftp://alpha.greenie.net/pub/mgetty/
401
402Originally there was a (Bourne) shell interface to B<vgetty> only.
403The B<Modem::Vgetty> module allows user to write the voice shell in Perl.
404The typical use is to write a script and point the B<vgetty> to it
405(in B<voice.conf> file). The script will be run when somebody calls in.
406Another use is running voice shell from the B<vm(8)> program, which
407can for example dial somewhere and say something.
408
409=head1 QUICK START
410
411	#!/usr/bin/perl
412	use Modem::Vgetty;
413	my $v = new Modem::Vgetty;
414	$v->add_handler('BUSY_TONE', 'endh', sub { $v->stop; exit(0); });
415	local $SIG{ALRM} = sub { $v->stop; };
416	$v->enable_events;
417	$v->record('/tmp/hello.rmd');
418	alarm(20);
419	$v->waitfor('READY');
420	$v->shutdown;
421
422The above example installs the simple `exit now'-style handler for the
423B<BUSY_TONE> event (which is sent by B<vgetty> when user hangs up)
424and then records the B<hello.rmd> file. Put this text into a file
425and then point B<vgetty> to it in the B<voice.conf>. After you dial into
426your voice modem, you can record a 20-seconds of some message.
427Verify that B</tmp/hello.rmd> exists. Now delete the line contaning
428the word "record" and two subsequent lines and insert to the file
429the following line instead of them:
430
431	$v->play_and_wait('/tmp/hello.rmd');
432
433Now call the voice modem and listen to the sounds you have just recorded.
434
435
436=head1 METHODS
437
438=head2 Begin and end of communication
439
440The B<Modem::Vgetty> object will initialize the communication pipes to
441the B<vgetty> at the creation time - in the constructor. The closing
442of the communication is done via the B<shutdown> method:
443
444	$v->shutdown;
445
446The module will call this method itself from the destructor, if you do
447not call it explicitly.
448
449=head2 Low-level communication
450
451Users probably don't want to use these methods directly. Use the higher-level
452functions instead.
453
454=over 4
455
456=item receive
457
458This method returns a string received from the B<vgetty>. It parses
459the string for the event types and runs appropriate event handlers.
460If event handler is run it waits for another string.
461
462=item send($string)
463
464This method sends the string B<$string> to the B<vgetty> process.
465
466=item expect($string1, $string2, ...)
467
468Receives a string from B<vgetty> (using the B<receive> method described
469above) and returns it iff it is equal to one of the strings in the argument
470list. When something different is received, this method returns B<undef>.
471
472=item waitfor($string)
473
474Waits until the string B<$sring> is received from B<vgetty> (using the
475B<receive> method described above).
476=item chat($expect1, $sent1, $expect2, $sent2, ...)
477
478A chat-script with B<vgetty>. Arguments are interpreted as the received-sent
479string pairs. A received string equals to the empty string means that no
480B<receive> method will be called at that place. This can be used for
481constructing chat scripts beginning with the sent string instead of the
482received one.
483
484=back
485
486=head2 Vgetty control methods
487
488There are miscellaneous methods for controllig B<vgetty> and querying its
489status.
490
491
492=over 4
493
494=item getty
495
496Returns the name of the modem special file (e.g. B</dev/ttyC4>).
497
498=item device($name)
499
500Sets the port of the voice modem input and output is done to.
501Possible values are qw(NO_DEVICE DIALUP_LINE EXTERNAL_MICROPHONE
502INTERNAL_SPEAKER LOCAL_HANDSET).
503
504=item autostop($bool)
505
506With autostop on, the voicelib will automatically abort a
507play in progress and return READY. This is useful for faster
508reaction times for voice menus. Possible arguments are qw(ON OFF).
509B<Note:> The interface should probably be changed to accept the
510Perl boolean arguments (undef, something else). Returns defined
511value on success, undef on failure.
512
513=item modem_type
514
515B<vgetty> currently has no way of telling voice shell
516the type of the current modem. This method is a proposed interface
517for determining this type. Currently returns B<undef>. The appropriate
518low-level interface has to be implemented in B<vgetty> first.
519
520=back
521
522=head2 Voice commands
523
524=over 4
525
526=item beep($freq, $len)
527
528Sends a beep through the chosen device using given frequency (HZ) and length
529(in miliseconds).
530Returns a defined value on success or undef on failure.
531The state of the vgetty changes to "BEEPING" and B<vgetty>
532returns "READY" after a beep is finshed. Example:
533
534	$v->beep(50,10);
535	# Possibly do something else
536	$v->waitfor('READY');
537
538=item dial($number)
539
540Modem tries to dial a given number. The B<vgetty> changes its state
541to "DIALING" and returns "READY" after the dialing is finished.
542
543=item play($filename)
544
545The B<vgetty> tries to play the given file as a raw modem data.
546See the "Voice data" section for details on creating the raw modem data
547file. It changes the state to "PLAYING" and returns "READY" after
548playing the whole file.
549
550=item record($filename)
551
552The B<vgetty> records the voice it can hear on the line to the given file.
553It uses the raw modem data format (which can be re-played using the
554B<play> subroutine). B<vgetty> changes its state to "RECORDING" and
555you need to manually stop the recording using the B<stop> method
556after some time (or, you can set B<autostop> and wait for any event
557- silence, busy tone, etc).
558
559=item wait($seconds)
560
561The modem waits for a given number of seconds. Changes its state to
562"WAITING" and returns "READY" after the wait is finished. Example:
563
564	$v->wait(5);
565	$v->waitfor('READY');
566
567=item stop
568
569The B<vgetty> stops anything it is currently doing and returns to the
570command state. You must use B<stop> when you want to call another
571B<beep>, B<dial>, B<play>, B<record> or B<wait> before the previous
572one is finished. The B<vgetty> returns "READY" after the B<stop>
573is called. So it is possible to interrupt a main routine waiting
574for "READY" from the event handler:
575
576	my $dtmf;
577	$v->add_handler('RECEIVED_DTMF', 'readnum',
578		sub { my $self=shift; $self->stop; $dtmf = $_[2]; });
579	$v->enable_events;
580	$v->wait(10);
581	$v->waitfor('READY');
582
583In the previous example the B<waitfor> method can be finished either by
584the 10-second timeout expired, or by the 'READY' generated by the
585B<stop> in the event handler. See also the B<Events> section.
586
587=item play_and_wait($file)
588
589It is an abbreviation for the following:
590
591	$v->play($file);
592	$v->waitfor('READY');
593
594It is repeated so much time in the voice applications so I have decided
595to make a special routine for it. I may add the similar routines
596for B<dial>, B<record>, B<beep> and even B<wait> in the future releases.
597
598=back
599
600=head2 Event handler methods
601
602=over 4
603
604=item add_handler($event, $handler_name, $handler)
605
606Installs a call-back routine $handler for the event type $event.
607The call-back routine is called with three arguments. The first
608one is the Modem::Vgetty object itself, the second one is the
609event name and the third one is optional event argument.
610The B<$handler_name> argument can be anything. It is used when you
611want to delete this handler for identificating it.
612
613=item del_handler($event, $handler_name)
614
615This method deletes the handler $handler_name for the $event event.
616The result of unregistering the handler from the
617event handler of the same event is unspecified. It may or may not be
618called.
619
620=item enable_events
621
622Tells the B<vgetty> that the voice shell is willing to dispatch events.
623No events are sent by B<vgetty> until this method is called.
624
625=item disable_events
626
627Tells the B<vgetty> that the voice shell doesn't want to receive
628any events anymore.
629
630=back
631
632=head2 The B<readnum> method
633
634=over 4
635
636=item readnum($message, $tmout, $repeat)
637
638The applications often need to read the multi-digit
639number via the DTMF tones.  This routine plays the B<$message> to the
640voice object and then waits for the
641sequence of the DTMF keys finished by the `#' key. If no key is pressed
642for B<$tmout> of seconds, it re-plays the message again. It returns
643failure if no key is pressed after the message is played B<$repeat>-th
644time. It returns a string (a sequence of DTMF tones 0-9,A-D and `*')
645without the final `#'. When some DTMF tones are received and no terminating
646`#' or other tone is received for B<$tmout> seconds, the routine returns
647the string it currently has without waiting for the final '#'.
648DTMF tones are accepted even at the time the B<$message> is played.
649When the DTMF tone is received, the playing of the B<$message> is
650(with some latency, of course) stopped.
651
652B<NOTE:> The interface of this routine can be changed in future releases,
653because I am not (yet) decided whether the current interface is the best one.
654See also the B<EXAMPLES> section where the source code of this routine
655(and its co-routine) is discussed.
656
657=back
658
659=head1 EVENTS
660
661=head2 Introduction
662
663Events are asynchronous messages sent by B<vgetty> to the voice shell.
664The B<Modem::Vgetty> module dispatches events itself in the B<receive>
665method. User can register any number of handlers for each event.
666When an event arrives, all handlers for that event are called (in no
667specified order).
668
669=head2 Event types
670
671At this time, the B<Modem::Vgetty> module recognizes the following
672event types (description is mostly re-typed from the B<vgetty>
673documentation):
674
675=over 4
676
677=item BONG_TONE
678
679The modem detected a bong tone on the line.
680
681=item BUSY_TONE
682
683The modem detected busy tone on the line (when dialing to the busy
684number or when caller finished the call).
685
686=item CALL_WAITING
687
688Defined in IS-101 (I think it is when the line receives another call-in
689when some call is already in progress. -Yenya).
690
691=item DIAL_TONE
692
693The modem detected dial tone on the line.
694
695=item DATA_CALLING_TONE
696
697The modem detected data calling tone on the line.
698
699=item DATA_OR_FAX_DETECTED
700
701The modem detected data or fax calling tones on the line.
702
703=item FAX_CALLING_TONE
704
705The modem detected fax calling tone on the line.
706
707=item HANDSET_ON_HOOK
708
709Locally connected handset went on hook.
710
711=item HANDSET_OFF_HOOK
712
713Locally connected handset went off hook.
714
715=item LOOP_BREAK
716
717Defined in IS-101.
718
719=item LOOP_POLARITY_CHANGE
720
721Defined in IS-101.
722
723=item NO_ANSWER
724
725After dialing the modem didn't detect answer for the time
726give in dial_timeout in voice.conf.
727
728=item NO_CARRIER
729
730The caller has hung up. This event is detected only by the ISDN4Linux
731driver.
732
733=item NO_DIAL_TONE
734
735The modem didn't detect dial tone (make sure your modem is
736connected properly to your telephone company's line, or check
737the ATX command if dial tone in your system differs from
738the standard).
739
740=item NO_VOICE_ENERGY
741
742It means that the modem detected voice energy at the
743beginning of the session, but after that there was a
744period of some time of silence (the actual time can be set using
745the B<rec_silence_len> and B<rec_silence_treshold> parameters
746in B<voice.conf>).
747
748=item RING_DETECTED
749
750The modem detected an incoming ring.
751
752=item RINGBACK_DETECTED
753
754The modem detected a ringback condition on the line.
755
756=item RECEIVE_DTMF
757
758The modem detected a dtmf code. The actual code value
759(one of 0-9, *, #, A-D) is given to the event handler as the
760third argument.
761
762=item SILENCE_DETECTED
763
764The modem detected that there was no voice energy at the
765beginning of the session and after some time of silence
766(the actual time can be set using
767the B<rec_silence_len> and B<rec_silence_treshold> parameters
768in B<voice.conf>).
769
770=item SIT_TONE
771
772Defined in IS-101.
773
774=item TDD_DETECTED
775
776Defined in IS-101.
777
778=item VOICE_DETECTED
779
780The modem detected a voice signal on the line. IS-101 does
781not define, how the modem makes this decision, so be careful.
782
783=item UNKNOWN_EVENT
784
785None of the above :)
786
787=back
788
789=head1 VOICE DATA
790
791Voice shell can send the voice data to the modem using the B<play>
792method and record them using the B<record> method. The ".rmd" extension
793(Raw Modem Data) is usually used for these files. The ".rmd" is not
794a single format - every modem has its own format (sampling frequency,
795data bit depth, etc). There is a B<pvftools> package for converting
796the sound files (it is a set of filters similar to the B<netpbm> for image
797files). The B<pvftormd(1)> filter can be used to create the RMD files
798for all known types of modems.
799
800=head1 EXAMPLES
801
802=head2 Answering machine
803
804A simple answering machine can look like this:
805
806        #!/usr/bin/perl
807        use Modem::Vgetty;
808	my $voicemaster = 'root@localhost';
809	my $tmout = 30;
810	my $finish = 0;
811        my $v = new Modem::Vgetty;
812        $v->add_handler('BUSY_TONE', 'finish',
813		sub { $v->stop; $finish=1; });
814        $v->add_handler('SILENCE_DETECTED', 'finish',
815		sub { $v->stop; $finish=1; });
816	local $SIG{ALRM} = sub { $v->stop; };
817        $v->enable_events;
818        $v->play_and_wait('/path/welcome.rmd');
819        $v->beep(100,10);
820	$v->waitfor('READY');
821	if ($finish == 0) {
822		my $num = 0;
823		$num++ while(-r "/path/$num.rmd");
824		$v->record("/path/$num.rmd");
825		alarm $tmout;
826		$v->waitfor('READY');
827	}
828	system "echo 'Play with rmdtopvf /path/$num.rmd|pvftoau >/dev/audio'" .
829		 " | mail -s 'New voice message' $voicemaster";
830        exit 0;
831
832See the B<examples/answering_machine.pl> in the source distribution,
833which contains a more configurable version of the above text.
834It first sets the event handlers for the case of busy tone (the caller
835hangs up) or silence (the caller doesn't speak at all). The handler
836stops B<vgetty> from anything it is currently doing and sets the $finish
837variable to 1. Then the reception of the events is enabled and
838the welcome message is played. Then the answering machine beeps
839and starts to record the message. Note that we need to check the
840$finish variable before we start recording to determine if user
841hanged up the phone. Now we find the first filename <number>.rmd
842such that this file does not exist and we start to record the message
843to this file. We record until user hangs up the phone or until
844the timeout occurs.
845
846=head2 Readnum routine
847
848An interesting application of the low-level routines is the
849B<Voice::Modem::readnum> method. The calling sequence of this method
850has been discussed above. The source code for this routine and its
851co-routine will be discussed here, so that you can write your own
852variants of B<readnum> (which in fact does not have too general
853interface). See also the source code of B<Vgetty.pm> for the B<readnum>
854source.
855
856The B<readnum> routine needs to have its own event handler for the
857B<RECEIVED_DTMF> event and the way the handler can communicate with
858this routine. In our solution we use "static" variables:
859
860	my $_readnum_number = '';
861	my $_readnum_timeout = 10;
862	my $_readnum_in_timeout = 1;
863
864The event handler will add the new character to the end of the
865B<$_readnum_number> variable. The B<$_readnum_timeout> is the number
866of seconds both B<readnum> and the event handler should wait for the
867next keypress, and the B<$_readnum_in_timeout> is a flag used by the
868event handler for notifying the main B<readnum> routine that it forced
869the B<vgetty> to emit the `READY' message because of the final `#'
870has been received.
871
872	sub _readnum_event {
873		my $self = shift;
874		my $input = shift; # Unused. Should be 'RECEIVED_DTMF'.
875		my $dtmf = shift;
876
877		if ($dtmf eq '#') { # Stop the reading now.
878			$_readnum_in_timeout = 0;
879			$self->stop;
880			$self->{LOG}->print("_readnum_event(): Got #; stopping\n");
881			return;
882		}
883		$_readnum_number .= $dtmf;
884		$self->stop;
885		$self->expect('READY');
886		# Restart the wait again.
887		$_readnum_in_timeout = 1;
888		$self->wait($_readnum_timeout);
889	}
890
891The event handler is installed for the `RECEIVED_DTMF' event only, so it
892doesn't need to check for the B<$input> value. The actual DTMF key is in
893the third parameter, B<$dtmf>. Note that the handler will be called
894when B<vgetty> is PLAYING or WAITING and the B<readnum> routine will
895be waiting for the `READY' message. This allows us to immediately
896interrupt waiting by the B<$self->stop> (which emits the `READY' message).
897So when the `#' DTMF tone is received, we send a B<stop> to B<vgetty>.
898If something else is received, we B<stop> the B<vgetty> too but we
899enter a new wait using B<$self->wait>.
900
901	sub readnum {
902		my $self = shift;
903		my $message = shift;
904		my $timeout = shift;
905		my $times = shift;
906		$_readnum_number = '';
907		$_readnum_in_timeout = 1;
908		$_readnum_timeout = $timeout if $timeout != 0;
909		$times = 3 if $times == 0;
910
911		# Install the handler.
912		$self->add_handler('RECEIVED_DTMF', 'readnum', \&_readnum_event);
913		while($_readnum_in_timeout != 0 && $_readnum_number eq ''
914			&& $times-- > 0) {
915			$self->play_and_wait($message);
916			last if $_readnum_in_timeout == 0;
917			while ($_readnum_in_timeout != 0) {
918				$self->wait($_readnum_timeout);
919				$self->expect('READY');
920			}
921		}
922		return undef if $times < 0;
923		$self->del_handler('RECEIVED_DTMF', 'readnum');
924		$self->stop;
925		$self->expect('READY');
926		$_readnum_number;
927	}
928
929The B<readnum> routine just sets up the event handler, then plays
930the B<$message> and waits for the input (possibly several times).
931The main work is done in the event handler. At the end the handler
932is unregistered and the final value is returned.
933
934=head2 Callme script
935
936In the B<examples> subdirectory of the source distribution there is
937a B<callme.pl> script. This dials the given number and plays the
938given message. Use the following command to run it:
939
940	vm shell -S /usr/bin/perl callme.pl <number> <message>.rmd
941
942=head1 BUGS
943
944There may be some, but it will more likely be in the B<vgetty> itself.
945On the other hand, there can be typos in this manual (English is not my
946native language) or some parts of the interface that should be
947redesigned. Feel free to mail any comments on this module to me.
948
949=head1 TODO
950
951=over 4
952
953=item Modem type recognition
954
955The B<vgetty> should be able to tell the voice shell the name of the
956current modem type.
957
958=item The _wait() routines
959
960I need to implement the routines similar to B<play_and_wait> for other
961B<vgetty> states as well.
962
963=item Debugging information
964
965The module has currently some support for writing a debug logs
966(use the $Modem::Vgetty::testing = 1 and watch the /var/log/voicelog
967file). This needs to be re-done using (I think) Sys::Syslog.
968I need to implement some kind of log-levels, etc.
969
970=item Mgetty/Vgetty 1.1.17
971
972Need to figure out what is new in 1.1.17 (I use 1.1.14 now). I think
973new B<vgetty> can play more than one file in the single `PLAY' command,
974it (I think) have some support for sending voice data from/to the voice
975shell via the pipe, etc.
976
977=back
978
979=head1 AUTHOR
980
981The B<Modem::Vgetty> package was written by Jan "Yenya" Kasprzak
982<kas@fi.muni.cz>. Feel free to mail me any suggestions etc.
983on this module. Module itself is available from CPAN, but be sure
984to check the following address, where the development versions can
985be found:
986
987	http://www.fi.muni.cz/~kas/vgetty/
988
989=head1 COPYRIGHT
990
991Copyright (c) 1998 Jan "Yenya" Kasprzak <kas@fi.muni.cz>. All rights
992reserved. This package is free software; you can redistribute it and/or
993modify it under the same terms as Perl itself.
994
995=cut
996
997