/* LIB_FOD.CMD - Fax-on-demand procedure for FaxWorks/PMfax (REXX) */
/* 
                  Keller Group Inc.  September 9, 1996
   You may freely use or modify this script for use with licensed
        products which are developed by Keller Group Inc.
*/
/*******************************************************************
LIB_FOD.CMD - Fax-on-demand procedure - to be called from scripts

This is NOT a script file.  It is a procedure which has been placed
in this separate file so it can be easily called from several other
Voice/Fax Answer Scripts.  See the calling scripts, such as
V_FOD.CMD, for information and an example of calling the procedure.

Supported features:
	Can use documents from a fax log directory or another directory
	Both one-call and two-call fax-on-demand (FOD)
	Interactive fax response (generate data and fax it on-the-fly)
	Both text file and fax image file support
	Voice-on-demand (VOD)
	Drag/drop creation of FOD/VOD document library
	Full source code in REXX - modify as needed

DESCRIPTION:
-----------
This procedure does much more than just "fax-on-demand" since it also
supports "voice-on-demand" (playing user-selected voice message
files) and "text-on-demand" (converting user-selected text files to
fax and faxing them).  It also demonstrates how you can execute your
own programs to dynamically gather data (such as from your database)
and send it as a fax document.  So it's really a powerful "document
on demand" system that you can customize to meet your needs.

USAGE:
-----
Call this external REXX procedure using a statement similar to the
following:

call "LIB_FOD" FODDIR, VOXDIR1, VOXDIR2, CALLER, FAXFILE, FFCOMMENT, FFNOTE

where the parameters are as follows:

	FODDIR - pathname of directory which contains "on-demand"
	files, including the trailing \ character.

	VOXDIR1 - pathname of primary directory which contains voice
	prompt files.  This is the first place checked for a prompt.

	VOXDIR2 - (optional) pathname of secondary directory which
	contains voice prompt files.  This directory is checked only
	if a prompt file is not found in the VOXDIR1

	CALLER - (optional) the name of the caller, if known, for use
	on cover sheets.  Defaults to "Person" if not provided.

	FAXFILE - (optional) a pre-selected fax file (or log index#,
	or comma-separated list of fax files or log indices) to send.
	If provided, this bypasses the document selection procedure
	and just interacts with caller to fax them the fax file.

	FFCOMMENT - (optional) the Comment string for the cover sheet
	when FAXFILE is specified and the caller has the FAXFILE
	queued for sending to a fax number.

	FFNOTE - (optional) the Notes string for the spooled fax job.
        Default is "FOD".

RETURNS:
-------
This procedure returns one of the following values.  These values can
be used in a "SIGNAL VALUE RESULT" call to branch to labels of these
same names if desired.

	HELLO - meaning: done, and perhaps give user another prompt

	BYEBYE - meaning: error, so quit with error termination

	OUT - meaning: done, so quit with normal termination

VOICE PROMPT FILES:
------------------
To record or modify your own voice prompt files, use your OS/2
Multimedia microphone and record voice prompts using the "Fax/New
message" command then save them to a .WAV file with the "Fax/Save
file/Wave" command.  You can also use the OS/2 Digital Audio program
to record, save, edit and modify the Wave files (be sure to use
"Type" of Mono, 8-bit, 11.025 kHz).

	ENTR_DOC.WAV - Short: "Enter document number and # key, or
	press the # key if done."
	Long: "Please enter the document number followed by the # key,
	or press the # key if done.  To receive an index of available
	documents, enter document 1000."

	HOW_FAX.WAV - Short: "Enter 1 if calling from fax machine, 2
	if not."
	Long: "If you are calling from your fax machine and are ready
	to receive the fax press 1, to send the fax to a different
	number press 2." 

	ENTR_FAX.WAV - Short: "Enter fax number and # key."
	Long: "Please enter your fax number followed by the # key,
	including 1 and area code if this is not a local call." 

	NO_FILE.WAV - Short: "File not found."
	Long: "That document was not found, please try again."

	WAIT.WAV - Short: "Please wait."
	Long: "Please wait while we process your request."

	THANKYOU.WAV - Short: "Thank you."
	Long: "Thank you.  Your fax is queued for sending."


FAX/VOICE/TEXT-ON-DEMAND DOCUMENTS:
----------------------------------
This procedure allows the user to enter document numbers to select one
or more documents.  Each document can be a fax, text or voice message
document.  When voice documents are selected, they are played to the
caller.  When fax and text documents are selected, they are gathered
as a list and then either faxed to the caller on this current call
("one-call" fax-on-demand - if caller called from a fax machine) or
faxed to a number which the caller enters ("two-call" fax-on-demand).

The program's standard document file name format is used for the
"on-demand" documents (FX000001.FAX for fax documents, FX000001.TXT
for text documents, FX000001.MSG for voice message documents).  Any
fax, voice or text item that can appear in the log can be used as an
"on-demand" document.  You can create the documents in many different
ways (faxing to the program, printing through the FxPrint printer
driver, using the program's editing tools, recording voice messages
using Fax/New message or the answering machine features, etc.).

If the FODDIR parameter is set to the fax log directory, then this
procedure can use the documents from the log and the "document
number" is the "ID" number in the program's log display ("Fax/Open
log" command).

If the FODDIR parameter is set to a different directory, then
this script uses the documents which are found in that directory.
For many uses, you will usually want to do this so that you can
control the document numbers yourself.  For example, you may wish to
have an "index fax" as document 1000 (file FX001000.FAX) so that
callers can order a list of all available documents, then have
different categories of documents as document 1100, 1101, 1200,
1201, etc.  This is easy to do using your choice of techniques:

	1) DRAG/DROP - Create a folder, drag (to move) or Ctrl-drag
	(to copy) the documents from the log to your folder, and use
	direct editing (Alt-Click) to edit the file names to use your
	desired ID values.  Set the FODDIR script variable to the
	pathname of the folder's directory (including trailing \).

	2) COMMAND LINE - Create a directory, then copy the desired
	files from the log directory to your desired file names in
	your directory (or use the Fax/Save file command in the fax
	program).  Set the FODDIR script variable to the pathname of
	the directory's pathname (including trailing \ character).

The procedure uses ID 9999 as a special case to demonstrate how you
can dynamically call another program to generate text, convert the
text to a fax and send the fax to the caller.  For this
demonstration, we simply use the OS/2 DIR command, but you could
change this to do something more interesting (a database query, etc.).

TO MODIFY:
---------
This is REXX and uses calls from the Keller REXX API which are
automatically loaded into the OS/2 REXX environment by the retail
versions of Keller's fax products (version 3.0 and later).  See the
Reference Manual for documentation of the FxRx and FxLn calls.  You
may modify this procedure (and the scripts which call it) as desired,
and then use it as the "Answer script" with Keller fax software
products.

*******************************************************************/



lib_fod:
  parse arg FODDIR, VOXDIR1, VOXDIR2, CALLER, FAXFILE, FFCOMMENT, FFNOTE

  call FxLnMsg "Fax-on-demand"
  call FxLnVout 'Lib_fod called with params:' FODDIR '-' VOXDIR1 '-' ,
         VOXDIR2 '-' CALLER '-' FAXFILE '-' FFCOMMENT '-' FFNOTE

  /* initialize our variables which will hold lists of files */
  fodfilelist = ''	/* comma-separated list of documents to fax */
  fodlist = 'Your requested documents are attached:' /* for cover sheet */
  foddelete. = ''	/* stem variable list of temp files to delete */ 
  foddelete.0 = 0	/* list is initially empty */

  /* if CALLER and FFNOTES strings not provided, then default them */
  if CALLER = '' then CALLER = 'Person'
  if FFNOTE = '' then FFNOTE = 'FOD'

  /* if FAXFILE was provided, use it and skip to sending */
  if FAXFILE <> '' then do
    fodfilelist = FAXFILE
    fodlist = FFCOMMENT
    signal fodsend
  end

  /* otherwise, let the user select the documents */
  do forever
    if stream(VOXDIR1||'ENTR_DOC.WAV', 'C', 'QUERY EXISTS' ) <> ''
    then call FxLnPlay VOXDIR1||'ENTR_DOC.WAV'
    else call FxLnPlay VOXDIR2||'ENTR_DOC.WAV'
      if result = 'NOTOK' then signal fodbyebye
    
    fodnum = GetNumber( 7 )		/* get up to 6-digit doc # */
    if fodnum = '' then leave		/* if no number entered ... */

    /* Treat number 9999 as a special case for this demonstration */
    if fodnum = 9999 then do
      call FxLnMsg "Query #9999"
      if stream(VOXDIR1||'WAIT.WAV', 'C', 'QUERY EXISTS' ) <> ''
      then call FxLnPlay VOXDIR1||'WAIT.WAV'
      else call FxLnPlay VOXDIR2||'WAIT.WAV'
        if result = 'NOTOK' then signal fodbyebye
      tmp1 = FODDIR||TmpFile()||'.TXT'
      call RememberToDelete tmp1
      /* You could do a database query or something interesting. */
      /* For demo, we will just use DIR command to get text info */
      'DIR \ >"'||tmp1||'"'		/* put text in tmp1 file */
      tmp2 = FODDIR||TmpFile()||'.FAX'
      call RememberToDelete tmp2
      call FxRxTextToFax tmp1, tmp2	/* convert text to fax */
        if result = 'NOTOK' then signal fodbyebye
      fodlist = fodlist fodnum
      fodfilelist = AddToCsvList( tmp2, fodfilelist )
      iterate
    end

    fodfile = DocFile( fodnum, FODDIR )		/* normal doc #... */
    fodtype = DocType( fodfile )		/* look for the file */
    call FxLnMsg 'FOD Doc:' fodfile||fodtype

    if fodtype = '' then do			/* file not found */
      if stream(VOXDIR1||'NO_FILE.WAV', 'C', 'QUERY EXISTS' ) <> ''
      then call FxLnPlay VOXDIR1||'NO_FILE.WAV'
      else call FxLnPlay VOXDIR2||'NO_FILE.WAV'
      iterate
    end

    if fodtype = '.MSG' then do			/* voice document */
      call FxLnPlay fodfile||fodtype
      iterate
    end

    if fodtype = '.TXT' then do			/* text document */
      if stream(VOXDIR1||'WAIT.WAV', 'C', 'QUERY EXISTS' ) <> ''
      then call FxLnPlay VOXDIR1||'WAIT.WAV'
      else call FxLnPlay VOXDIR2||'WAIT.WAV'
        if result = 'NOTOK' then signal fodbyebye
      tmp2 = FODDIR||TmpFile()||'.FAX'
      call RememberToDelete tmp2
      call FxRxTextToFax fodfile||fodtype, tmp2	/* convert text to fax */
        if result = 'NOTOK' then signal fodbyebye
      /* Note: FxRxTextToFax uses FxPrint queue by default */
      /* You can specify "print queue" (physical name) as third parameter */
      /* The queue's job properties are used, so long text lines will not */
      /* wrap if in PCL emulation (like a LaserJet), but will wrap if in  */
      /* >>FONT emulation mode.                                           */
      fodlist = fodlist fodnum
      fodfilelist = AddToCsvList( tmp2, fodfilelist )
      iterate
    end

    if fodtype = '.FAX' then do			/* fax document */
      fodlist = fodlist fodnum
      fodfilelist = AddToCsvList( fodfile||fodtype, fodfilelist )
      iterate
    end

  end

fodsend:
  if fodfilelist = '' then signal fodhello	/* if nothing to fax */
  call FxLnMsg 'FOD How?'
  if stream(VOXDIR1||'HOW_FAX.WAV', 'C', 'QUERY EXISTS' ) <> ''
  then call FxLnPlay VOXDIR1||'HOW_FAX.WAV'
  else call FxLnPlay VOXDIR2||'HOW_FAX.WAV'
    if result = 'NOTOK' then signal fodbyebye
  call FxLnDtmf 1, 15, 'faxnow'
    if result = 'NOTOK' then signal fodbyebye
    if result <> 'DTMF' then signal fodqueue
  if faxnow <> 1 then signal fodqueue
  call FxLnSend fodfilelist			/* fax - current call */
  signal fodout

fodqueue:					/* fax - second call */
  call FxLnMsg 'FOD Queue'
  if stream(VOXDIR1||'ENTR_FAX.WAV', 'C', 'QUERY EXISTS' ) <> ''
  then call FxLnPlay VOXDIR1||'ENTR_FAX.WAV'
  else call FxLnPlay VOXDIR2||'ENTR_FAX.WAV'
    if result = 'NOTOK' then signal fodbyebye
  
  faxnum = GetNumber( 12 )
  call FxLnMsg 'Fax number:' faxnum

  if faxnum <> '' then do
    /* Send with default cover sheet and default "From" information */
    call FxRxQueue fodfilelist, ,
       'TO='||CALLER||' at fax: '||faxnum||',,'||faxnum, ,
       'INFO='||'"'||fodlist||'"'||',*,'||FFNOTE||',*,1,2', ,
       'FROM=*,*,*,*'
    if stream(VOXDIR1||'THANKYOU.WAV', 'C', 'QUERY EXISTS' ) <> ''
    then call FxLnPlay VOXDIR1||'THANKYOU.WAV'
    else call FxLnPlay VOXDIR2||'THANKYOU.WAV'
      if result = 'NOTOK' then signal fodbyebye
    signal fodhello
  end
  else call FxLnVout 'No fax number was entered'
  signal fodhello


fodbyebye:				/* for error cases */
  call cleanup
  call FxLnVout 'Lib_fod returns BYEBYE'
  return 'BYEBYE'

fodhello:				/* done, reprompt user? */ 
  call cleanup
  call FxLnVout 'Lib_fod returns HELLO'
  return 'HELLO'

fodout:					/* for normal cases */
  call cleanup
  call FxLnVout 'Lib_fod returns OUT'
  return 'OUT'

cleanup:
  /* clean up temporary files from .TXT processing */
  call FxLnVout 'Deleting' foddelete.0 'temp files.'
  do i = 1 to foddelete.0 by 1
    call FxLnVout 'Deleting:' foddelete.i
    'DEL "'||foddelete.i||'"'
  end
  return



/************************ Procedures ************************/

GetNumber: procedure
  /* Gets DTMF input until # or * key or "digits" are entered. */
  /* TimeOut is seconds to wait for each digit (default 15).       */
  parse arg digits, TimeOut
  number = ''
  if TimeOut = '' then TimeOut = 15  /* default to 15 seconds */
  do digits
    call FxLnDtmf 1, TimeOut, 'newkey'
      if result <> 'DTMF' | newkey = '#' | newkey = '*' then leave
    number = number||newkey
  end
  return number

DocFile: procedure
  /* Given a document id and directory, returns pathname of the doc */
  /* file (without extension).  File names are FX000001.xxx format. */
  parse arg id, dir
  return ( dir||'FX'||right( id, 6, '0' ) )

DocType: procedure
  /* Given a document pathname (without extension), returns the */
  /* extension of the existing file or '' if file doesn't exist */
  parse arg basefile
  if stream( basefile||'.FAX', 'C', 'QUERY EXISTS' ) <> ''
    then return '.FAX'
  if stream( basefile||'.MSG', 'C', 'QUERY EXISTS' ) <> ''
    then return '.MSG'
  if stream( basefile||'.TXT', 'C', 'QUERY EXISTS' ) <> ''
    then return '.TXT'
  return ''

TmpFile: procedure
  /* Generate a unique base file name using seconds since midnight */
  return 'TMP'||time( S )

RememberToDelete: procedure expose foddelete.
  /* Adds a file to the list of tmp files to be deleted */
  parse arg newfile
  foddelete.0 = foddelete.0 + 1
  i = foddelete.0
  foddelete.i = newfile
  call FxLnVout 'Remembering to delete' foddelete.i
  return

AddToCsvList: procedure
  /* returns a comma-separated value list with item added */
  parse arg item, list
  if list = ''
    then list = item
    else list = list||','||item
  return list
