<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Structural overview of the default scripts</title><meta name="generator" content="DocBook XSL Stylesheets V1.65.1" /><link rel="home" href="index.html" title="CapiSuite 0.4.5" /><link rel="up" href="ch02.html" title="Chapter 2. Users Guide" /><link rel="previous" href="ch02s05.html" title="Example for an idle script" /><link rel="next" href="ch02s07.html" title="CapiSuite command reference" /></head><body><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Structural overview of the default scripts</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ch02s05.html">Prev</a> </td><th width="60%" align="center">Chapter 2. Users Guide</th><td width="20%" align="right"> <a accesskey="n" href="ch02s07.html">Next</a></td></tr></table><hr /></div><div class="sect1" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="default_script_overview"></a>Structural overview of the default scripts</h2></div></div><div></div></div><div class="sect2" lang="en" xml:lang="en"><div class="titlepage"><div><div><h3 class="title"><a id="default_incoming"></a>incoming.py</h3></div></div><div></div></div><p>The incoming script handles all incoming connections. It reads two configuration files containing all necessary data which were described in detail in <a href="ch01s03.html#script_config" title="Script configuration">the section called “Script configuration”</a>. The overall structure will be described here giving you an overview of how it is implemented.</p><p>Firstly (after importing some necessary modules), it defines the necessary function <tt class="function">callIncoming</tt> which will call all other functions if needed.</p><div class="sect3" lang="en" xml:lang="en"><div class="titlepage"><div><div><h4 class="title"><a id="default_incoming_1"></a>function <tt class="function">callIncoming</tt></h4></div></div><div></div></div><p>This function starts with a call to <tt class="function">cs_helpers.readConfig</tt> to read the configuration. It then iterates through all sections representing the configured users (except <tt class="literal">GLOBAL</tt>) to see if the called number belongs to any user. If a match is found, the user and the defined service are saved to <tt class="literal">curr_user</tt> and <tt class="literal">curr_service</tt>.</p><p>If no match was found (<tt class="literal">curr_user</tt> is empty), the call is rejected and the function returns. Otherwise the directory to use for incoming fax or voice data is determined and created if not existing yet.</p><p>The last thing the function does, is to produce a log entry, accept the call with the right service (fax or voice) and call either <tt class="function">faxIncoming</tt> or <tt class="function">voiceIncoming</tt>. It also defines an exeception handler for <tt class="literal">capisuite.CallGoneError</tt>.</p></div><div class="sect3" lang="en" xml:lang="en"><div class="titlepage"><div><div><h4 class="title"><a id="default_incoming_2"></a>function <tt class="function">faxIncoming</tt></h4></div></div><div></div></div><p><tt class="function">faxIncoming</tt> is quite straight forward: it creates a uniqe filename, calls <tt class="function">capisuite.fax_receive</tt>, disconnects and logs the disconnection reasons. Then it checks if a fax have been really received succesfully (i.e. if the file exists). If yes, it creates a description file for it, <span><b class="command">chown</b></span>'s the file to the right user and sends the file as mail.</p></div><div class="sect3" lang="en" xml:lang="en"><div class="titlepage"><div><div><h4 class="title"><a id="default_incoming_3"></a>function <tt class="function">voiceIncoming</tt></h4></div></div><div></div></div><p><tt class="function">voiceIncoming</tt> has much more features to accomplish like fax recognition and switching to fax mode, starting a remote inquiry etc.</p><p>It starts by determining the directory to use and creating a unique filename. Also, the PIN for remote inquiry is saved to a private variable. There are two possibilites now: the user has already an own announcement - in this case it's played now. Otherwise, a predefined announcement containing of a general announcement and the number which was called is played. If recording a message wasn't disabled (by setting <tt class="literal">voice_action</tt> to <tt class="literal">None</tt>), it starts now after a beep.</p><p>All <tt class="function">audio_send</tt> and <tt class="literal">audio_receive</tt> calls used so far had DTMF abortion enabled and so the script "falls through" all these calls after a DTMF signal was recognized. After them, <tt class="function">read_DTMF</tt> is used to see if any such signal have been found. "<tt class="literal">X</tt>" represents the fax tone and triggers a switch to fax protocols and a call to <tt class="function">faxIncoming</tt>. Any other received signals are interpreted to be a part of the PIN for remote inquiry and so a loop which waits 3 seconds after each tone for the next one is entered. If a valid PIN is entered, it starts the <tt class="function">remoteInquiry</tt>. After three wrong attempts, it will disconnect.</p><p>After disconnecting and logging, a description file is written (if the recorded file exists), both files will be <span><b class="command">chown</b></span>'ed to the right user and the recorded message will be mailed to him/her.</p></div><div class="sect3" lang="en" xml:lang="en"><div class="titlepage"><div><div><h4 class="title"><a id="default_incoming_4"></a>function <tt class="function">remoteInquiry</tt></h4></div></div><div></div></div><p>The <tt class="function">remoteInquiry</tt> starts by creating a lock file and acquiring an exclusive lock on it to prevent two parallel remote inquiries for the same user. If the lock can't be acquired, an error message is played and the function returns. If locking has succeeded, a list of the recorded voice calls is compiled by listing the user directory, filtering and sorting it. Now, a file called <tt class="filename">last_inquiry</tt> is read when it exists. It contains the number of the last heard message. With this information, the old messages can be filtered out to a separate list and thus the caller can listen to messages he doesn't know already first.</p><p>The number of new messages is said, followed by a small menu where the caller can choose to either record an announcment or hear the recorded messages. If he chooses announcement recording, the function <tt class="function">newAnnouncement</tt> is called, otherwise <tt class="function">remoteInquiry</tt> will continue.</p><p>Now, a loop will first iterate over the new and then the all old messages. It starts by telling the caller how much messages have been found. Then all messages will be played, repeating the following steps for each one:</p><div class="itemizedlist"><ul type="disc"><li><p>read the description file of the current message</p></li><li><p>play an information block containing the current message number, source, destination, date and time of the call.</p></li><li><p>play the message</p></li><li><p>provide a menu where the caller can go on to the next or last message, repeat the current message or delete it</p></li></ul></div><p>At the end, the caller will be informed that no more messages are available and the connection will be finished, followed by releasing the lock file and deleting it.</p></div><div class="sect3" lang="en" xml:lang="en"><div class="titlepage"><div><div><h4 class="title"><a id="default_incoming_5"></a>function <tt class="function">newAnnouncement</tt></h4></div></div><div></div></div><p><tt class="function">newAnnouncement</tt> presents some instructions to the caller first. Then, the new announcement will be recorded to a temporary file. To give the user the ability to check it, it will be played, followed by a menu allowing him/her to save it or to repeat the recording. If the user has chosen to save it, it will be moved from the temporary file to <tt class="filename">announcement.la</tt> in the users voice directory and <span><b class="command">chown</b></span>'ed to him/her. The call will be finished with an approval to the caller that it has been saved succesfully.</p></div></div><div class="sect2" lang="en" xml:lang="en"><div class="titlepage"><div><div><h3 class="title"><a id="default_idle"></a>idle.py</h3></div></div><div></div></div><p>The idle script is responsible for collecting jobs from the send queues (where they're stored by <span><b class="command">capisuitefax</b></span>) and sending them to the given destinations. It reads its configuration from the files presented in <a href="ch01s03.html#script_config" title="Script configuration">the section called “Script configuration”</a>, too. </p><div class="sect3" lang="en" xml:lang="en"><div class="titlepage"><div><div><h4 class="title"><a id="default_idle_1"></a>function <tt class="function">idle</tt></h4></div></div><div></div></div><p>After reading the configuration by calling <tt class="function">cs_helpers.readConfig</tt> and testing for the existence of the archive directories needed, the userlist is compiled from the list of available sections.</p><p>For each user who has a valid fax setup (otherwise this user will be skipped), the send queue will be looked at. If the necessary queue directories don't exist, they'll be created. After that, a list called <tt class="literal">files</tt> with the names of all files in the send queue is created and filtered to only contain fax jobs.</p><p>For each found job, a security check is done to see if it was created by the right user. If this check was successful, a lock file is created and a lock on it is acquired. This prevents the <span><b class="command">capisuitefax</b></span> command to abort a job while it is in transfer. After that, the existence of the file is checked (perhaps the job has been cancelled before we could acquire the lock?).</p><p>Now, the description file for this job is read and the starttime is checked. If it's not reached, the script will go on with the next job. Otherwise, some parameters are taken from the configuration and a log message is created. The file is transferred by calling <tt class="function">sendfax</tt>. The results are stored and logged. If the job was successful, it is moved to the done dir and an approval is mailed to the user. If it wasn't succesful, the delay interval will be determined from the configuration and the new starttime is calculated by increasing the old starttime by this interval. A counter for the used tries is increased and the description file is rewritten with the new values. If the number of tries exceeds a given maximum, the job is moved to the failed dir and the error is reported to the user by mail.</p><p>Finally, the lock file will be unlocked and deleted.</p></div><div class="sect3" lang="en" xml:lang="en"><div class="titlepage"><div><div><h4 class="title"><a id="default_idle_2"></a>function <tt class="function">sendfax</tt></h4></div></div><div></div></div><p>This function handles the send process. After determining the MSN to use from either the <tt class="literal">outgoing_MSN</tt> setting or from the <tt class="literal">fax_numbers</tt> list, a call to the destination is initiated. If it fails, the function returns; otherwise the file will be sent and the connection finished.</p></div><div class="sect3" lang="en" xml:lang="en"><div class="titlepage"><div><div><h4 class="title"><a id="default_idle_3"></a>function <tt class="function">movejob</tt></h4></div></div><div></div></div><p>This is a small helper function used for moving a job and its accompanying description file to another directory.</p></div></div><div class="sect2" lang="en" xml:lang="en"><div class="titlepage"><div><div><h3 class="title"><a id="default_capisuitefax"></a>capisuitefax</h3></div></div><div></div></div><p><span><b class="command">capisuitefax</b></span> allows to enqueue fax jobs, list the current queue and abort jobs. It's not used directly by the <span class="application">CapiSuite</span> system - it's a frontend for the users send queue directory. It has several commandline options - for an explanation of its usage, please refer to <a href="ch01s04.html#usingscripts_send" title="Sending fax jobs">the section called “Sending fax jobs”</a>.</p><p>There are three helper functions defined first. <span class="emphasis"><em><tt class="function">usage</tt></em></span> prints out a small help if "<tt class="option">--help</tt>" or "<tt class="option">-h</tt>" was given as parameter or if a parameter isn't understood. <span class="emphasis"><em><tt class="function">showlist</tt></em></span> gets a listing from the users send queue directory and prints it nicely formatted as table. <span class="emphasis"><em> <tt class="function">abortjob</tt></em></span> removes a job from the queue. It does this safely by using a lock file to not interfere with the sending process.</p><p>The main code of this script checks the given commandline options first. It sets several variables to the given values. After some checks of the validity of the options, the rights of the user to send faxes and the existence of the necessary directories, it will fulfill the requested task. Either, <tt class="function">listqueue</tt> will be called to show a listing of active jobs, <tt class="function">abortjob</tt> to abort a job or the given files are processed and put to the queue.</p><p>To process a job, the existence of it and its format will be checked. Currently, only PostScript is allowed. The <span class="application">CapiSuite</span> core itself only supports the SF format. Therefore, the files are coverted from PostScript to it by calling <span><b class="command">ghostscript</b></span>. Finally, the description file for this job is created containing the given parameters like the destination number.</p></div><div class="sect2" lang="en" xml:lang="en"><div class="titlepage"><div><div><h3 class="title"><a id="default_helpers"></a>cs_helpers.py</h3></div></div><div></div></div><p>The <tt class="filename">cs_helpers.py</tt> script contains many small helper functions used in the other scripts. These are:</p><div class="variablelist"><dl><dt><span class="term"><tt class="function">readConfig</tt></span></dt><dd><p>Reads either the configuration files described in <a href="ch01s03.html#script_config" title="Script configuration">the section called “Script configuration”</a> or an arbitrary config file like the description files accompanying each received file or job to send.</p></dd><dt><span class="term"><tt class="function">getOption</tt></span></dt><dd><p>Get an option from the given user section and fall back to the global section if it's not found.</p></dd><dt><span class="term"><tt class="function">getAudio</tt></span></dt><dd><p>Get an audio file from the users directory or fall back to the global <span class="application">CapiSuite</span> directory.</p></dd><dt><span class="term"><tt class="function">uniqueName</tt></span></dt><dd><p>Construct a new file name in a given directory by using a given prefix & suffix and adding a counter. See also <a href="ch02s04.html#incoming_tut_unique_names" title="Using sensible file names">the section called “Using sensible file names”</a>.</p></dd><dt><span class="term"><tt class="function">sendMIMEMail</tt></span></dt><dd><p>Send an e-mail with attachment to a given user. Supports also automatic format conversion SFF -> PDF and inversed A-Law -> WAV.</p></dd><dt><span class="term"><tt class="function">sendSimpleMail</tt></span></dt><dd><p>Send a normal e-mail without attachment to a given user.</p></dd><dt><span class="term"><tt class="function">writeDescription</tt></span></dt><dd><p>Create a description file which can be read by <tt class="function">readConfig</tt> later.</p></dd><dt><span class="term"><tt class="function">sayNumber</tt></span></dt><dd><p>Supports saying a number using various wave fragments. Works only for german output currently.</p></dd></dl></div><p>For a detailled description of each function and its usage, please have a look at the script file itself. There are comments describing each function in detail.</p></div></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ch02s05.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="ch02.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="ch02s07.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Example for an idle script </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> CapiSuite command reference</td></tr></table></div></body></html>