home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 3 Comm / 03-Comm.zip / voice2.zip / v_multi.cmd < prev    next >
OS/2 REXX Batch file  |  1997-06-19  |  30KB  |  827 lines

  1. /* V_MULTI.CMD - Voice/Fax Answer Script for FaxWorks/PMfax (REXX) */
  2. /* 
  3.                   Keller Group Inc.  June 19, 1997
  4.    You may freely use or modify this script for use with licensed
  5.         products which are developed by Keller Group Inc.
  6.       For new scripts or to share your scripts with others,
  7.                  see http://www.kellergroup.com
  8.  
  9.    Modification history:
  10.       05May97 - Added SysSleep to paging to make sure line is hung up.
  11.       06Jun97 - NOTE: Uses new FxRxFind command (requires 3.01.01 !!)
  12.       19Jun97 - Added reset command ('*')
  13.       19Jun97 - Changed termination after FOD calls - no log entry
  14. */
  15. /*******************************************************************
  16. V_MULTI.CMD - Multiple Mailbox (Standalone) voice/fax mailbox system
  17.  
  18. For use with the following Keller software configurations:
  19.   Stand-alone (single-line or multiline)
  20.   LAN Shared Mode
  21.   LAN Private Mode (with fax server as router & retrieval from server log)
  22.  
  23. Features:
  24.  
  25.   Callers can:
  26.      select a mailbox using an extension
  27.      hear both a "company" greeting and the extension's "personal" greeting
  28.      send a fax (to an extension, or by default to mailbox 0),
  29.      leave a voice message (to an extension, or by default to mailbox 0),
  30.      listen to an announcement, or
  31.      enter extension and private password to enter remote retrieval mode
  32.  
  33.   In the password-protected remote retrieval mode, you can do:
  34.      greeting modification - remotely update your personal greeting message
  35.      password modification - remotely modify your personal access code
  36.      voice retrieval - get voice messages by phone
  37.      fax retrieval - get fax messages, or send them to a fax number
  38.      log retrieval - get a fax of your log (or the last part of it)
  39.      "fax on demand" from log - retrieve voice and fax items from your log
  40.  
  41.   New features:
  42.      20May97 - Switched to FxRxFind Next/Prev functions to allow retrieval
  43.                of old messages (not just new ones) using the PrevMsg command.
  44.  
  45.  
  46. DESCRIPTION:
  47. -----------
  48. This script is a "multiple mailbox" voice/fax system which will work
  49. with a standalone copy of PMfax/FaxWorks.  When messages or faxes are
  50. received, the notes field in the log will indicate the mailbox
  51. extension.  Mailbox users can call and retrieve their messages and
  52. faxes from the system for their specific mailbox extension.
  53.  
  54. The script first plays your outgoing message (OGM).  The caller can
  55. enter a "mailbox extension" followed by the '#' key to hear that
  56. mailbox's personal outgoing message and then record a message or send
  57. a fax to that mailbox.  If the caller doesn't enter any extension or
  58. enters '0#' or '#', the caller can record a message to the
  59. "receptionist" at mailbox '0'.
  60.  
  61. The caller can press the # or * key to skip the outgoing message and
  62. immediately record their message, otherwise the script will provide a
  63. beep and record the caller's message if no further action is taken.
  64.  
  65. If the call is from a fax device and your fax hardware detects the
  66. caller's fax (CNG) tones, the script automatically receives the fax.
  67.  
  68. If the caller enters '2' during playing of the outgoing message, the
  69. script plays the "announcement" and then returns to the outgoing
  70. message again so that the caller can leave a message on the same
  71. call.  If a mailbox extension was entered, the mailbox's personal
  72. announcement is played, otherwise the system's main announcement is
  73. played.
  74.  
  75. If the caller enters '9' during or immediately after the playing of
  76. the OGM and then enters the user-configurable access code followed by
  77. the # key, the script enters its "remote retrieval" mode so the
  78. caller can hear received voice messages, have received faxes sent to
  79. them via fax, and other features.  When in this mode, the keys on the
  80. telephone do the following:
  81.  
  82.    1 - HELP       - Play help message which describes these commands
  83.    2 - SET CODE   - Changes LAN user's private access code (default: 42)
  84.    3 - GREETING   - Enter new outgoing message (change greeting)
  85.  
  86.    4 - PREV MSG   - Play previous voice message
  87.    5 - REPLAY MSG - Play current voice message (again)
  88.    6 - NEXT MSG   - Play next voice message
  89.  
  90.    7 - GET FAXES  - Retrieve new fax messages by fax
  91.    8 - GET LOG    - Retrieve fax log by fax
  92.    9 - FOD LOG    - Retrieve voice/fax msgs from log ("fax-on-demand")
  93.  
  94.    0 - TOP        - Return to top level and play outgoing message again
  95.  
  96.    * - RESET      - Marks all "new" messages/faxes as "retrieved"
  97.  
  98.  
  99. In summary, for multiple mailbox use:
  100.  
  101. 1) You will want to create an outgoing message (OGM) which instructs
  102. your callers to "Enter the mailbox extension number followed by the #
  103. key".  When they record a message or send a fax, it will than appear
  104. in the log with a Notes entry of "mbx1234" where 1234 is the
  105. extension number.
  106.  
  107. 2) To call in and retrieve the messages and/or faxes for extension
  108. 1234, enter 1234# during or just after the OGM, then press 9 to enter
  109. the remote retrieval mode.  Enter the access code (which defaults to
  110. 42, but can be changed by each user once in the remote retrieval
  111. mode).  The system will beep once for each new voice message.  You
  112. can then use '5' to hear the first voice message, '4' to hear older
  113. voice messages (even ones that aren't "new" anymore), and other keys
  114. to change your access code, change your mailbox outgoing message, and
  115. get your faxes.  You will only get those messages and faxes which
  116. match the extension.
  117.  
  118.  
  119. USAGE INSTRUCTIONS:
  120. ------------------
  121. You must be using the program with supported voice/fax hardware to
  122. use this script.  Consult the README.DOC file for tested voice/fax
  123. hardware and recommended configuration settings for your hardware.
  124. Before using this script, first test your system with our built-in
  125. voice answering machine feature by enabling "Voice" and setting the
  126. "Answer script" to * (an asterisk character) on the Voice page of the
  127. Settings notebook.  If you are using supported voice/fax hardware
  128. with the proper configuration settings, you can then use
  129. "Fax/Receive/All calls" mode to answer calls, play the outgoing
  130. message (OGM), and record a voice message (or receive a fax).
  131.  
  132. Then, to change to this advanced script, specify the full pathname of
  133. this file in the "Answer script" field on the Voice page of the
  134. settings notebook.
  135.  
  136. NOTE: The script expects to find the LIB_FOD.CMD file and its Wave
  137. audio files in the fax program (EXE) directory.  The script also uses
  138. Wave files from the c:\mmos2\sounds directory for special effects.
  139.  
  140. SCRIPT VARIABLES:
  141. ----------------
  142. The following script variable is used by this script.  Script
  143. variables are set on the Voice page of the Settings Notebook.
  144.  
  145. General:
  146.  
  147.     OGM - Pathname of the main "outgoing message" which is played
  148.     to the caller.  By default, the program sets OGM to be the
  149.     file OGM.WAV in the program directory.
  150.     Example: OGM = C:\FAX\OGM.WAV
  151.     [Mailbox users can also place a personal MBXnnnn.WAV file in the
  152.         program directory or record one using remote access command '3'.]
  153.  
  154.     CODE - Access code for retrieving messages or changing
  155.     settings from the log.  By default, the program
  156.     sets CODE to be 42.  You can change this to be any number of up
  157.     to 5 digits in length.
  158.     Example: CODE = 42
  159.     [Mailbox users can also set a personal access code for their mailbox
  160.     using the '2' command when they call in, and this personal value
  161.     is saved in the MBXnnnn.COD file in the program directory.  If no
  162.     personal access code is set, the default value is 42.]
  163.  
  164.     CALLER - (optional, default "Person") - Name of the person/company
  165.     who will be using the access code to retrieve messages/faxes
  166.     by phone.  This is used for addressing faxes when the caller
  167.     uses the access code for remote retrieval.  
  168.     Example: CALLER = Your Company Inc.
  169.  
  170.     LOGMAXLINE - (optional, default 56) - Maximum number of log
  171.     entries, from the end of the log, to be sent to the caller
  172.     when they retrieve the log by fax.  If set to 0, then
  173.     the entire log is sent.
  174.     Example: LOGMAXLINE = 120
  175.  
  176.  
  177. VOICE PROMPT FILES:
  178. ------------------
  179. The script expects to find the following Wave audio files in the fax
  180. program (EXE) directory.  The script also uses Wave files from the
  181. c:\mmos2\sounds directory for special effects.
  182.  
  183. To record or modify your own voice prompt files, use your OS/2
  184. Multimedia microphone and record voice prompts using the "Fax/New
  185. message" command then save them to a .WAV file with the "Fax/Save
  186. file/Wave" command.  You can also use the OS/2 Digital Audio program
  187. to record, save, edit and modify the Wave files (be sure to use
  188. "Type" of Mono, 8-bit, 11.025 kHz).
  189.  
  190.     OGM.WAV - The main "outgoing message" as recorded with the
  191.     Utilities/Outgoing message command.
  192.  
  193.     ENTR_COD.WAV - Short: "Enter code."
  194.     Long: "Please enter your access code and the # key."
  195.  
  196.     ENTR_CMD.WAV - Short: "Enter command."
  197.     Long: "To play current message press 5, to play next message
  198.     press 6, to play previous message press 4...."
  199.  
  200.     ENTR_MSG.WAV - Short: "Enter message, then press # key."
  201.     Long: "Please leave your message at the beep.  Press # key to end."
  202.  
  203.     ANNOUNC.WAV - Short: "No announcement."
  204.     Long: "Our annoucement for this week is...."
  205.  
  206.     HELP.WAV - "Press 3 to change outgoing message, 4 for previous..."
  207.  
  208.     NO_MSGS.WAV - Short: "No more messages."
  209.  
  210. And used by any fax retrieval actions (LIB_FOD.CMD procedure):
  211.  
  212.     ENTR_DOC.WAV - Short: "Enter document number and # key, or
  213.     press the # key if done."
  214.     Long: "Please enter the document number followed by the # key,
  215.     or press the # key if done.  To receive an index of available
  216.     documents, enter document 1000."
  217.  
  218.     HOW_FAX.WAV - Short: "Enter 1 if calling from fax machine, 2
  219.     if not."
  220.     Long: "If you are calling from your fax machine and are ready
  221.     to receive the fax press 1, to send the fax to a different
  222.     number press 2." 
  223.  
  224.     ENTR_FAX.WAV - Short: "Enter fax number and # key."
  225.     Long: "Please enter your fax number followed by the # key,
  226.     including 1 and area code if this is not a local call." 
  227.  
  228.     NO_FILE.WAV - Short: "File not found."
  229.     Long: "That document was not found, please try again."
  230.  
  231.     WAIT.WAV - Short: "Please wait."
  232.     Long: "Please wait while we process your request."
  233.  
  234.     THANKYOU.WAV - Short: "Thank you."
  235.  
  236. TO MODIFY THE SCRIPT:
  237. --------------------
  238. The script is REXX and uses calls from the Keller REXX API which are
  239. automatically loaded into the OS/2 REXX environment by the retail
  240. versions of Keller's fax products (version 3.0 and later).  See the
  241. Reference Manual for documentation of the FxRx and FxLn calls.  You
  242. may modify the script as desired, and then use it as the "Answer
  243. script" with Keller fax software products.
  244.  
  245. Note - For retrieval, this script uses the READ/N_READ mode of
  246. FxRxFind and the new "NOTES=" parameter of version 3.01.01 and later.
  247. Using READ/N_READ mode means it will report all faxes/messages for
  248. the matching mailbox userid which have not been previously retrieved
  249. via phone (even those that have been viewed at the computer).  If
  250. desired, you can change this to use RCVD/N_RCVD mode of FxRxFind,
  251. which means that it will report only those faxes which have been
  252. received but not already viewed at the computer and not previously
  253. retrieved via phone (but this is less reliable since "error" faxes
  254. won't be included).  You can also retrieve any desired fax, whether
  255. or not it has been viewed or retrieved, using the "fax log" and
  256. "fax-on-demand" features in this script which allow you to retrieve
  257. any fax by its index number.  In version 3 of the fax program,
  258. viewing a received fax changes its status from Rcvd to Read, but
  259. printing of faxes does NOT change the status, so you can auto-print
  260. all received faxes at the computer and still retrieve them as "Rcvd"
  261. faxes by phone. 
  262.  
  263. TO USE WITH MULTILINE VERSIONS:
  264. ------------------------------
  265. This script can be used with multiline versions of Keller fax
  266. software.  All lines are handled identically, so calls can be
  267. received on any of your "receive" lines.  If you prefer to have
  268. different lines be handled differently you can modify the script to
  269. test the LID variable.  For example, to have line 1 immediately jump
  270. to the "please enter your message" prompt, you could add a line like
  271. the following after the "call FxLnInit" line in the script: "if LID =
  272. 1 then signal voice" where "voice" is a label in the script.
  273.  
  274. *******************************************************************/
  275.  
  276.   call FxLnInit
  277.  
  278.   VOXDIR = FxRxPath( 'EXE' )    /* get voice prompts from exe dir */
  279.   LIBDIR = FxRxPath( 'EXE' )    /* get REXX subroutines from exe dir */
  280.   FODPROCEDURE = LIBDIR||'lib_fod.cmd'  /* use this external procedure */
  281.  
  282.   /* default values for script variables */
  283.   if CALLER = 'CALLER' then CALLER = 'Person'
  284.   if LOGMAXLINE = 'LOGMAXLINE' then LOGMAXLINE = 56
  285.  
  286.   DEFAULTCODE = '42'        /* default access code */
  287.  
  288. hello:
  289.   LREC. = ""                /* be sure this is clean */
  290.   USERID = '0'                /* default/receptionist is mbx 0 */
  291.   USERDIR = VOXDIR||'MBX'||USERID    /* just add extension later */
  292.  
  293.   /* If using Brooktrout, you may need to use certain lines for fax since */
  294.   /* it has trouble hearing calling fax CNG tones when you are using      */
  295.   /* voice and DTMF commands. For example... */
  296.   /* if LID = 1 then signal fax */
  297.  
  298.   call FxLnMsg 'OGM'                /* show in status window */
  299.     if result = 'NOTOK' then signal byebye
  300.   call FxLnPlay OGM                /* play greeting prompt */
  301.     if result = 'NOTOK' then signal byebye
  302.     if result = 'FAX' then signal fax
  303.     if result = 'DATA' then signal data
  304.  
  305.   digits = GetExtension( 5, 10, 5 )        /* get extension or number */
  306.     if digits = 'NOTOK' then signal byebye
  307.     if digits = 'FAX' then signal fax
  308.     if digits = 'DATA' then signal data
  309.  
  310.   if digits = '' | digits = '0' then signal voice
  311.   if digits = 2 then signal announce        /* use key value... */
  312.   if digits = 9 then signal accesscode
  313.  
  314.   /* else they must have entered an extension... */
  315.   USERID = digits
  316.   USERDIR = VOXDIR||'MBX'||USERID        /* just add extension later */
  317.   if stream(USERDIR||'.WAV', 'C', 'QUERY EXISTS' ) <> ''
  318.   then call FxLnPlay USERDIR||'.WAV'
  319.  
  320.   call FxLnDtmf 1, 3, 'digits'            /* get key, if any... */
  321.     if result = 'NOTOK' then signal byebye
  322.     if result = 'FAX' then signal fax
  323.     if result = 'DATA' then signal data
  324.     if result <> 'DTMF' then signal voice
  325.  
  326.   if digits = 2 then signal announce        /* use key value... */
  327.   if digits = 3 then signal fax
  328.   if digits = 9 then signal accesscode
  329.  
  330.  
  331. voice:                    /* take voice message, hangup */
  332.   call FxLnMsg "Record Msg"
  333.   call FxLnTone 1850
  334.     if result = 'NOTOK' then signal byebye
  335.   call FxLnDtmf     /* flush buffer */
  336.   call FxLnRecord
  337.     if result = 'NOTOK' then signal byebye
  338.     if result = 'FAX' then signal fax
  339.     if result = 'DATA' then signal data
  340.   /* caller can hang up or press a key to end recording */
  341.   call FxLnTone 1850, 1850, 1850
  342.   if USERID <> '' then do
  343.     LREC.!Notes = 'mbx'||USERID        /* tag the message with a note */
  344.   end
  345.   signal out
  346.  
  347.  
  348. fax:                    /* receive fax and hangup */
  349.   call FxLnReceive
  350.   if USERID <> '' then do
  351.     LREC.!Notes = 'mbx'||USERID        /* tag the fax with a note */
  352.   end
  353.   signal out
  354.  
  355.  
  356. data:                    /* report data call, hangup */
  357.   call FxLnMsg 'Data call, oh well...'
  358.   LREC.!Status = '*Data!'   /* log status of call */
  359.   signal out
  360.  
  361.  
  362. announce:                /* play annoucement, restart */
  363.   call FxLnMsg "Announcement"
  364.   if stream(USERDIR||'.ANN', 'C', 'QUERY EXISTS' ) <> ''
  365.   then call FxLnPlay USERDIR||'.ANN'
  366.   else call FxLnPlay VOXDIR||'ANNOUNC.WAV'
  367.   signal hello
  368.  
  369.  
  370. accesscode:
  371.   call FxLnMsg 'Code ???'        /* get & check access code */
  372.   call FxLnPlay VOXDIR||'ENTR_COD.WAV'
  373.     if result = 'NOTOK' then signal byebye
  374.   digits = GetNumber( 6, 10 )
  375.   if digits <> FetchCode() then signal evil
  376.  
  377.   call FxLnMsg 'Code Mode'
  378.   call FxLnVout 'Valid code entered'
  379.   call FxRxBeep 354, 393, 295, 354, 0, 393
  380.  
  381.   call FxRxFind 'MSG', 'N_READ', 'NOTES=mbx'||USERID    /* # msgs */
  382.   if result = 'NOTOK' then do
  383.     call FxLnPlay 'c:\mmos2\sounds\BOING.wav'
  384.     signal byebye
  385.   end
  386.   n = result
  387.  
  388.   /* if no messages... stay in command mode for other commands */
  389.   if n = 0 then do
  390.         call FxLnPlay VOXDIR||'NO_MSGS.WAV'
  391.         if result = 'NOTOK' then signal byebye
  392.   end
  393.  
  394.   i = n                /* Play 1 beep for each voice message */
  395.   call FxLnMsg 'Code Mode' n 'messages'
  396.   call FxLnVout 'Beep' n 'times'
  397.   do while i > 0
  398.     call FxLnTone 2100
  399.     i = i - 1
  400.   end
  401.  
  402.   call FxLnVout 'Enter message loop'
  403.   i = 0
  404.  
  405.   /* select the first voice message, or last one if no new msgs */
  406.   if n > 0 then do
  407.     call FxRxFind 'MSG', 'READ', 'NOTES=mbx'||USERID, 'LREC'
  408.     if result <> 'NOTOK' then do
  409.       call FxLnVout 'Found by READ' LREC.!ID
  410.       i = LREC.!ID
  411.     end
  412.   end
  413.   else do
  414.     call FxRxFind 'MSG', 'PREV', 'NOTES=mbx'||USERID, 'LREC'
  415.     if result <> 'OK' then do
  416.       call FxLnVout 'Found by PREV' LREC.!ID
  417.       i = LREC.!ID
  418.     end
  419.   end
  420.  
  421.   do forever
  422.     call FxLnMsg 'Waiting for next command'
  423.     call FxLnPlay VOXDIR||'ENTR_CMD.WAV'
  424.     call FxLnDtmf 1, 30, 'digits'
  425.     if result <> 'DTMF' then do
  426.       signal goodbye
  427.     end
  428.     else do
  429.       call FxLnMsg 'Code Mode command' digits
  430.       call FxLnVout 'Command' digits 'entered'
  431.  
  432.  
  433.       if digits = '1' then do            /* 1 = Play help msg */
  434.         call FxLnVout 'Help message'
  435.         call FxLnPlay VOXDIR||'HELP.WAV'
  436.       if result = 'NOTOK' then signal byebye
  437.         iterate
  438.       end
  439.  
  440.  
  441.       if digits = '2' & USERID > '0' then do    /* 2 = change access code */
  442.         /* Only access codes for MBX users are changed through this. */
  443.         /* For the fax server, use the CODE script variable on Voice page. */
  444.         call FxLnVout 'Change access code for' USERID
  445.         call FxLnMsg 'Code Mode command' digits
  446.         call FxLnPlay VOXDIR||'ENTR_COD.WAV'
  447.           if result = 'NOTOK' then signal byebye
  448.         code1 = GetNumber( 6, 10 )
  449.         call FxLnPlay VOXDIR||'ENTR_COD.WAV'
  450.           if result = 'NOTOK' then signal byebye
  451.         code2 = GetNumber( 6, 10 )
  452.         if code1 = code2 then do
  453.           call SaveCode code1
  454.           call FxLnPlay VOXDIR||'THANKYOU.WAV'
  455.         end
  456.         else do
  457.           call FxLnVout 'New code mismatch:' code1 'vs' code2
  458.           call FxLnPlay 'c:\mmos2\sounds\BOO.wav'
  459.         end
  460.         iterate
  461.       end
  462.  
  463.  
  464.       if digits = '3' then do            /* 3 = Enter outgoing msg */
  465.         call FxLnVout 'Enter outgoing message for' USERID
  466.         call FxLnPlay VOXDIR||'ENTR_MSG.WAV'
  467.       if result = 'NOTOK' then signal byebye
  468.         call FxLnTone 1850
  469.       if result = 'NOTOK' then signal byebye
  470.         call FxLnDtmf        /* flush buffer */
  471.         if USERID = '0'
  472.         then call FxLnRecord OGM
  473.         else call FxLnRecord USERDIR||'.WAV'
  474.        if result = 'NOTOK' then signal byebye
  475.         call FxLnTone 1850, 1850, 1850
  476.         call FxLnDtmf        /* flush buffer */
  477.         if USERID = '0'
  478.         then call FxLnPlay OGM
  479.         else call FxLnPlay USERDIR||'.WAV'
  480.       if result = 'NOTOK' then signal byebye
  481.         iterate
  482.       end
  483.  
  484.  
  485.       if digits = '4' then do            /* 4 = Previous msg */
  486.         call FxLnVout 'Play previous message' i
  487.         if i = 0 
  488.     then call FxLnPlay VOXDIR||'NO_MSGS.WAV'
  489.     else do
  490.       call FxRxFind 'MSG', 'PREV', 'NOTES=mbx'||USERID, 'LREC'
  491.       if result = 'OK'
  492.       then do
  493.         call FxLnVout 'Find PREV returns' result
  494.         call FxLnPlay VOXDIR||'NO_MSGS.WAV'
  495.       end
  496.       else do
  497.         call FxLnVout 'Find PREV returns' result
  498.         call FxLnVout 'Found by PREV' LREC.!ID
  499.         i = LREC.!ID
  500.         call FxLnMsg 'Code Mode command' digits 'Msg' i
  501.         call FxLnPlay i
  502.       end
  503.         end
  504.         iterate
  505.       end
  506.  
  507.  
  508.       if digits = '5' then do            /* 5 = Replay msg */
  509.         call FxLnVout 'Replay message' i
  510.         if i = 0 
  511.     then call FxLnPlay VOXDIR||'NO_MSGS.WAV'
  512.     else do
  513.       call FxLnMsg 'Code Mode command' digits 'Msg' i
  514.       call FxLnPlay i
  515.         end
  516.         iterate
  517.       end
  518.  
  519.  
  520.       if digits = '6' then do            /* 6 = Next message */
  521.         call FxLnVout 'Play next message' i
  522.         if i = 0 
  523.     then call FxLnPlay VOXDIR||'NO_MSGS.WAV'
  524.     else do
  525.       call FxRxFind 'MSG', 'NEXT', 'NOTES=mbx'||USERID, 'LREC'
  526.       if result = 'OK'
  527.       then do
  528.         call FxLnVout 'Find NEXT returns' result
  529.         call FxLnPlay VOXDIR||'NO_MSGS.WAV'
  530.       end
  531.       else do
  532.         call FxLnVout 'Find NEXT returns' result
  533.         call FxLnVout 'Found by NEXT' LREC.!ID
  534.         i = LREC.!ID
  535.         call FxLnMsg 'Code Mode command' digits 'Msg' i
  536.         call FxLnPlay i
  537.       end
  538.         end
  539.         iterate
  540.       end
  541.  
  542.  
  543.       if digits = '7' then do            /* 7 = send rcvd faxes */
  544.         call FxLnVout 'Send rcvd faxes'
  545.         call FxLnMsg 'Code Mode command' digits
  546.         call FxRxFind 'FAX', 'N_READ', 'NOTES=mbx'||USERID  /* # new faxes */
  547.         if result = 'NOTOK' then do
  548.           call FxLnPlay 'c:\mmos2\sounds\BOING.wav'
  549.           signal byebye
  550.         end
  551.         nfax = result
  552.         if nfax = 0 then do
  553.           call FxLnPlay VOXDIR||'NO_MSGS.WAV'
  554.           if result = 'NOTOK' then signal byebye
  555.         end
  556.         else do
  557.           ifax = nfax        /* Get faxes into list and beep per fax */
  558.           faxlist = ''
  559.           flist = ''
  560.           call FxLnMsg 'Code Mode' nfax 'faxes'
  561.           call FxLnVout 'FaxBeep' nfax 'times'
  562.           do while ifax > 0
  563.             call FxLnTone 2100
  564.             ifax = ifax - 1
  565.             call FxRxFind 'FAX', 'READ', 'NOTES=mbx'||USERID, 'LREC'
  566.             call FxLnVout 'Found' LREC.!ID
  567.             /* Note use of filenames rather than ID values.  This is done */
  568.             /* because FxLnSend, which could be used in the FOD procedure,*/
  569.             /* cannot be given IDs from an FxRxSelect LAN user directory. */
  570.             faxlist = AddToCsvList( FxRxIndexToFax( LREC.!ID ), faxlist )
  571.             flist = flist LREC.!ID
  572.           end
  573.           /* call our FOD procedure to do the faxing */
  574.           FODPARAMS = "FxRxPath( 'LOG' ), VOXDIR, , CALLER, faxlist," ,
  575.             "'As you requested, your received faxes are attached:' flist," ,
  576.             "'Remote fax retrieval...'"
  577.           interpret 'call' "'"||FODPROCEDURE||"'" FODPARAMS
  578.           if result = 'BYEBYE' then signal BYEBYE
  579.           if result = 'OUT' then signal OUT
  580.         end
  581.         iterate
  582.       end
  583.  
  584.  
  585.       if digits = '8' then do            /* 8 = send log */
  586.         call FxLnVout 'Send log'
  587.         call FxLnMsg 'Code Mode command' digits
  588.         call FxLnPlay VOXDIR||'WAIT.WAV'
  589.       if result = 'NOTOK' then signal byebye
  590.         call SendLog
  591.           if result = 'BYEBYE' then signal BYEBYE
  592.           if result = 'OUT' then signal OUT
  593.         iterate
  594.       end
  595.  
  596.  
  597.       if digits = '9' then do            /* 9 = FOD from log */
  598.         call FxLnVout 'FOD from log'
  599.         call FxLnMsg 'Code Mode command' digits
  600.         FODPARAMS = "FxRxPath( 'LOG' ), VOXDIR, , CALLER, , ," ,
  601.                "'FOD Retrieval...'"
  602.         interpret 'call' "'"||FODPROCEDURE||"'" FODPARAMS
  603.           if result = 'BYEBYE' then signal BYEBYE
  604.           if result = 'OUT' then signal OUT
  605.         iterate
  606.       end
  607.  
  608.  
  609.       if digits = '0' then do            /* 0 = back to top level */
  610.         call FxLnVout 'Return to HELLO'
  611.     signal hello
  612.       end
  613.  
  614.  
  615.       if digits = '*' then do            /* * = reset */
  616.         /* This is used to mark as messages and faxes in the log as  */
  617.     /* having been "previously retrieved" so that you don't need */
  618.     /* to get them all via phone.  You can still go back through */
  619.     /* them from the end using "Prev Msg" and "fax-on-demand".   */
  620.         call FxLnVout 'Reset' i
  621.     call FxLnMsg 'Reset command' digits
  622.         call FxLnPlay VOXDIR||'WAIT.WAV'
  623.       if result = 'NOTOK' then signal byebye
  624.     LREC. = ""        /* forget any previous position in log */
  625.     do forever
  626.       call FxRxFind 'ANY', 'NEXT', 'NOTES=mbx'||USERID, 'LREC'
  627.           if result = 'OK' | result = 'NOTOK' then leave
  628.     end
  629.     /* Select last voice message as the current message */
  630.     LREC. = ""
  631.     call FxRxFind 'MSG', 'PREV', 'NOTES=mbx'||USERID, 'LREC'
  632.     if result = 'OK'
  633.     then i = 0
  634.     else i = LREC.!ID
  635.     call FxLnVout 'Reset find PREV returns' result
  636.         iterate
  637.       end
  638.  
  639.  
  640.       if digits = '#' then do
  641.         signal goodbye
  642.       end
  643.  
  644.  
  645.       /* otherwise, if none were matched... */
  646.       call FxLnVout 'Unknown command' i
  647.       call FxLnPlay 'c:\mmos2\sounds\EEERRUPP.wav'
  648.       iterate
  649.  
  650.     end
  651.   end
  652.  
  653.  
  654. goodbye:
  655.   call FxLnVout 'Exit Code Mode'
  656.   call FxLnPlay VOXDIR||'THANKYOU.WAV'
  657.   call FxLnPlay 'c:\mmos2\sounds\DRUMROLL.wav'
  658.   signal byebye
  659.  
  660.  
  661. evil:
  662.   call FxLnVout 'Bad code entered:' digits 'vs' FetchCode()
  663.   call FxLnPlay 'c:\mmos2\sounds\BOO.wav'
  664.   call FxRxBeep 1318, 1396, 1318, 1090, 1318, 1396, 1318, 1090
  665.   signal byebye
  666.  
  667.  
  668. byebye:                    /* called for error cases */
  669.   LREC.!Status = ''            /* don't log anything */
  670.   signal out
  671.  
  672.  
  673. out:                    /* clean up and quit */
  674.   call FxLnTerm
  675.   exit
  676.  
  677.  
  678. /************************ Procedures ************************/
  679.  
  680.  
  681. GetNumber: procedure
  682.   /* Gets DTMF input until # or * key or "digits" are entered. */
  683.   /* TimeOut is seconds to wait for each digit (default 15).       */
  684.   parse arg digits, TimeOut
  685.   number = ''
  686.   if TimeOut = '' then TimeOut = 15  /* default to 15 seconds */
  687.   do digits
  688.     call FxLnDtmf 1, TimeOut, 'newkey'
  689.       if result <> 'DTMF' | newkey = '#' | newkey = '*' then leave
  690.     number = number||newkey
  691.   end
  692.   return number
  693.  
  694.  
  695. GetExtension: procedure
  696.   /* Gets DTMF input until # or * key or "digits" are entered. */
  697.   /* TimeOut is seconds to wait for first digit (default 15).   */
  698.   /* NextTime is seconds to wait for subsequent digits (default TimeOut)*/
  699.   /* Returns 'FAX' or 'DATA' or 'NOTOK' results or the number. */
  700.   parse arg digits, TimeOut, NextTime
  701.   number = ''
  702.   if TimeOut = '' then TimeOut = 15  /* default to 15 seconds */
  703.   if NextTime = '' then NextTime = TimeOut
  704.   do digits
  705.     call FxLnDtmf 1, TimeOut, 'newkey'
  706.       if result = 'FAX' | result = 'DATA' | result = 'NOTOK' then return result
  707.       if result <> 'DTMF' | newkey = '#' | newkey = '*' then leave
  708.     number = number||newkey
  709.     TimeOut = NextTime
  710.   end
  711.   return number
  712.  
  713.  
  714. TmpFile: procedure
  715.   /* Generate a unique base file name using seconds since midnight */
  716.   return 'TMP'||time( S )
  717.  
  718.  
  719. AddToCsvList: procedure
  720.   /* returns a comma-separated value list with item added */
  721.   parse arg item, list
  722.   if list = ''
  723.     then list = item
  724.     else list = list||','||item
  725.   return list
  726.  
  727.  
  728. SendLog:    /* sends the log file by fax */
  729.   tmp1 = VOXDIR||TmpFile()||'.TXT'
  730.   tmp2 = VOXDIR||TmpFile()||'.FAX'
  731.   log = FxRxPath( 'LOG' )||'fax.log'
  732.  
  733.   call LineOut tmp1, 'Fax Log   ' Date('W') ' '||Date('N') ' ' Time('C')
  734.   call LineOut tmp1, ''
  735.   call LineOut tmp1, ,
  736.        'Type ID      Date    Time  Pg Status Elpsd  Name/RemoteID/CallerID'
  737.   call LineOut tmp1, ''
  738.  
  739.   if LOGMAXLINE <= 0 then do /* send the entire fax log */
  740.     do while Lines( log ) > 0
  741.       record = LineIn( log )        /* read a record from log */
  742.       if FxRxParseLog( record, 'lrec' ) = OK then do
  743.         call LogRpt tmp1
  744.       end
  745.     end
  746.   end
  747.   else do /* send the last x lines from the log */
  748.     head = 1
  749.     tail = 1
  750.     do while Lines( log ) > 0    /* collect last x lines */
  751.       buf.head = LineIn( log )
  752.       head = head + 1
  753.       if head > LOGMAXLINE then head = 1
  754.       if head = tail then tail = tail + 1
  755.       if tail > LOGMAXLINE then tail = 1
  756.     end
  757.     if tail <> head & FxRxParseLog( buf.head, 'lrec' ) = OK then do
  758.       call LogRpt tmp1
  759.     end
  760.     do while tail <> head
  761.       if FxRxParseLog( buf.tail, 'lrec' ) = OK then do
  762.         call LogRpt tmp1
  763.       end
  764.       tail = tail + 1
  765.       if tail > LOGMAXLINE then tail = 1
  766.     end
  767.   end
  768.   rc = LineOut( log )            /* close the files */
  769.   rc = LineOut( tmp1 )
  770.   call FxRxTextToFax tmp1, tmp2        /* convert text to fax */
  771.   /* call our FOD procedure to do the faxing */
  772.   FODPARAMS = "FxRxPath( 'LOG' ), VOXDIR, , CALLER, tmp2," ,
  773.           "'As you requested, the log is attached.', 'Log retrieval...'"
  774.   interpret 'call' "'"||FODPROCEDURE||"'" FODPARAMS
  775.   fodresult = result
  776.   call FxLnVout 'Deleting:' tmp1
  777.   'DEL "'||tmp1||'"'
  778.   call FxLnVout 'Deleting:' tmp2
  779.   'DEL "'||tmp2||'"'
  780.   return fodresult
  781.  
  782.  
  783. LogRpt:
  784.   /* Using global lrec., write a report line to a file */
  785.   parse arg Rfile
  786.  
  787.   if BitTest( lrec.!Flags, 256 ) then mtype = 'MSG'
  788.   else if BitTest( lrec.!Flags, 512 ) then mtype = 'Txt'
  789.   else if BitTest( lrec.!Flags, 1024 ) then mtype = 'Dat'
  790.   else mtype = 'Fax'
  791.  
  792.   if lrec.!Company = ''
  793.   then namestr = lrec.!Name
  794.   else namestr = lrec.!Name||', '||lrec.!Company
  795.  
  796.   if lrec.!Pages = 0
  797.   then pagestr = ''    /* don't show 0 pages */
  798.   else pagestr = lrec.!Pages
  799.       
  800.   call LineOut Rfile, mtype left( lrec.!ID, 6 ) ,
  801.          left( lrec.!Date, 9 ) left( lrec.!Time, 5 ) ,
  802.          right( pagestr, 2 ) left( lrec.!Status, 6 ) ,
  803.          right( lrec.!Elapsed, 5) ' '||strip( left( namestr, 46 ) )
  804.   return
  805.  
  806.  
  807. BitTest: procedure
  808.   /* Given a number and a bit number, return 1 if bit is set */
  809.   parse arg value, bit
  810.   return (value % bit) // 2
  811.  
  812. SaveCode:
  813.   /* Save access code to file MBXnnnnn.COD in user's log directory */
  814.   parse arg newcode
  815.   call LineOut USERDIR||'.cod', newcode, 1
  816.   call LineOut USERDIR||'.cod'        /* close file */
  817.   return
  818.  
  819. FetchCode:
  820.   /* Returns the access code for the current USERID */
  821.   if USERID = 0
  822.   then return CODE
  823.   newcode = LineIn( USERDIR||'.cod', 1 )
  824.   call LineOut USERDIR||'.cod'        /* close file */
  825.   if newcode = '' then newcode = DEFAULTCODE
  826.   return newcode
  827.