Sofaswitch-svn
Threads by month
- ----- 2026 -----
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
June 2007
- 1 participants
- 69 discussions
Author: derek
Date: Fri Jun 8 00:05:34 2007
New Revision: 272
Added:
sofaswitch/trunk/callflow/docs/app1.sgml
sofaswitch/trunk/callflow/docs/chap1.sgml
sofaswitch/trunk/callflow/docs/chap2.sgml
sofaswitch/trunk/callflow/docs/chap3.sgml
Log:
Add these files, which are the split up chapters from description.sgml
Added: sofaswitch/trunk/callflow/docs/app1.sgml
==============================================================================
--- (empty file)
+++ sofaswitch/trunk/callflow/docs/app1.sgml Fri Jun 8 00:05:34 2007
@@ -0,0 +1,21 @@
+<appendix>
+<title>Building these docs</title>
+<para>
+The documentation for %callflow was generated from multiple
+<literal>.sgml</literal> and <literal>.xml</literal files. The utility
+<screenshot>
+xsltproc
+</screenshot>
+was used to process the supplied files to generate <literal>html</literal>
+files and several auxillary help files. The generated files were compressed
+into one <literal>.zip</literal> file. When the &callflow; utility runs, it
+reads in the supplied zip file (which contains the index information). A
+<literal>wxWidgets</literal> class is used to display the html documentation.
+</para>
+
+<para>
+The file <literal>makedoc.xsl</literal> contains the stylesheet commands that
+are used when converting the docbook file <literal>callflow.xml</literal> into html.
+</para>
+</sect1>
+</appendix>
Added: sofaswitch/trunk/callflow/docs/chap1.sgml
==============================================================================
--- (empty file)
+++ sofaswitch/trunk/callflow/docs/chap1.sgml Fri Jun 8 00:05:34 2007
@@ -0,0 +1,103 @@
+<chapter>
+<title>Introduction</title>
+<para>&callflow; is a utility which has been designed to enable the user to control
+the various entities in the &sofaswitch; system. This utility allows the
+user to graphically design call setup, connection, and teardown. This utility
+takes the graphical layout and generates Python code, which implements the
+desired operation. </para>
+
+<para>Python is areasonably tidy language, cross platform, straightforward syntax and does not
+have the dependency hell of perl. Sadly, nothing is easy, and it takes
+considerable effort to write Python scripts to control &sofaswitch; utilities. A
+graphical approach is preferable.
+</para>
+
+<para>
+The user will be exposed to some Python, but at a relatively simple
+level. These blocks of Python code are regular expressions and label
+defination. Consequently, it is straightforward, and quite manageable for the
+novice. The example flow graphs contain many blocks of Python code, which are
+a useful guide to the novice.
+</para>
+
+<para>The following section gives an overview of the operation of
+&callflow;. Subsequent chapters describe the operation of &callflow; by means
+of examples, and by a detailed description of each available control structure.
+</para>
+
+<sect1> <title>Overview of operation</title>
+<para>Various items are selected from the tool bar, and placed on the screen. These are connected
+together. Once the flow diagram is completed, it is compiled by selection of
+the compile button. Two files are generated.
+<itemizedlist>
+ <listitem><para>a graph file, which describes the items
+ on the screen, their internal settings ,and how they are connected. </para></listitem>
+ <listitem><para>a Python file, which contains Python documentation and Python code to run
+ any graph file, and one line which invokes the reading of the generated
+ graph file.</para></listitem>
+</itemizedlist>
+</para>
+
+<para>
+The Python executable is, in fact, able to process any graph file. This happens
+as the Python executable contains all the methods for all known types of
+items. Indeed, if you compile two different graphs on the screen, the only
+difference in the generated Python code is the specified graph
+file. Consequently, it is possible for the one Python executable to load
+multiple graph files and do multiple concurrent calls.
+</para>
+
+<para>Prior to execution of the Python file, it is expected the server is
+running. The compiled Python script will contain instructions (as set by the
+user) to request nodes at the different &sofaswitch;
+entities. Should there be no reply (the entity is not running) there will be
+a timeout, and the user's code will need to respond accordingly. This Python
+script can be executed in a console, and the user can monitor the messages
+that flow to/from the server to see how things are progressing. Once the
+script has been tested with 1 call, multiple calls can be handled by multiple
+instances of the script.</para>
+
+<para>
+Each Python file invokes the handling of variables for all items on the screen
+within one instance of the <literal>Controller</literal> class. Should a
+separate graph be required to simultaneously, it will be run within a second
+instance of the <literal>Controller</literal> class. Thus, all graphs are kept
+totally separate. Should the user wish to share data between different
+executing graphs, thread safe structures such as databases should be used. To
+communicate between different instances of the <literal>Controller</literal>
+class, one may send messages via the server.
+</para>
+
+<para>
+For safety, variables required should be limited to the scope of the class that
+this graph is running. Consequently, if there are multiple instances of this
+graph being used, there will be no variable collision. It is therefore
+suggested that all variables have the string <literal>self</literal> before
+them. Consequently, you would refer to the variable <literal>i</literal> as
+<literal>self.i</literal>
+</para>
+
+<para>One difficulty with Python is the inability to handle threads well. They
+are available, but are very heavyweight in terms of system load, but provide
+limited gain. To illustrate, a multi threaded Python application will run at
+the same speed on a multiprocessor box as on a single cpu box. Worse, each new
+thread running in Python is a whole new running interpreter, which consumes
+system resources. This posed a problem - if the controller is going to handle
+lots of concurrent calls, it would be poor practice to place each controller
+handled call into a separate Python thread. </para>
+
+<para> We therefore base this code around
+<ulink URL="http://twistedmatrix.com/trac"></ulink> an event driven network
+framework written in Python. Using Twisted solved the handling of the any
+number of asynchronous events.. Further, we could have one psuedo thread per
+call, but in reality there is one thread in operation. One psuedo thread per
+call makes things much simpler to analyse. </para>
+
+<para>The Python code will process the items on the graph, until it reaches
+the end of the current graph. Execution then waits for a event to happen,
+which move the current point of execution back to the relevant event handler.
+Thus, a call flow graph in this system will only have one start point, but may
+have many termination points.
+</para>
+</sect1>
+</chapter>
Added: sofaswitch/trunk/callflow/docs/chap2.sgml
==============================================================================
--- (empty file)
+++ sofaswitch/trunk/callflow/docs/chap2.sgml Fri Jun 8 00:05:34 2007
@@ -0,0 +1,241 @@
+<chapter>
+<title> Example flow graphs for &callflow;</title>
+<para>
+We provide in this chapter multiple examples of the usage of
+&callflow;. These have been designed to give the reader an
+idea of the different components available, and how they link together. A full
+scale PBX will combine these elements together.
+</para>
+
+<para>
+One should remember that each graph is designed to handle one call. Events are
+posted to each graph, that are relevant to each call. Multiple calls can be
+handled simultaneously by spawning off graphs with the aid of the
+<literal>Load New Graph</literal> widget. Thus, on receiving notification of an
+incoming call, one would spawn of a <literal>Load New Graph</literal>, which is
+designed to handle that particular incoming call.
+</para>
+
+<sect1>
+<title>Hello World example</title>
+<para>
+Perhaps the simplest example of a graph you can create is the standard "Hello
+World" example, shown here, in figure <xref linkend="helloworldexample"/>.
+<figure id="helloworldexample">
+<title>The obligatory Hello World example</title>
+<mediaobject>
+<imageobject>
+<imagedata fileref="helloworld.png" align="center" format="PNG"></imagedata>
+</imageobject>
+</mediaobject>
+</figure>
+
+An example of a simple call flow graph. The properties of the Python object in the middle have been adjusted to contain
+ code to print text to the console. On execution, a text message is sent to the console.
+</para>
+
+<para>
+Python will start executing at the very top box, process the code in the
+middle, and then terminate at the bottom. The operation of the three boxes (top to bottom) is
+<itemizedlist>
+ <listitem><para>On loading of this graph, execution will start at this box. It is an error to
+ have two such flow generation boxes on the page.</para></listitem>
+ <listitem><para>Execute the Python code, which has been defined by
+ the user, in the properties of this instance of the Python code
+ box.</para></listitem>
+ <listitem><para>The skull and crossbones symbol indicates ther
+termination of this thread of execution, and then disconnect from the
+server. All future events are ignored. Other threads of execution on other
+pages are not influenced.
+ </para></listitem> </itemizedlist> </para>
+
+<para>Program flow is invariably top to
+bottom. Arrows are drawn on the output and input of each box to indicate where
+the flow is going. You will notice four black circles, filled, on this
+graph. They indicate a connection between the different entities.
+</para>
+</sect1>
+
+<sect1>
+<title>For Loops</title>
+<para>
+The flow of execution is to follow the graph on the screen and behaves likes a
+for loop in the pogramming language "C". Thus, start at the beginning,
+initialise the loop variable, evaluate the termination clause and goto the
+body of the for loop or the end block (if the termination clause is false). On
+completion of the body of the for loop, return back to the start. Execute the
+increment operation and then evaluate the termination condition. If the
+termination condition is false, execute the body of the for loop. The
+initialisation, increment operator, and termination condition, consist of
+Python code that is set in the preferences at the beginning of the for loop
+(right mouse button on the for loop entity). A simple example of a for loop is
+shown in figure <xref linkend="forloopexample"/>.
+<figure id="forloopexample">
+<title>Example of a for loop</title>
+<mediaobject>
+<imageobject>
+<imagedata fileref="forloop.png" align="center" format="PNG"></imagedata>
+</imageobject></mediaobject>
+</figure>
+</para>
+
+<para> While processing each of the nodes in the supplied graph, it is
+ignoring all timer events. Execution continues until it falls of the end of
+the graph, or passes through an Eventer type structure and goes nowhere. Once
+execution has gone nowhere, the system will process pending events.
+</para>
+
+
+
+</sect1>
+
+
+<sect1>
+<title>Event handling</title>
+<para>
+We describe the handling of events in this section, with a simple example.
+Consider the figure <xref linkend="simpleeventexample"/>.
+<figure id="simpleeventexample">
+<title>Example of event handling</title>
+<mediaobject>
+<imageobject>
+<imagedata fileref="simpleevent.png" align="center" format="PNG"></imagedata>
+</imageobject>
+</mediaobject>
+</figure>
+</para>
+
+<para>
+Execution starts at the top, moves to the next node which sends off a request
+to obtain a new worker node. Then, the eventer box is entered, where we
+register to receive any event that contains the word "NEW" (we are searching
+for all events advising of a new node). At which point, execution continues to
+the right, and goes into the lower "execute Python code" box, which prints a
+message. Finally, execution moves into the bottom most box, and is suspended.
+</para>
+
+<para>
+At this point, we rely upon the twisted module in Python to call methods
+indicating that things have happened (e.g. a timer, data received from network
+etc). On receipt of a message about a new node, execution is moved to the box
+on the star output of the eventer box. Thus, the left Python code box is
+executed, which (in this case) reports the id of the voip node created.
+Execution then moves to the skull and cross bones and terminates.
+</para>
+
+
+<para>
+Of crucial importance is that the user should note that all events (such as network
+and timer) are only processed when execution has stopped. Thus, execution has
+to have moved to a suspend execution box. In the graphic above, execution is
+suspended when it moves to the right side of the graph and down. After the
+event has happened, execution moves to the skull and crossbones and this entire
+graph is terminated.
+</para>
+
+<para>
+The eventer object, on selecting the right mouse button, brings up a properties
+box that has multiple fields
+<informaltable frame="all">
+<tgroup cols="2">
+<tbody>
+<row> <entry>
+ <literal>Event Sought</literal></entry> <entry><para>The
+event this box waits for can be described as text or Python code, which is
+matched as a regular expression to each event. The user should specify the
+event in Python code or as text.</para></entry></row>
+<row>
+ <entry><literal>Python variable:source of the event</literal></entry>
+ <entry><para>The source of the event (node id or timer) is
+ recorded in the specified Python variable.</para></entry> </row>
+ <row>
+ <entry><literal>Python variable:name of the event</literal></entry>
+ <entry><para>The name of the event (such as <literal>RequestNode</literal>)
+ is stored in the specified Python variable</para></entry></row>
+ <row>
+ <entry><literal>Python variable:generated data</literal></entry>
+ <entry><para>This Python variable may not receive a value (and will be set
+to <literal>None</literal>), but sometimes will get a value, to be used in
+subsequent elements of this graph. One example is when the user requests a node
+from a remote &sofaswitch; entity. The received node id will
+be stored in this variable. Alternatively, DTMF data received from a remote
+&sofaswitch; entity will be stored in this
+variable.</para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+</para>
+</sect1>
+
+
+<sect1>
+<title>Trivial transfer audio</title>
+<para>
+Key to the operation of &sofaswitch; is the ability to move
+audio from one entity to another. This audio passes directly betweeen
+entities, and does not go via the server. The &sofaswitch;
+entities themselves worry about the transport of the data. The trivial example in
+figure <xref linkend="trivialtransferexample"/> shows the transfer of audio from
+the sound entity back to the sound entity. Consequently, audio that is captured
+at the mic will be directed to the speaker. The sound entity has therefore been told to
+talk to itself.
+<figure id="trivialtransferexample">
+<title>Trivial example of the transfer of audio</title>
+<mediaobject>
+<imageobject>
+<imagedata fileref="trivialtransfer.png" align="center" format="PNG"></imagedata>
+</imageobject>
+</mediaobject>
+</figure>
+</para>
+
+<para>
+In this example, there is no request process for a "sound" entity. The code
+just assumes a "sound" entity is there, and writes directly to it. Should this
+assumption be wrong, and "sound" is not available, there will be no error. The
+message server will receive the transfer request, and silently drop it on the
+floor.
+</para>
+
+<para>
+There is no limit on the when the transfer media request is sent, or on how
+many are sent. Thus, as the call progresses, one can transfer media to an
+answering machine (to record audio/play a message), conference device or to an
+outgoing voip/tdm call. In this way, one can build a full IVR system by
+connecting the audio stream to different objects as required.
+</para>
+</sect1>
+
+
+<sect1>
+<title>Transfer audio, and timer example</title>
+<para>
+We describe the handling of events in this section, with a simple example.
+Consider the figure <xref linkend="amtestexample"/>.
+<figure id="amtestexample">
+<title>Example of audio transfer between &sofaswitch; nodes,
+and timers.</title>
+<mediaobject>
+<imageobject>
+<imagedata fileref="amtest.png" align="center" format="PNG"></imagedata>
+</imageobject>
+</mediaobject>
+</figure>
+</para>
+
+<para>
+This graph connects an answering machine node to the sound card node. The
+answering machine node, on creation, is asked to record audio from the sound
+card, and send audio to the sound card. When DTMF character is received from
+the sound card, or node termination event occurs, the test is ended. On test
+end, the sound card is asked to direct audio to itself, and a timer is started.
+</para>
+
+<para>
+ The timer is a mechanism to stop the immediate handling of items on this
+graph, and all outstanding messages are sent, and events are handled. Thus, the
+message to the sound entity is actually sent. On the timer completing, death
+happens and this graph is closed down.
+</para>
+</sect1>
+</chapter>
Added: sofaswitch/trunk/callflow/docs/chap3.sgml
==============================================================================
--- (empty file)
+++ sofaswitch/trunk/callflow/docs/chap3.sgml Fri Jun 8 00:05:34 2007
@@ -0,0 +1,1583 @@
+<chapter>
+<title>Description of each control box in &callflow;</title>
+<para>
+Each of the available control structures in the &callflow;
+program is described in this section. In particular, the different parameters
+available are explained. Posible applications for each control box are given,
+to aid the user in deciding which one to use.
+</para>
+
+<para>
+All of the control structures in this application have optional parameters.
+Usually, these are strings, with no quotes required, and this is the case for
+parameters such as tool tips. Sometimes, the parameters are labelled as being
+Python code. In this case, you can specifiy a Python variable, so a possible
+value could be <literal>self.amNode</literal>. Alternatively, you can specify
+a string, which is indicated by placing double quotes at either end. Which
+makes <literal>"voip"</literal> an example of valid string Python code.
+</para>
+
+
+
+
+<sect1>
+<title>Conditional execution</title>
+<para>
+Consider the figure <xref linkend="conditionalicon"/> which shows the icon
+and graph representation of the control structure used to direct the flow of
+execution, given the outcome of a Python statement.
+<figure id="conditionalicon">
+<title>Conditonal control element</title>
+<informaltable frame="none">
+<tgroup cols="2">
+<tbody>
+<row><entry><para>
+<mediaobject><imageobject>
+ <imagedata fileref="../html/ControlsIf.png" align="center" scale="300" format="PNG"></imagedata>
+</imageobject></mediaobject>
+</para></entry>
+<entry><para>
+<mediaobject><imageobject>
+<imagedata fileref="../html/conditional.png" align="center" format="PNG"></imagedata>
+</imageobject></mediaobject>
+</para></entry></row>
+<row><entry><para>icon </para></entry>
+ <entry><para>graph representation</para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+</figure>
+</para>
+
+<para>
+This control structure will execute the user supplied Python code, and direct
+the flow of execution to the bottom (true result) or right (false result).
+</para>
+
+<para>
+ It is valid to connect the output of this control structure to another
+structure, even though the destination structure is already connected
+elsewhere. In this case, the flow of execution is not amiguous.
+</para>
+
+<para>
+The code that is evaluated (to determine which way to go) is not evaluated
+until the compiled graph is executed. Should the condition test generate an
+exception when it is evaluated, a message will be printed and the flow of
+execution moves to the false direction.
+</para>
+
+
+<para>
+The Conditional control structure, on selecting the right mouse button, brings up a properties
+box that has multiple fields
+
+<informaltable frame="all">
+<tgroup cols="2">
+<tbody>
+
+<row> <entry><literal>
+Tool tip
+</literal></entry>
+<entry><para>
+The text which is displayed when the mouse hovers over this object for 3 seconds.
+Ideally, you should extend this to contain a description of the test to be completed.
+</para></entry></row>
+
+<row> <entry><literal> Test (Python code)
+</literal></entry>
+<entry><para>
+The Python code that generates a <literal>true</literal> or
+<literal>false</literal> value is entered here. The code has access to all the
+variables defined previously while processing the current graph.
+</para></entry></row>
+
+
+</tbody>
+</tgroup>
+</informaltable>
+
+
+</para>
+</sect1>
+
+
+
+
+
+
+<sect1>
+<title>Death - terminate processing of this graph</title>
+<para>
+Consider the figure <xref linkend="deathicon"/> which shows the icon
+and graph representation of the control structure used to immediately terminate
+all processing of this graph.
+<figure id="deathicon">
+<title>Death control element</title>
+<informaltable frame="none">
+<tgroup cols="2">
+<tbody>
+<row><entry><para>
+<mediaobject>
+<imageobject>
+<imagedata fileref="../bitmaps/death.png" align="center" scale="300" format="PNG"></imagedata>
+</imageobject>
+</mediaobject>
+</para></entry>
+<entry><para>
+<mediaobject>
+<imageobject>
+<imagedata fileref="../html/Death.png" align="center" format="PNG"></imagedata>
+</imageobject>
+</mediaobject>
+</para></entry></row>
+<row><entry><para>icon </para></entry>
+ <entry><para>graph representation</para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+</figure>
+</para>
+
+<para>
+On evaluation of the compiled code, execution of all elements in this graph
+is terminated. All current or pending events are ignored. All outstanding
+timers are ignored. Messages which have been defined to be sent out (such as
+termination of a remote node) are dropped.
+</para>
+
+<para>
+If the graph which executes the death control structrue is the one launched
+from the command line, it is applied to all graphs. However, if this is a child
+graph (launched from a "load new graph" control structure), then death only
+applies the child graph. Consequently, the parent graph can receive incoming
+calls, and send all incoming calls to multiple child graphs. Each child graph
+may execute the death control structure, and not influence the other calls.
+</para>
+
+<para>
+The outcome of executing this control structure is very simple - it will remove
+the id associated with this graph (<literal>self.myId</literal>) from the
+server.
+</para>
+
+<para>
+The death control structure, on selecting the right mouse button, brings up a properties
+box that has one field
+<informaltable frame="all">
+<tgroup cols="2">
+<tbody>
+
+<row> <entry><literal>
+Tool tip
+</literal></entry>
+<entry><para>
+The text which is displayed when the mouse hovers over this object for 3 seconds.
+Ideally, you should extend this to contain some meaningful comment about the
+circumstances around the shutdown, or perhaps leave this field blank.
+</para></entry></row>
+
+
+</tbody>
+</tgroup>
+</informaltable>
+
+
+</para>
+</sect1>
+
+
+
+
+
+<sect1>
+<title>End a call</title>
+<para>
+Consider the figure <xref linkend="endcallicon"/> which shows the icon
+and graph representation of the control structure used to end a call, or
+terminate a &sofaswitch; node. Thus, you could use this
+control structure to terminate a voip call or close down an answering machine
+worker node.
+<figure id="endcallicon">
+<title>End call control element</title>
+<informaltable frame="none">
+<tgroup cols="2">
+<tbody>
+<row><entry><para>
+<mediaobject>
+<imageobject>
+<imagedata fileref="../html/endcall.png" align="center" format="PNG"></imagedata>
+</imageobject>
+</mediaobject>
+</para></entry>
+<entry><para>
+<mediaobject>
+<imageobject>
+<imagedata fileref="../html/EndCall.png" align="center" format="PNG"></imagedata>
+</imageobject>
+</mediaobject>
+</para></entry></row>
+<row><entry><para>icon </para></entry>
+ <entry><para>graph representation</para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+</figure>
+</para>
+
+<para>
+This control structure causes the remote worker node to die. Thus, one would
+hangup the call, and then create a new worker node to make a new call. There
+is no intention of allowing a voip node (say) to make multiple consequetive
+calls. The code is build around "One node, one call".
+</para>
+
+<para>
+Created nodes from the answering machine, and conference room will, once they
+have passed the intial "use in 2 seconds timeout", endeavour to live
+forever. There is no automatic means of destroying these nodes. On graph
+closedown, these nodes are not deleted - some other graph might have taken
+control of the nodes. To remove these created nodes, one has to use this
+control structure.
+</para>
+
+<para>
+The end call control structure, on selecting the right mouse button, brings up a properties
+box that has multiple fields
+
+<informaltable frame="all">
+<tgroup cols="2">
+<tbody>
+
+<row> <entry><literal>
+Tool tip
+</literal></entry>
+<entry><para>
+The text which is displayed when the mouse hovers over this object for 3 seconds.
+Ideally, you should extend this to contain information about the worker node to
+be closed down.
+</para></entry></row>
+
+<row> <entry><literal>Worker node for termination (Python code)
+</literal></entry>
+<entry><para>
+This field describes the identity of the remote node that is to be
+terminated. If the value could not be evaluated, there will be a
+warning message on running the generated Python code. If the supplied value
+does not match any node in existance, nothing will happen - the message server
+will silenty drop the termination message.
+</para></entry></row>
+
+
+</tbody>
+</tgroup>
+</informaltable>
+
+
+</para>
+</sect1>
+
+
+
+
+
+
+
+
+<sect1>
+<title>Event collection and registration</title>
+<para>
+Consider the figure <xref linkend="eventicon"/> which shows the icon
+and graph representation of the control structure used to collect events, and register
+for events.
+<figure id="eventicon">
+<title>Event control element</title>
+<informaltable frame="none">
+<tgroup cols="2">
+<tbody>
+<row><entry><para>
+<mediaobject>
+<imageobject>
+<imagedata fileref="../html/eventer.png" align="center" scale="300" format="PNG"></imagedata>
+</imageobject>
+</mediaobject>
+</para></entry>
+<entry><para>
+<mediaobject>
+<imageobject>
+<imagedata fileref="../html/Eventer.png" align="center" format="PNG"></imagedata>
+</imageobject>
+</mediaobject>
+</para></entry></row>
+<row><entry><para>icon </para></entry>
+ <entry><para>graph representation</para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+</figure>
+</para>
+
+<para>
+This control structure is central to the processing of each graph. With this
+item, we have made it possible for the system to respond to network and timer
+events. Further, this structure provides a general means of registering to
+receive an event. Multiple event control structrures can be on a graph, where
+each structure waits for a different event.
+</para>
+
+<para>
+In our implementation, events are collected in the background, and then
+processed after execution has fallen into a "Suspend Processing" box, which is
+described below.
+</para>
+
+<para>
+The Event control structure has two outputs:
+<itemizedlist>
+ <listitem><para>On the right, which is where execution goes after registering for an
+ event.</para></listitem>
+ <listitem><para>On the bottom, which is where execution returns to after detecting the
+ event. This output is labelled with a star on the graph page.</para></listitem>
+</itemizedlist>
+</para>
+
+
+
+<para>
+The Event control structure, on selecting the right mouse button, brings up a properties
+box that has multiple fields
+<informaltable frame="all">
+<tgroup cols="2">
+<tbody>
+
+<row> <entry><literal>
+Tool tip
+</literal></entry>
+<entry><para>
+The text which is displayed when the mouse hovers over this object for 3 seconds.
+Ideally, you should extend this to contain a description of the event sought.
+</para></entry></row>
+
+<row> <entry><literal>Event sought (Python code)</literal></entry>
+<entry><para>
+Either this, or the next element on this table, should be filled in. The code
+is evaluated, which should produce a string. This string is treated as a
+regular expresssion, and compared with the available events.
+</para></entry></row>
+
+<row> <entry><literal>Event sought(Regular Exp)</literal></entry>
+<entry><para>
+This string is treated as a
+regular expresssion, and compared with the available events. Thus, the string
+<literal>DTMF</literal> will match all strings containing these letters, from
+all nodes in this graph.
+</para></entry></row>
+
+<row> <entry><literal>Python variable: source of the event</literal></entry>
+<entry><para>
+Describes the identity of the &sofaswitch; node that
+generated the event. In the case of a Timer event, it will be set to <literal>None</literal>.
+</para></entry></row>
+
+<row> <entry><literal>Python variable: name of the event</literal></entry>
+<entry><para>
+This Python variable describes the name of the event that has occurrd
+</para></entry></row>
+
+<row> <entry><literal>Python variable: generated data
+</literal></entry>
+<entry><para>
+Contains any associated data with the event. So, for <literal>DTMF</literal> it
+will contain the detected stream of characters. For an incoming voip call, it
+will contain the identity of the remote person who made the call.
+</para></entry></row>
+
+
+</tbody>
+</tgroup>
+</informaltable>
+</para>
+
+<para>
+ When this structure is first entered, to register to receive an event, all of
+the Python variables listed in the above table are initialised to
+<literal>None</literal>.
+</para>
+</sect1>
+
+
+
+
+
+
+
+
+
+<sect1>
+<title>Join items</title>
+<para>
+Consider the figure <xref linkend="joinlinesicon"/> which shows the icon
+representation of the control structure used to
+<figure id="joinlinesicon">
+<title>Join control element</title>
+<informaltable frame="none">
+<tgroup cols="1">
+<tbody>
+<row><entry><para>
+<mediaobject>
+<imageobject>
+<imagedata fileref="../html/joinlines.png" align="center" format="PNG"></imagedata>
+</imageobject>
+</mediaobject>
+</para></entry> </row>
+<row><entry><para>icon </para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+</figure>
+</para>
+
+<para>
+Items on the drawing screen may be joined directly - one to another, or joined
+with this structure, which is multiline segment object. Select the toolbar
+icon, move to the drawing area, and left click to mark the points on the shape
+and complete with the right mouse button. Once completed, you may move the
+shape by selecting it with the left button or shift left to select multiple
+objects.
+</para>
+
+<para>
+When there is a valid connection at both ends of this object, a filled black
+circle is drawn at each end. Attempting to connect the outputs of two control
+structures together is not valid, and no filled black circles will be drawn.
+</para>
+
+<para>
+It is entirely valid to have the output of several items connected to one
+item. There is no ambiguity over where the flow of execution should
+go. However, connecting the output of one control item to multiple other
+control items is incorrect, as the correct direction for execution is not
+determinable.
+</para>
+
+
+
+<para>
+The join items object, on selecting the right mouse button, brings up a properties
+box that has one fields
+<informaltable frame="all">
+<tgroup cols="2">
+<tbody>
+
+<row> <entry><literal>
+Tool tip
+</literal></entry>
+<entry><para>
+The text which is displayed when the mouse hovers over this object for 3 seconds.
+Ideally, you should extend this to contain comment about the logic
+flow. Alternatively, you could clear this field to minimise the amount of
+displayed text to the screen.
+</para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+
+
+</para>
+</sect1>
+
+
+
+
+
+
+
+
+
+
+<sect1>
+<title>Load new graph</title>
+<para>
+Consider the figure <xref linkend="loadnewgraphicon"/> which shows the icon
+and graph representation of the control structure used to load a new graph file
+into the currently running Python executable.
+<figure id="loadnewgraphicon">
+<title>Load new graph control element</title>
+<informaltable frame="none">
+<tgroup cols="2">
+<tbody>
+<row><entry><para>
+<mediaobject>
+<imageobject>
+<imagedata fileref="../html/newgraph.png" align="center" format="PNG"></imagedata>
+</imageobject>
+</mediaobject>
+</para></entry>
+<entry><para>
+<mediaobject>
+<imageobject>
+<imagedata fileref="../html/loadnewgraph.png" align="center" format="PNG"></imagedata>
+</imageobject>
+</mediaobject>
+</para></entry></row>
+<row><entry><para>icon </para></entry>
+ <entry><para>graph representation</para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+</figure>
+</para>
+
+
+<para>
+This item provides the means to extend one graph so that it can launch child
+processes. It is similar to the C command <literal>system</literal>, except
+that control returns immediately to the parent process and does not wait for
+execution to finish in the child process.
+</para>
+
+<para>
+It is not similar to threads in C, as the child process does not have access to
+the memory of the parent process. Nor is it similar to
+<literal>fork()</literal> in C, as there is no duplication of the parent
+process.
+</para>
+
+<para>
+As a convenience, the child process always has a Python variable,
+<literal>self.parentId</literal> defined, which contains the id of the child
+process. The child may send a message (via the server) to the parent Id
+indicating status. The variable <literal>self.parentId</literal> is
+<literal>None</literal>, if there is no parent.
+</para>
+
+<para>
+The load new graph control object, on selecting the right mouse button, brings up a properties
+box that has multiple fields
+
+<informaltable frame="all">
+<tgroup cols="2">
+<tbody>
+
+<row> <entry><literal>
+Tool tip
+</literal></entry>
+<entry><para>
+The text which is displayed when the mouse hovers over this object for 3 seconds.
+Ideally, you should extend this to contain information about the purpose of the
+child graph.
+</para></entry></row>
+
+<row> <entry><literal>new graph file (Python code)</literal></entry>
+<entry><para>
+Specifies the path and directory to the new graph file. The default path is the
+directory of the currently running Python executable.
+</para></entry></row>
+
+<row> <entry><literal>Python variable to pass to the child</literal></entry>
+<entry><para>
+One Python variable (which may be a list) is past to the child graph. This
+(typically) would contain the id of &sofaswitch; worker
+nodes that are in existance which are available to do any desired task.
+</para></entry></row>
+
+</tbody>
+</tgroup>
+</informaltable>
+
+
+</para>
+</sect1>
+
+
+
+
+
+
+
+
+
+<sect1>
+<title>Make a call</title>
+<para>
+Consider the figure <xref linkend="makecallicon"/> which shows the icon
+and graph representation of the control structure used to cause a
+&sofaswitch; entity to initiate a TDM or voip call.
+<figure id="makecallicon">
+<title>Make call control element</title>
+<informaltable frame="none">
+<tgroup cols="2">
+<tbody>
+<row><entry><para>
+<mediaobject>
+<imageobject>
+<imagedata fileref="../html/makecall.png" align="center" scale="300" format="PNG"></imagedata>
+</imageobject>
+</mediaobject>
+</para></entry>
+<entry><para>
+<mediaobject>
+<imageobject>
+<imagedata fileref="../html/MakeCall.png" align="center" format="PNG"></imagedata>
+</imageobject>
+</mediaobject>
+</para></entry></row>
+<row><entry><para>icon </para></entry>
+ <entry><para>graph representation</para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+</figure>
+</para>
+
+<para>
+One possible call destination that was used during testing is the voip node
+itself. I setup multiple concurrent incoming and outgoing calls, simply by
+getting the voip node to make a call to "h323:127.0.0.1".
+</para>
+
+
+<para>
+The Make a call control object, on selecting the right mouse button, brings up a properties
+box that has multiple fields
+
+<informaltable frame="all">
+<tgroup cols="2">
+<tbody>
+
+<row> <entry><literal>
+Tool tip
+</literal></entry>
+<entry><para>
+The text which is displayed when the mouse hovers over this object for 3 seconds.
+Ideally, you should extend this to contain information about the destination of
+this call.
+</para></entry></row>
+
+<row> <entry><literal>
+Worker node to activate (Python code)
+</literal></entry>
+<entry><para>
+The worker node is a preexisting node on some external application that was
+created in response to a "Request Node" operation. Causing the node to make a
+call will mark the node as in use, and it will not be destroyed 2 seconds after creation.
+</para></entry></row>
+
+<row> <entry><literal>
+Call destination (Python code)
+</literal></entry>
+<entry><para>
+The call destination is somewhere capable of receiving a call. For a voip
+call, one possible destination is the H323 test site set up by Craig
+Southeren, which is given as "h323:h323.voxgratia.org"
+</para></entry></row>
+
+
+</tbody>
+</tgroup>
+</informaltable>
+</para>
+
+</sect1>
+
+
+
+
+
+
+
+
+<sect1>
+<title>Execute arbitrary Python command</title>
+<para>
+Consider the figure <xref linkend="Pythonicon"/> which shows the icon
+and graph representation of the control structure used to define and execute an
+arbitrary Python command.
+<figure id="Pythonicon">
+<title>Execute arbitrary Python code control element</title>
+<informaltable frame="none">
+<tgroup cols="2">
+<tbody>
+<row><entry><para>
+<mediaobject>
+<imageobject>
+<imagedata fileref="../html/Python.png" align="center" format="PNG"></imagedata>
+</imageobject>
+</mediaobject>
+</para></entry>
+<entry><para>
+<mediaobject>
+<imageobject>
+<imagedata fileref="../html/Python.png" align="center" format="PNG"></imagedata>
+</imageobject>
+</mediaobject>
+</para></entry></row>
+<row><entry><para>icon </para></entry>
+ <entry><para>graph representation</para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+</figure>
+</para>
+
+<para>
+The Python code that is executed is carried out within a
+<literal>try..except</literal> environment, so graph execution is not stopped if
+the code is faulty. Further, quote marks (<literal>"</literal>) are
+correctly managed, so a valid code statement would be
+<literal>print "Id of this instance is ", self.myId</literal>
+</para>
+
+<para>
+The arbitrary Python code control object, on selecting the right mouse button,
+brings up a properties box that has multiple fields which are described in the
+table below. This control object is ideal for debugging, and can contain Python
+print statements to report on values stored in variables or program status, or
+when events have been detected.
+<informaltable frame="all">
+<tgroup cols="2">
+<tbody>
+
+<row> <entry><literal>
+Tool tip
+</literal></entry>
+<entry><para>
+The text which is displayed when the mouse hovers over this object for 3 seconds.
+Ideally, you should extend this to contain a comment about the purpose of the
+Python code
+</para></entry></row>
+
+<row> <entry><literal>
+Python code
+</literal></entry>
+<entry><para>
+The arbitrary Python code which is to be executed. You have access to all the
+internal variables used in the execution of this graph. It is possible to
+simply put a print statement in there as a debugging technique. It is
+encouraged that you put short, quickly executed statements here, as all other
+actions are suspended while processing this item.
+</para></entry></row>
+
+
+</tbody>
+</tgroup>
+</informaltable>
+</para>
+
+<para>
+When the Python executable processes a graph file, the following variables are
+available for the user to access. Sometimes, it is helpful to include a print
+statement in development graphs to report on these variables. The user may
+modify these variables (at their own peril) to give interesting results. For
+example, one could modify <literal>self.data[a]</literal> to control which node
+in the graph is executed next.
+
+<informaltable frame="all">
+<tgroup cols="2">
+<tbody>
+
+<row> <entry><literal>self.data[a]</literal></entry>
+<entry><para>
+ The data structure describing this node on the graph.
+</para></entry></row>
+
+<row> <entry><literal>self.pendingEvents</literal></entry>
+<entry><para>
+Holds the name of timers waiting to expire.
+</para></entry></row>
+
+<row> <entry><literal>self.isMaster</literal></entry>
+<entry><para>
+Boolean flag, if this graph is generated directly from the command line.
+</para></entry></row>
+
+<row> <entry><literal>self.parentId</literal></entry>
+<entry><para>
+The id assigned to the parent graph by the server, or <literal>None</literal>
+(if this graph is generated directly from the command line).
+</para></entry></row>
+
+<row> <entry><literal>self.myId</literal></entry>
+<entry><para>
+The id assigned to this graph by the server.
+</para></entry></row>
+
+<row> <entry><literal>self.currentHandlers</literal></entry>
+<entry><para>
+List of registered handlers, which is populated by the Eventer control
+structure.
+</para></entry></row>
+
+<row> <entry><literal>self.generatedEvents</literal></entry>
+<entry><para>
+A list of events we have to examine at the next opportunity. This list will
+include expired timers and packets from the network.
+</para></entry></row>
+
+<row> <entry><literal>self.keepGoing</literal></entry>
+<entry><para>
+A flag to indicate that we should keep working along this graph. If set to
+<literal>false</literal> , it is equivalent to processing a Suspend Processing.
+</para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+</para>
+
+
+</sect1>
+
+
+
+
+
+<sect1>
+<title>Read from file</title>
+<para>
+Consider the figure <xref linkend="readfromfileicon"/> which shows the icon
+and graph representation of the control structure used to request an answering
+machine node to read audio from a S16_LE wav file. Audio read from the wav file
+is sent to the node designated by previous/subsequent transfer media commands.
+<figure id="readfromfileicon">
+<title>Read from file control element</title>
+<informaltable frame="none">
+<tgroup cols="2">
+<tbody>
+<row><entry><para>
+<mediaobject>
+<imageobject>
+<imagedata fileref="../html/readfromfile.png" align="center" format="PNG"></imagedata>
+</imageobject>
+</mediaobject>
+</para></entry>
+<entry><para>
+<mediaobject>
+<imageobject>
+<imagedata fileref="../html/playfromfile.png" align="center" format="PNG"></imagedata>
+</imageobject>
+</mediaobject>
+</para></entry></row>
+<row><entry><para>icon </para></entry>
+ <entry><para>graph representation</para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+</figure>
+</para>
+
+<para>
+You may switch an answering machine node to read from a different file at any time.
+Multiple answering machine nodes may read from the same file at the same time.
+</para>
+
+<para>
+Should you specify an invalid file to read from no audio will be sent by this
+worker node.
+</para>
+
+<para>
+You may specify the file to read from at any time after the creation of the
+answering machine worker node.
+</para>
+
+<para>
+As noted before, if a requested node from the &sofaswitch;
+entity answering machine is not used in the 2 second period after creation, it
+is silently destroyed. Issuing this command will stop the destruction, and mark
+the created node as being "in use"
+</para>
+
+<para>
+The eblank object, on selecting the right mouse button, brings up a properties
+box that has multiple fields
+
+<informaltable frame="all">
+<tgroup cols="2">
+<tbody>
+
+<row> <entry><literal>
+Tool tip
+</literal></entry>
+<entry><para>
+The text which is displayed when the mouse hovers over this object for 3 seconds.
+Ideally, you should extend this to contain
+</para></entry></row>
+
+<row> <entry><literal>
+</literal></entry>
+<entry><para>
+</para></entry></row>
+
+
+</tbody>
+</tgroup>
+</informaltable>
+
+
+</para>
+</sect1>
+
+
+
+
+
+
+
+<sect1>
+<title>Request node</title>
+<para>
+Consider the figure <xref linkend="requestnodeicon"/> which shows the icon
+and graph representation of the control structure used to request a worker node
+from a &sofaswitch; entity.
+<figure id="requestnodeicon">
+<title>Request node control element</title>
+<informaltable frame="none">
+<tgroup cols="2">
+<tbody>
+<row><entry><para>
+<mediaobject>
+<imageobject>
+<imagedata fileref="../html/RequestNode.png" align="center" scale="300" format="PNG"></imagedata>
+</imageobject>
+</mediaobject>
+</para></entry>
+<entry><para>
+<mediaobject>
+<imageobject>
+<imagedata fileref="../html/requestnode.png" align="center" format="PNG"></imagedata>
+</imageobject>
+</mediaobject>
+</para></entry></row>
+<row><entry><para>icon </para></entry>
+ <entry><para>graph representation</para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+</figure>
+</para>
+
+<para>
+Request Node is a key component of the SofaSwitch suite of applications. With
+this item, the controller asks the designated application to supply one worker
+node for use by this call graph. Alternatively, this is the mechanism by which
+this call graph gets remote entities who can handle media data.
+</para>
+
+<para>
+Once created, the requested worker has a lifetime of 2 seconds. This lifetime is
+set by the designated application. If the requested worker is not acknowledged
+after 2 seconds, it is silently destroyed by the designated application.
+</para>
+
+<para>
+On receiving advise the node has been created, and its identity, this call
+graph can advise the node to <literal>transfer media to itself</literal>. Once
+this command is made, the requested node is safe from death by timeout.
+</para>
+
+<para>
+In most cases, the controlling entity is required to request a node before
+using the node. This is certainly the case for the answering machine and
+conference server. However, when dealing with an incoming call (voip/tdm etc),
+the process is changed slightly. The remote &sofaswitch;
+entity is required to create a node to deal with the incoming call. The
+controller is then advised of the incoming call, and the id of the newly
+created node. From this point, the controller deals with the incoming call by
+communicating directly with the newly created node.
+</para>
+
+<para>
+The request node object, on selecting the right mouse button, brings up a
+properties box that has multiple fields
+
+<informaltable frame="all">
+<tgroup cols="2">
+<tbody>
+
+<row> <entry><literal>
+Tool tip
+</literal></entry>
+<entry><para>
+The text which is displayed when the mouse hovers over this object for 3 seconds.
+Ideally, you should extend this to contain the destination
+&sofaswitch; entity, timer duration, and or what this node
+is required for.
+</para></entry></row>
+
+<row> <entry><literal>
+Request node from (Python code)
+</literal></entry>
+<entry><para>
+Specifies the &sofaswitch; entity that will supply the worker node.
+</para></entry></row>
+
+<row> <entry><literal>
+Timer period (seconds)
+</literal></entry>
+<entry><para>
+This Python code specifies the maximum time we are prepared to wait for an
+answer to our requests. A float value of <literal>1.4</literal> indicates 1400
+milliseconds. If there is no response in the specified time period, we have an
+indication the remote node is "dead".
+</para></entry></row>
+
+<row> <entry><literal>
+Timer label
+</literal></entry>
+<entry><para>
+This label is used in the eventer structure, and "fires" when there has been no
+answer in the specified time period.
+</para></entry></row>
+
+<row> <entry><literal>
+Additional information (Python code)
+</literal></entry>
+<entry><para>
+The additional information field is used to provide details that some
+&sofaswitch; applications want. For example, the conference
+utility needs information on which room the requested node should be in.
+</para></entry></row>
+
+
+</tbody>
+</tgroup>
+</informaltable>
+
+
+</para>
+</sect1>
+
+
+
+
+
+<sect1>
+<title>Start for loop</title>
+<para>
+Consider the figure <xref linkend="StartForLoopIcon"/> which shows the icon
+and graph representation of the control structure used to begin a <literal>for
+loop</literal>.
+<figure id="StartForLoopIcon">
+<title>Start for loop control element</title>
+<informaltable frame="none">
+<tgroup cols="2">
+<tbody>
+<row><entry><para>
+<mediaobject>
+<imageobject>
+<imagedata fileref="../html/Controlsfor.png" align="center" scale="300" format="PNG"></imagedata>
+</imageobject>
+</mediaobject>
+</para></entry>
+<entry><para>
+<mediaobject>
+<imageobject>
+<imagedata fileref="../html/startfor.png" align="center" format="PNG"></imagedata>
+</imageobject>
+</mediaobject>
+</para></entry></row>
+<row><entry><para>icon </para></entry>
+ <entry><para>graph representation</para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+</figure>
+</para>
+
+
+<para>It is entirely up to the user what the initialisation, increment and
+completion code actually is. Consequently, one may create an infinite for
+loop with ease. Further, it is acceptable to have flow paths that break out of
+the for loop without completing all preset loops.</para>
+
+<para>
+It is worth nothing that the initialisation, increment, and termination
+condition are Python code that is not tested until this code is used to manage
+different &sofaswitch; entities. Thus, if you have
+supplied invalid Python code, an error message will be printed and operation
+will attempt to continue. The termination condtion will, in the case of an
+error, evaluate to TRUE, and execution will move past the end of the loop.
+</para>
+
+<para>
+The for loop control object, on selecting the right mouse button, brings up a properties
+box that has multiple fields
+<informaltable frame="all">
+<tgroup cols="2">
+<tbody>
+
+<row> <entry><literal>
+Tool tip
+</literal></entry>
+<entry><para>
+The text which is displayed when the mouse hovers over this object for 3 seconds.
+Ideally, you should extend this to contain information about the loop counter,
+intitialisation and termination.
+</para></entry></row>
+
+<row> <entry><literal>
+Initialise (Python code)
+</literal></entry>
+<entry><para>
+The Python code which initialises the loop variable. It is wise to create a
+variable that is stored in the class representing this graph, so the text
+<literal>self.</literal> is at the beginning of the variable name.
+</para></entry></row>
+
+<row> <entry><literal>
+Test for terminatin (Python code)
+</literal></entry>
+<entry><para>
+This test should evaluated to <literal>true</literal> or
+<literal>false</literal>. By making this test always resulting in
+<literal>true</literal> one has an infinite loop.
+</para></entry></row>
+
+<row> <entry><literal>
+Increment (Python code)
+</literal></entry>
+<entry><para>
+This code is designed to increment the Python variable. One may leave this
+field empty for special loop types. Thus, the loop could be set up to loop for
+a period of time, not number of iterations.
+</para></entry></row>
+
+</tbody>
+</tgroup>
+</informaltable>
+
+
+</para>
+</sect1>
+
+
+<sect1>
+<title>Start graph processing</title>
+<para>
+Consider the figure <xref linkend="graphprocessicon"/> which shows the icon
+and graph representation of the control structure used to initiate processing
+of this graph.
+<figure id="graphprocessicon">
+<title>Start graph processing control element</title>
+<informaltable frame="none">
+<tgroup cols="2">
+<tbody>
+<row><entry><para>
+<mediaobject>
+<imageobject>
+<imagedata fileref="../html/Controlsstart.png" align="right" scale="300" format="PNG"></imagedata>
+</imageobject>
+</mediaobject>
+</para></entry>
+<entry><para>
+<mediaobject>
+<imageobject>
+<imagedata fileref="../html/startflow.png" align="center" format="PNG"></imagedata>
+</imageobject>
+</mediaobject>
+</para></entry></row>
+<row><entry><para>icon </para></entry>
+ <entry><para>graph representation</para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+</figure>
+</para>
+
+
+<para>
+When this graph is processed, this item indicates that a new identity on the
+server will be created, for each control structure on this graph to communicate
+with. Thus, on instantiation, this graph will be identified as identity
+<literal>c290</literal> (say). Any messages sent via the server will be
+labelled as being sent by <literal>c290</literal>.
+</para>
+
+<para>
+It is mandatory that there is only one of these items on each graph. Placing
+more than Start of graph processing item on the drawing area is ambiguous -
+where would call processing start ?
+</para>
+
+
+
+<para>
+The initiate graph processing object, on selecting the right mouse button, brings up a properties
+box that has one fields
+<informaltable frame="all">
+<tgroup cols="2">
+<tbody>
+<row> <entry><literal>
+Tool tip
+</literal></entry>
+<entry><para>
+The text which is displayed when the mouse hovers over this object for 3 seconds.
+Ideally, you should extend this to contain text describing the purpose of this graph.
+</para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+</para>
+</sect1>
+
+
+
+
+
+<sect1>
+<title>Suspend graph processing</title>
+<para>
+Consider the figure <xref linkend="suspendprocessingicon"/> which shows the icon
+and graph representation of the control structure used to suspend the
+processing of the graph.
+<figure id="suspendprocessingicon">
+<title>Suspend graph processing control element</title>
+<informaltable frame="none">
+<tgroup cols="2">
+<tbody>
+<row><entry><para>
+<mediaobject>
+<imageobject>
+<imagedata fileref="../html/ControlsEndHere.png" align="center" format="PNG"></imagedata>
+</imageobject>
+</mediaobject>
+</para></entry>
+<entry><para>
+<mediaobject>
+<imageobject>
+<imagedata fileref="current/endflow.png" align="center" format="PNG"></imagedata>
+</imageobject>
+</mediaobject>
+</para></entry></row>
+<row><entry><para>icon </para></entry>
+ <entry><para>graph representation</para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+</figure>
+</para>
+
+<para>
+This control structure is provided as a means for temporarily holding up graph
+processing, while we wait for external events. If processing does fall into
+here, external events will move graph processing to an Event Collection item as
+required. Note that if graph processing was such that some events were never
+registered for, then execution will be permanently stuck in this control structure.
+</para>
+
+<para>
+When execution is in the Suspend graph processing control
+structure, waiting for an event to happen, there is no CPU penalty.
+</para>
+
+<para>
+The Suspend graph processing control structure, on selecting the right mouse button, brings up a properties
+box that has one field,
+
+<informaltable frame="all">
+<tgroup cols="2">
+<tbody>
+
+<row> <entry><literal>
+Tool tip
+</literal></entry>
+<entry><para>
+The text which is displayed when the mouse hovers over this object for 3 seconds.
+Ideally, you could extend this to contain the event being waited on.
+</para></entry></row>
+
+</tbody>
+</tgroup>
+</informaltable>
+
+
+</para>
+</sect1>
+
+
+
+
+
+
+
+<sect1>
+<title>Timer</title>
+<para>
+Consider the figure <xref linkend="timericon"/>, which contains the toolbar icon
+and graph represeentation of the control structure used to create a timer.
+<figure id="timericon">
+<title>Timer control element</title>
+<informaltable frame="none">
+<tgroup cols="2">
+<tbody>
+<row><entry><para>
+<mediaobject>
+<imageobject>
+<imagedata fileref="../html/miniclock.png" align="center" format="PNG"></imagedata>
+</imageobject>
+</mediaobject>
+</para></entry>
+<entry><para>
+<mediaobject>
+<imageobject>
+<imagedata fileref="../html/starttimer.png" align="center" format="PNG"></imagedata>
+</imageobject>
+</mediaobject>
+</para></entry></row>
+<row><entry><para>icon </para></entry>
+ <entry><para>graph representation</para></entry></row></tbody>
+</tgroup>
+</informaltable>
+</figure>
+</para>
+
+<para>
+The timer object, on selecting the right mouse button, brings up a properties
+box that has multiple fields
+
+<informaltable frame="all">
+<tgroup cols="2">
+<tbody>
+
+<row> <entry><literal>
+Tool Tip
+</literal></entry>
+<entry><para>
+The text which is displayed when the mouse hovers over this object for 3 seconds.
+Ideally, you should extend this to describe the purpose of this timer, or duration.
+</para></entry></row>
+<row> <entry><literal>
+Timer period (seconds, Python code)
+</literal></entry>
+<entry><para>
+The time period is specified in units of seconds. You may use a floating point
+number here with an exponent, or a Python variable. Thus, one would specify a
+delay of 1200 milliseconds as <literal>1.2</literal>.
+</para></entry></row>
+<row> <entry><literal>
+timer label (Python code)
+</literal></entry>
+<entry><para>
+This text is used to determine which timer has fired that is on this graph. The
+eventer control structure should be told to match on this string (or a
+substring), when waiting for an event.
+</para></entry></row>
+<row><entry><para>icon </para></entry>
+ <entry><para>graph representation</para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+</para>
+
+<para>
+Timer events which are
+generated when processing a different graph are never passed to this
+graph. Consequently, if you have multiple instances of this graph in operation,
+the same label (to identify the timer) can be used.
+</para>
+
+<para>
+As before, note that expired timers are not detected until the flow of
+execution has been suspended, or paused.
+</para>
+
+</sect1>
+
+
+
+
+
+
+
+
+
+<sect1>
+<title>Transfer of audio between two &sofaswitch; entities</title>
+<para>
+Consider the figure <xref linkend="transfermediaicon"/>, which shows the icon
+and graph representation of the control structure used to enable the flow of audio between
+two &sofaswitch; entities.
+<figure id="transfermediaicon">
+<title>Transfer audio control element</title>
+<informaltable frame="none">
+<tgroup cols="2">
+<tbody>
+<row><entry><para>
+<mediaobject>
+<imageobject>
+<imagedata fileref="../html/transfermedia.png" align="right" format="PNG"></imagedata>
+</imageobject>
+</mediaobject>
+</para></entry>
+<entry><para>
+<mediaobject>
+<imageobject>
+<imagedata fileref="current/TransferMedia.png" align="left" format="PNG"></imagedata>
+</imageobject>
+</mediaobject>
+</para></entry></row>
+<row><entry><para>icon </para></entry>
+ <entry><para>graph representation</para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+</figure>
+</para>
+
+<para>
+One possible use is when we wish to record an incoming voip call. In this case,
+we will request and create a voip and an answering machine node. Then, issue this
+command to one of the two created nodes. It is not our responsibility to worry
+abount media format, or ports/addresses. It is our responsibility to issue the
+connect command.
+</para>
+
+<para>
+Alternatively, suppose we wish to connect one TDM (standard phone line) call
+to another TDM call. In this case, both TDM worker nodes happen to be on the
+same machine, via the same phone card. On reception of the Transfer Media
+command, the nodes will do a direct bridging of the audio between them.
+</para>
+
+<para>
+After requesting a node, it stays in existance for 2 seconds. If it is not used
+in that time, the worker node is silently deleted. One
+way of preventing that death is to do a Transfer Media command to that node
+just created. If the recipient node is not ready, one can do a transer media
+request to a non existant node. This will keep the requested node in existance,
+and the person at the other end will not hear an eacho.
+</para>
+
+<para>
+The transfer audio object, on selecting the right mouse button, brings up a properties
+box that has multiple fields
+<informaltable frame="all">
+<tgroup cols="2">
+<tbody>
+
+<row> <entry><literal>
+Tool Tip
+</literal></entry>
+<entry><para>
+The text which is displayed when the mouse hovers over this object for 3 seconds.
+Ideally, you should extend this to contain a description of the two nodes that
+will be connected
+</para></entry></row>
+
+<row> <entry><literal>
+First SofaSwitch worker(Python)
+</literal></entry>
+<entry><para>
+This text is evaluated as Python code, and specifies one of the two entities
+which is to connect audio.
+</para></entry></row>
+
+<row> <entry><literal>
+Second SofaSwitch worker(Python)
+</literal></entry>
+<entry><para>
+This text is evaluated as Python code, and specifies the second of the two entities
+which is to connect audio.
+</para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+</para>
+</sect1>
+
+
+
+
+
+<sect1>
+<title>Write to file</title>
+<para>
+Consider the figure <xref linkend="writetofileicon"/>, which shows the icon
+and graph representation of the control structure used to cause the answering
+machine to write incoming audio to a file.
+<figure id="writetofileicon">
+<title>Write to file control element</title>
+<informaltable frame="none">
+<tgroup cols="2">
+<tbody>
+<row><entry><para>
+<mediaobject>
+<imageobject>
+<imagedata fileref="../html/writetofile.png" align="center" format="PNG"></imagedata>
+</imageobject>
+</mediaobject>
+</para></entry>
+<entry><para>
+<mediaobject>
+<imageobject>
+<imagedata fileref="current/recordtofile.png" align="center" format="PNG"></imagedata>
+</imageobject>
+</mediaobject>
+</para></entry></row>
+<row><entry><para>icon </para></entry>
+ <entry><para>graph representation</para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+</figure>
+</para>
+
+<para>
+This control structure causes the designated answering machine node to write
+audio to the wave file (format S16_LE).
+</para>
+
+<para>
+You may switch an answering machine node to write to a different file at any
+time. On switching files, the answering machine node will close the current
+file and attempt to use the new file. It is valid to set the file name to the
+same value. In this case, the old recorded data is lost, and audio is written
+to the beginning of the current file.
+</para>
+
+<para>
+Should you specify an invalid file to write to, no audio will be written.
+</para>
+
+
+<para>
+The write to file control object, on selecting the right mouse button, brings up a properties
+box that has multiple fields
+
+<informaltable frame="all">
+<tgroup cols="2">
+<tbody>
+
+<row> <entry><literal>
+Tool Tip
+</literal></entry>
+<entry><para>
+The text which is displayed when the mouse hovers over this object for 3 seconds.
+Ideally, you should extend this to contain information about the destination
+file, or other meaningful details.
+</para></entry></row>
+
+<row> <entry><literal>
+Filename to contain new audio (Python code)
+</literal></entry>
+<entry><para>
+This Python code specifies the filename and directory of the file to write
+audio to. The directory path specification is relative to the directory in
+which the answering machine entity was run from.
+</para></entry></row>
+
+<row> <entry><literal>
+Answering machine node (Python code)
+</literal></entry>
+<entry><para>
+This Python code describes the id of the answering machine worker node that we
+control. The answering machine node would have been created by a "Request node" command.
+</para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+</para>
+</sect1>
+
+
+</chapter>
1
0
Author: derek
Date: Fri Jun 8 00:04:07 2007
New Revision: 271
Added:
sofaswitch/trunk/callflow/docs/callflow.xml
Log:
Add this file - the header file for the Docbook docs.
Added: sofaswitch/trunk/callflow/docs/callflow.xml
==============================================================================
--- (empty file)
+++ sofaswitch/trunk/callflow/docs/callflow.xml Fri Jun 8 00:04:07 2007
@@ -0,0 +1,57 @@
+<?xml version="1.0"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [
+
+<!ENTITY callflow "<emphasis>CallFlow</emphasis>">
+<!ENTITY sofaswitch "<emphasis>SofaSwitch</emphasis>">
+
+
+<!ENTITY chap1 SYSTEM "chap1.sgml">
+<!ENTITY chap2 SYSTEM "chap2.sgml">
+<!ENTITY chap3 SYSTEM "chap3.sgml">
+<!ENTITY app1 SYSTEM "app1.sgml">
+
+
+
+]>
+<book>
+ <bookinfo>
+ <date>2007 - June</date>
+ <title>&callflow; - GUI for designing call handling in &sofaswitch;</title>
+ <subtitle>GUI design of call handling</subtitle>
+ <authorgroup>
+ <author>
+ <firstname>Derek</firstname>
+ <surname>Smithies</surname>
+ <affiliation>
+ <orgname>IndraNet Technoligies Ltd
+ </orgname>
+ </affiliation>
+
+ </author></authorgroup>
+ <address>
+ <email>derek(a)indranet.co.nz</email>
+ </address>
+ <revhistory>
+ <revision>
+ <revnumber>0.1</revnumber>
+ <date>2007 May 31</date>
+ <authorinitials>djs</authorinitials>
+ <revremark>
+ Initial release
+ </revremark>
+ </revision>
+ </revhistory>
+ </bookinfo>
+
+&chap1;
+
+&chap2;
+
+&chap3;
+
+
+&app1;
+</book>
+
+
1
0
Author: derek
Date: Fri Jun 8 00:00:21 2007
New Revision: 270
Added:
sofaswitch/trunk/callflow/docs/makedoc.xsl
Log:
Add this file, for creating the html documentation from the supplied
Docbook files.
Added: sofaswitch/trunk/callflow/docs/makedoc.xsl
==============================================================================
--- (empty file)
+++ sofaswitch/trunk/callflow/docs/makedoc.xsl Fri Jun 8 00:00:21 2007
@@ -0,0 +1,19 @@
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ version="1.0">
+ <xsl:import href="/usr/share/xml/docbook/stylesheet/nwalsh/1.69.1/htmlhelp/htmlhelp.xsl"/>
+ <xsl:param name="htmlhelp.use.hhk" select="1"/>
+ <xsl:param name="htmlhelp.button.next" select="1"/>
+ <xsl:param name="htmlhelp.button.previous" select="1"/>
+ <xsl:param name="htmlhelp.button.back" select="1"/>
+ <xsl:param name="htmlhelp.button.forward" select="1"/>
+ <xsl:param name="htmlhelp.hhc.show.root" select="1"/>
+ <xsl:param name="htmlhelp.show.favorites" select="1"/>
+ <xsl:param name="htmlhelp.show.advanced.search" select="1"/>
+ <xsl:param name="htmlhelp.show.menu" select="1"/>
+ <xsl:param name="htmlhelp.hhp" select="'callflow.hhp'"/>
+ <xsl:param name="htmlhelp.hhc" select="'callflow.hhc'"/>
+ <xsl:param name="htmlhelp.hhk" select="'callflow.hhk'"/>
+ <xsl:param name="htmlhelp.chm" select="'callflow.chm'"/>
+ <xsl:param name="use.id.as.filename" select="1"/>
+</xsl:stylesheet>
+
1
0
06 Jun '07
Author: derek
Date: Wed Jun 6 01:23:09 2007
New Revision: 269
Added:
sofaswitch/trunk/callflow/docs/amtest.png (contents, props changed)
Modified:
sofaswitch/trunk/callflow/src/callflow.cpp
sofaswitch/trunk/callflow/src/callstartstop.cpp
sofaswitch/trunk/callflow/src/dnd.cpp
sofaswitch/trunk/callflow/src/eventer.cpp
sofaswitch/trunk/callflow/src/loadnewgraph.cpp
sofaswitch/trunk/callflow/src/requestnode.cpp
sofaswitch/trunk/callflow/src/senddtmf.cpp
sofaswitch/trunk/callflow/src/shapelist.cpp
sofaswitch/trunk/callflow/src/transfermedia.cpp
sofaswitch/trunk/callflow/src/writetofile.cpp
sofaswitch/trunk/callflow/tests/child.src
sofaswitch/trunk/callflow/tests/loadgraph.src
Log:
tidy up fixes resulting from work on the docs.
Added: sofaswitch/trunk/callflow/docs/amtest.png
==============================================================================
Binary file. No diff available.
Modified: sofaswitch/trunk/callflow/src/callflow.cpp
==============================================================================
--- sofaswitch/trunk/callflow/src/callflow.cpp (original)
+++ sofaswitch/trunk/callflow/src/callflow.cpp Wed Jun 6 01:23:09 2007
@@ -325,7 +325,7 @@
toolBar->AddTool(wxH_CONTROLSDEATH, wxBitmap ( death ), wxT("End all processing in this flow chart"));
toolBar->AddTool(wxH_CONTROLSENDCALL, wxBitmap ( endcall ), wxT("End a call (send hangup)"));
toolBar->AddTool(wxH_CONTROLSSTARTHERE, wxBitmap ( Controlsstart ), wxT("Start processing"));
- toolBar->AddTool(wxH_CONTROLSENDHERE, wxBitmap ( ControlsEndHere ), wxT("End processing"));
+ toolBar->AddTool(wxH_CONTROLSENDHERE, wxBitmap ( ControlsEndHere ), wxT("Suspend processing"));
toolBar->AddTool(wxH_CONTROLSREQUESTNODE, wxBitmap (RequestNode ), wxT("Query Supervisor for worker node"));
toolBar->AddTool(wxH_CONTROLSSENDDTMF, wxBitmap (senddtmf), wxT("Send DTMF string to worker node"));
toolBar->AddTool(wxH_CONTROLSIF, wxBitmap ( ControlsIf_xpm ), wxT("Test a condition"));
@@ -336,7 +336,7 @@
toolBar->AddTool(wxH_CONTROLSMAKECALL, wxBitmap (makecall), wxT("Make a voip/TDM call to outside entity"));
toolBar->AddTool(wxH_CONTROLSFOR, wxBitmap ( Controlsfor_xpm ), wxT("Start a for loop"));
toolBar->AddTool(wxH_CONTROLSEND_FOR, wxBitmap ( Controlsend_for_xpm ), wxT("end a for loop"));
- toolBar->AddTool(wxH_CONTROLSPYTHON, wxBitmap ( Python_xpm ), wxT("arbitrary python code"));
+ toolBar->AddTool(wxH_CONTROLSPYTHON, wxBitmap ( Python_xpm ), wxT("arbitrary Python code"));
toolBar->AddTool(wxH_CONTROLSSENDMESSAGE, wxBitmap ( sendmessage_xpm ), wxT("send arbitrary sofa message"));
toolBar->AddTool(wxH_CONTROLSMASTERNODE, wxBitmap ( masternode_xpm ), wxT("collect events from remote sofa node"));
toolBar->AddTool(wxH_CONTROLSCONNECT_OBJECTS, wxBitmap ( JoinObjects ),
@@ -604,7 +604,7 @@
void MyFrame::OnCompile (wxCommandEvent & WXUNUSED(event))
{
- wxFileDialog filedlg(this, _T("Select a file to contain the python code"), _T(""), _T(""), _T("*.py"));
+ wxFileDialog filedlg(this, _T("Select a file to contain the Python code"), _T(""), _T(""), _T("*.py"));
if (filedlg.ShowModal() != wxID_OK)
return;
Modified: sofaswitch/trunk/callflow/src/callstartstop.cpp
==============================================================================
--- sofaswitch/trunk/callflow/src/callstartstop.cpp (original)
+++ sofaswitch/trunk/callflow/src/callstartstop.cpp Wed Jun 6 01:23:09 2007
@@ -29,15 +29,15 @@
switch(kindToMake) {
case AcceptCall:
displayData[displayData.size()] =
- InformationSection(wxT("Worker node to inform on call status (python code)"), wxT("\"voip1\""));
+ InformationSection(wxT("Worker node to inform on call status (Python code)"), wxT("\"voip1\""));
break;
case EndCall:
displayData[displayData.size()] =
- InformationSection(wxT("Worker node for termination (python code)"), wxT("\"voip1\""));
+ InformationSection(wxT("Worker node for termination (Python code)"), wxT("\"voip1\""));
break;
case MakeCall:
displayData[displayData.size()] =
- InformationSection(wxT("Worker node to activate (python code)"), wxT("\"voip1\""));
+ InformationSection(wxT("Worker node to activate (Python code)"), wxT("\"voip1\""));
break;
}
AdjustIoPoints();
@@ -64,20 +64,20 @@
file.AddLine(" try: ");
file.AddLine(" self.rhost = eval(self.data[a][\"worker node\"]) ");
file.AddLine(" except: ");
- file.AddLine(" print \"The worker node string \", self.data[a][\"worker node\"], \" could not be evaluated as a python string\" ");
+ file.AddLine(" print \"The worker node string \", self.data[a][\"worker node\"], \" could not be evaluated as a Python string\" ");
file.AddLine(" self.rhost = \"\" ");
if (kind == MakeCall) {
file.AddLine(" try: ");
file.AddLine(" self.dest = eval(self.data[a][\"call destination\"]) ");
file.AddLine(" except: ");
- file.AddLine(" print \"The destination string \", self.data[a][\"call destination\"], \" could not be evaluated as a python string\" ");
+ file.AddLine(" print \"The destination string \", self.data[a][\"call destination\"], \" could not be evaluated as a Python string\" ");
file.AddLine(" self.dest = None ");
}
if (kind == AcceptCall) {
file.AddLine(" try: ");
file.AddLine(" self.option = eval(self.data[a][\"answer option\"]) ");
file.AddLine(" except: ");
- file.AddLine(" print \"The answer call option string \", self.data[a][\"answer option\"], \" could not be evaluated as a python string\" ");
+ file.AddLine(" print \"The answer call option string \", self.data[a][\"answer option\"], \" could not be evaluated as a Python string\" ");
file.AddLine(" self.option = \"No\" ");
}
Modified: sofaswitch/trunk/callflow/src/dnd.cpp
==============================================================================
--- sofaswitch/trunk/callflow/src/dnd.cpp (original)
+++ sofaswitch/trunk/callflow/src/dnd.cpp Wed Jun 6 01:23:09 2007
@@ -475,13 +475,10 @@
DndShape * dndShape = NULL;
MyTokenizer bits(description, GetEndBlock());
-
if (bits.CountTokens() != 4) {
- printf("String does not have the right number of tokens - %d suppl\n",
- bits.CountTokens());
- printf("Break up \"%s\"\n", description.c_str());
return NULL;
}
+
long kind, xpos, ypos;
wxString ans = bits.GetNextToken();
Modified: sofaswitch/trunk/callflow/src/eventer.cpp
==============================================================================
--- sofaswitch/trunk/callflow/src/eventer.cpp (original)
+++ sofaswitch/trunk/callflow/src/eventer.cpp Wed Jun 6 01:23:09 2007
@@ -50,7 +50,7 @@
bool vblEmpty = displayData[3].data.IsEmpty();
if (vblEmpty)
- SetCompileError(wxT("There is no python variable to hold the output of the event"));
+ SetCompileError(wxT("There is no Python variable to hold the output of the event"));
bool oneEmpty = displayData[1].data.IsEmpty();
@@ -65,9 +65,9 @@
}
if (oneEmpty && twoEmpty)
- SetCompileError(wxT("Cannot specify both python code and a regular expression.\nEnter just one statement."));
+ SetCompileError(wxT("Cannot specify both Python code and a regular expression.\nEnter just one statement."));
else
- SetCompileError(wxT("You must enter one statement.\nEither python code, or a regular expression"));
+ SetCompileError(wxT("You must enter one statement.\nEither Python code, or a regular expression"));
return false;
}
Modified: sofaswitch/trunk/callflow/src/loadnewgraph.cpp
==============================================================================
--- sofaswitch/trunk/callflow/src/loadnewgraph.cpp (original)
+++ sofaswitch/trunk/callflow/src/loadnewgraph.cpp Wed Jun 6 01:23:09 2007
@@ -86,6 +86,7 @@
file.AddLine(" f.setGraph(self.fname) ");
file.AddLine(" f.setMaster(False) ");
file.AddLine(" f.setUserData(self.udata) ");
+ file.AddLine(" f.setScriptArgs(self.scriptArgs) ");
file.AddLine(" reactor.connectTCP(sofaServer, 5000, f) ");
file.AddLine(" return self.data[a][\"Output\"] ");
file.AddLine("");
Modified: sofaswitch/trunk/callflow/src/requestnode.cpp
==============================================================================
--- sofaswitch/trunk/callflow/src/requestnode.cpp (original)
+++ sofaswitch/trunk/callflow/src/requestnode.cpp Wed Jun 6 01:23:09 2007
@@ -84,7 +84,7 @@
file.AddLine(" try: ");
file.AddLine(" rhost = eval(rhost) + \":REQUESTNEWID \" ");
file.AddLine(" except: ");
- file.AddLine(" print \"Could not process \", self.data[a][\"Request node from\"], \" as a python string\" ");
+ file.AddLine(" print \"Could not process \", self.data[a][\"Request node from\"], \" as a Python string\" ");
file.AddLine(" return self.data[a][\"Output\"] ");
file.AddLine(" additional = self.data[a][\"Additional info\"] ");
file.AddLine(" if len(additional) > 0: ");
Modified: sofaswitch/trunk/callflow/src/senddtmf.cpp
==============================================================================
--- sofaswitch/trunk/callflow/src/senddtmf.cpp (original)
+++ sofaswitch/trunk/callflow/src/senddtmf.cpp Wed Jun 6 01:23:09 2007
@@ -27,10 +27,10 @@
relOutputPoints.Add(25, 50);
displayData[displayData.size()] =
- InformationSection(wxT("Worker node to activate (python code)"), wxT("\"voip1\""));
+ InformationSection(wxT("Worker node to activate (Python code)"), wxT("\"voip1\""));
displayData[displayData.size()] =
- InformationSection(wxT("DTMF to send to worker node (python code)"), wxT("\"1\""));
+ InformationSection(wxT("DTMF to send to worker node (Python code)"), wxT("\"1\""));
AdjustIoPoints();
}
Modified: sofaswitch/trunk/callflow/src/shapelist.cpp
==============================================================================
--- sofaswitch/trunk/callflow/src/shapelist.cpp (original)
+++ sofaswitch/trunk/callflow/src/shapelist.cpp Wed Jun 6 01:23:09 2007
@@ -310,7 +310,7 @@
file.AddLine(" help=\"location of the sofa switch message server\", ");
file.AddLine(" default=\"localhost\") ");
file.AddLine("parser.add_option(\"-o\", \"--opts\", dest=\"scriptArgs\", ");
- file.AddLine(" help=\"text passed to the running python code, as self.scriptArgs\",");
+ file.AddLine(" help=\"text passed to the running Python code, as self.scriptArgs\",");
file.AddLine(" default=\"\") ");
file.AddLine("(options, args) = parser.parse_args() ");
file.AddLine(" ");
@@ -350,7 +350,7 @@
file.AddLine(" self.isMaster = newIsMaster ");
file.AddLine(" ");
file.AddLine(" def setScriptArgs(self, newScriptArgs): ");
- file.AddLine(" \"\"\"Pass to the running python code the arguements that");
+ file.AddLine(" \"\"\"Pass to the running Python code the arguements that");
file.AddLine(" were on the command line. This is a feature that enables");
file.AddLine(" (for example) one command file to call different hosts.");
file.AddLine(" \"\"\" ");
Modified: sofaswitch/trunk/callflow/src/transfermedia.cpp
==============================================================================
--- sofaswitch/trunk/callflow/src/transfermedia.cpp (original)
+++ sofaswitch/trunk/callflow/src/transfermedia.cpp Wed Jun 6 01:23:09 2007
@@ -122,13 +122,13 @@
bool secondEmpty = displayData[2].data.IsEmpty();
if (firstEmpty)
- SetCompileError(wxT("You must supply a valid python expression as the name of the first SofaSwitch worker"));
+ SetCompileError(wxT("You must supply a valid Python expression as the name of the first SofaSwitch worker"));
if (secondEmpty)
- SetCompileError(wxT("You must supply a valid python expression as the name of the second SofaSwitch worker"));
+ SetCompileError(wxT("You must supply a valid Python expression as the name of the second SofaSwitch worker"));
if (firstEmpty && secondEmpty)
- SetCompileError(wxT("You must supply a valid python expression for the names of the two SofaSwitch workers"));
+ SetCompileError(wxT("You must supply a valid Python expression for the names of the two SofaSwitch workers"));
if (firstEmpty || secondEmpty)
return false;
Modified: sofaswitch/trunk/callflow/src/writetofile.cpp
==============================================================================
--- sofaswitch/trunk/callflow/src/writetofile.cpp (original)
+++ sofaswitch/trunk/callflow/src/writetofile.cpp Wed Jun 6 01:23:09 2007
@@ -28,7 +28,7 @@
displayData[displayData.size()] =
- InformationSection(wxT("answering machine node (Python code)"), wxT("Answering machine worker node"));
+ InformationSection(wxT("Answering machine node (Python code)"), wxT("self.amNode"));
relInputPoints.Add(25, 0);
relOutputPoints.Add(25, 50);
Modified: sofaswitch/trunk/callflow/tests/child.src
==============================================================================
--- sofaswitch/trunk/callflow/tests/child.src (original)
+++ sofaswitch/trunk/callflow/tests/child.src Wed Jun 6 01:23:09 2007
@@ -1 +1 @@
-20<B>531<B>142<B> extra <special>Tool Tip<ms>Death<ms><special> <B><Shape>1<B>518<B>50<B> extra <special>Tool Tip<ms>Start Processing<ms><special> <B><Shape>10<B>528<B>93<B> extra <special>Tool Tip<ms>Python<ms><special>Python Code<ms>print "CHILD says::: parent id is ", self.parentId, " user data is ", self.userData<ms><special> <B><Shape>
+1<B>518<B>50<B> extra <special>Tool Tip<ms>Start Processing<ms><special> <B><Shape>10<B>528<B>93<B> extra <special>Tool Tip<ms>Python<ms><special>Python Code<ms>print "CHILD says::: parent id is ", self.parentId, " user data is ", self.userData<ms><special> <B><Shape>20<B>531<B>142<B> extra <special>Tool Tip<ms>Death<ms><special> <B><Shape>
Modified: sofaswitch/trunk/callflow/tests/loadgraph.src
==============================================================================
--- sofaswitch/trunk/callflow/tests/loadgraph.src (original)
+++ sofaswitch/trunk/callflow/tests/loadgraph.src Wed Jun 6 01:23:09 2007
@@ -1 +1 @@
-10<B>387<B>114<B> extra <special>Tool Tip<ms>Python<ms><special>Python Code<ms>print "have generated the new graph"<ms><special> <B><Shape>9<B>442<B>241<B>442,241,499,241,537,241<special>Tool Tip<ms>Join blocks shape<ms><special> <B><Shape>12<B>378<B>172<B> extra <special>Tool Tip<ms>Timer<ms><special>Timer period (seconds)<ms>20<ms><special>Timer label (string literal)<ms>endloadgraph<ms><special> <B><Shape>14<B>392<B>219<B> extra <special>Tool Tip<ms>Eventer<ms><special>Event sought (Python code)<ms><ms><special>Event sought (Regular Exp)<ms>endloadgraph<ms><special>Python variable: source of the event<ms>self.eventSource<ms><special>Python variable: name of the event<ms>self.eventName<ms><special>Python variable: generated data<ms>self.eventData<ms><special> <B><Shape>1<B>379<B>35<B> extra <special>Tool Tip<ms>Start Processing<ms><special> <B><Shape>10<B>388<B>258<B> extra <special>Tool Tip<ms>Python<ms><special>Python Code<ms>print "end the master now"<ms><special> <B><Shape>20<B>391<B>305<B> extra <special>Tool Tip<ms>Death<ms><special> <B><Shape>18<B>378<B>79<B> extra <special>Tool Tip<ms>Load New Graph<ms><special>new graph file (Python code)<ms>"am_test.graph"<ms><special> <B><Shape>2<B>509<B>241<B> extra <special>Tool Tip<ms>End Processing<ms><special> <B><Shape>
+14<B>393<B>334<B> extra <special>Tool Tip<ms>Eventer<ms><special>Event sought (Python code)<ms><ms><special>Event sought (Regular Exp)<ms>thistimer<ms><special>Python variable: source of the event<ms>self.eventSource<ms><special>Python variable: name of the event<ms>self.eventName<ms><special>Python variable: generated data<ms>self.eventData<ms><special> <B><Shape>9<B>322<B>107<B>374,107,322,107,322,260,372,263<special>Tool Tip<ms>Join blocks shape<ms><special> <B><Shape>2<B>510<B>356<B> extra <special>Tool Tip<ms>End Processing<ms><special> <B><Shape>4<B>372<B>238<B> extra <special>Tool Tip<ms>End For Loop<ms><special> <B><Shape>12<B>381<B>280<B> extra <special>Tool Tip<ms>Timer<ms><special>Timer period (seconds, Python code)<ms>2<ms><special>Timer label (Python code)<ms>"thistimer"<ms><special> <B><Shape>18<B>381<B>127<B> extra <special>Tool Tip<ms>Load New Graph<ms><special>new graph file (Python code)<ms>"child.graph"<ms><special>Python variable to pass to child<ms>self.data[a]<ms><special> <B><Shape>10<B>390<B>181<B> extra <special>Tool Tip<ms>Python<ms><special>Python Code<ms>print "have generated the new graph"<ms><special> <B><Shape>10<B>389<B>373<B> extra <special>Tool Tip<ms>Python<ms><special>Python Code<ms>print "end the master now"<ms><special> <B><Shape>3<B>374<B>82<B> extra <special>Tool Tip<ms>Start For - to make lots of graphs<ms><special>Initialise (Python code)<ms>self.i = 0<ms><special>Test for Termination (Python code)<ms>self.i < 10<ms><special>Increment (Python code)<ms>self.i+=1<ms><special> <B><Shape>20<B>392<B>420<B> extra <special>Tool Tip<ms>Death<ms><special> <B><Shape>1<B>379<B>35<B> extra <special>Tool Tip<ms>Start Processing<ms><special> <B><Shape>9<B>443<B>356<B>443,356,500,356,538,356<special>Tool Tip<ms>Join blocks shape<ms><special> <B><Shape>
1
0
Author: derek
Date: Wed Jun 6 01:22:01 2007
New Revision: 268
Added:
sofaswitch/trunk/callflow/docs/description.sgml
Log:
Add a docbook description of what goes on. This will make
integration into the help of CallFlow possible.
Added: sofaswitch/trunk/callflow/docs/description.sgml
==============================================================================
--- (empty file)
+++ sofaswitch/trunk/callflow/docs/description.sgml Wed Jun 6 01:22:01 2007
@@ -0,0 +1,1830 @@
+<!doctype book PUBLIC "-//Davenport//DTD DocBook V3.0//EN" []>
+<book>
+ <bookinfo>
+ <date>2007 - June</date>
+ <title>Callflow - GUI for designing call handling in SofaSwitch</title>
+ <subtitle>GUI design of call handling</subtitle>
+ <authorgroup>
+ <author>
+ <firstname>Derek</firstname>
+ <surname>Smithies</surname>
+ <affiliation>
+ <orgname>IndraNet Technoligies Ltd
+ </orgname>
+ </affiliation>
+
+ </author></authorgroup>
+ <address>
+ <email>derek(a)indranet.co.nz</email>
+ </address>
+ <revhistory>
+ <revision>
+ <revnumber>0.1</revnumber>
+ <date>2007 May 31</date>
+ <authorinitials>djs</authorinitials>
+ <revremark>
+ Initial release
+ </revremark>
+ </revision>
+ </revhistory>
+ </bookinfo>
+<toc></toc>
+<chapter>
+<title>Introduction</title>
+<para><emphasis>CallFlow</emphasis> is a utility which has been designed to enable the user to control
+the various entities in the <emphasis>SofaSwitch</emphasis> system. This utility allows the
+user to graphically design call setup, connection, and teardown. This utility
+takes the graphical layout and generates Python code, which implements the
+desired operation. </para>
+
+<para>Python is areasonably tidy language, cross platform, straightforward syntax and does not
+have the dependency hell of perl. Sadly, nothing is easy, and it takes
+considerable effort to write Python scripts to control SofaSwitch utilities. A
+graphical approach is preferable.
+</para>
+
+<para>In this section of this manual, we describe
+<emphasis>CallFlow</emphasis>, how it works, what it does, and how to get the
+most result for the minimum of effort. We note that the user will be exposed
+to some Python. These blocks of Python code are regular expressions and label
+defination. Consequently, it is straightforward, and quite manageable for the
+novice. </para>
+
+<para>The following sections describe how <emphasis>SofaSwitch</emphasis>
+works with CallFlow by means of several examples.
+</para>
+
+<sect1> <title>Overview of operation</title>
+<para>Various items are selected from the tool bar, and placed on the screen. These are connected
+together. Once the flow diagram is completed, it is compiled by selection of
+the compile button. Two files are generated.
+<itemizedlist>
+ <listitem><para>a graph file, which describes the items
+ on the screen, their internal settings ,and how they are connected. </para></listitem>
+ <listitem><para>a python file, which contains python documentation and python code to run
+ any graph file, and one line which invokes the reading of the generated
+ graph file.</para></listitem>
+</itemizedlist>
+</para>
+
+<para>
+The python executable is, in fact, able to process any graph file. This happens
+as the python executable contains all the methods for all known types of
+items. Indeed, if you compile two different graphs on the screen, the only
+difference in the generated python code is the specified graph
+file. Consequently, it is possible for the one python executable to load
+multiple graph files and do multiple concurrent calls.
+</para>
+
+<para>Prior to execution of the python file, it is expected the server is
+running. The compiled Python script will contain instructions (as set by the
+user) to request nodes at the different <emphasis>SofaSwitch</emphasis>
+entities. Should there be no reply (the entity is not running) there will be
+a timeout, and the user's code will need to respond accordingly. This Python
+script can be executed in a console, and the user can monitor the messages
+that flow to/from the server to see how things are progressing. Once the
+script has been tested with 1 call, multiple calls can be handled by multiple
+instances of the script.</para>
+
+<para>Each python file invokes the handling of variables for all items on the screen
+within one "Controller" class. Should a separate graph be required to
+simultaneously, it will be run within a second instance of the "Controller"
+class. Thus, all graphs are kept totally separate. Should the user wish to
+communicate between different executing graphs, thread safe structures such as
+databases should be used.
+</para>
+
+<para>
+For safety, variables required should be limited to the scope of the class that
+this graph is running. Consequently, if there are multiple instances of this
+graph being used, there will be no variable collision. It is therefore
+suggested that all variables have the string <literal>self</literal> before
+them. Consequently, you would refer to the variable <literal>i</literal> as
+<literal>self.i</literal>
+</para>
+
+<para>One difficulty with Python is the inability to handle threads well. They
+are available, but are very heavyweight in terms of system load, but provide
+limited gain. To illustrate, a multi threaded python application will run at
+the same speed on a multiprocessor box as on a single cpu box. Worse, each new
+thread running in Python is a whole new running interpreter, which consumes
+system resources. This posed a problem - if the controller is going to handle
+lots of concurrent calls, it would be poor practice to place each controller
+handled call into a separate Python thread. </para>
+
+<para> We therefore base this code around
+<ulink URL="http://twistedmatrix.com/trac"></ulink> an event driven network
+framework written in Python. Using Twisted solved the handling of the any
+number of asynchronous events.. Further, we could have one psuedo thread per
+call, but in reality there is one thread in operation. One psuedo thread per
+call makes things much simpler to analyse. </para>
+
+<para>The Python code will process the items on the graph, until it reaches
+the end of the current graph. Execution then waits for a event to happen,
+which move the current point of execution back to the relevant event handler.
+Thus, a call flow graph in this system will only have one start point, but may
+have many termination points.
+</para>
+</sect1>
+</chapter>
+
+<chapter>
+<title> Example flow graphs for <emphasis>CallFlow</emphasis></title>
+<para>
+We provide in this chapter multiple examples of the usage of
+<emphasis>CallFlow</emphasis>. These have been designed to give the reader an
+idea of the different components available, and how they link together. A full
+scale PBX will combine these elements together.
+</para>
+
+<para>
+One should remember that each graph is designed to handle one call. Events are
+posted to each graph, that are relevant to each call. Multiple calls can be
+handled simultaneously by spawning off graphs with the aid of the
+<literal>Load New Graph</literal> widget. Thus, on receiving notification of an
+incoming call, one would spawn of a <literal>Load New Graph</literal>, which is
+designed to handle that particular incoming call.
+</para>
+
+<sect1>
+<title>Hello World example</title>
+<para>
+Perhaps the simplest example of a graph you can create is the standard "Hello
+World" example, shown here, in figure <xref linkend="helloworldexample"/.
+<figure id="helloworldexample">
+<title>The obligatory Hello World example</title>
+<graphic fileref="helloworld.png" align="center"></graphic>
+</figure>
+An example of a simple call flow graph. The properties of the Python object in the middle have been adjusted to contain
+ code to print text to the console. On execution, a text message is sent to the console.
+</para>
+
+<para>
+Python will start executing at the very top box, process the code in the
+middle, and then terminate at the bottom. The operation of the three boxes (top to bottom) is
+<itemizedlist>
+ <listitem><para>On loading of this graph, execution will start at this box. It is an error to
+ have two such flow generation boxes on the page.</para></listitem>
+ <listitem><para>Execute the python code, which has been defined by
+ the user, in the properties of this instance of the Python code
+ box.</para></listitem>
+ <listitem><para>The skull and crossbones symbol indicates ther
+termination of this thread of execution, and then disconnect from the
+server. All future events are ignored. Other threads of execution on other
+pages are not influenced.
+ </para></listitem> </itemizedlist> </para>
+
+<para>Program flow is invariably top to
+bottom. Arrows are drawn on the output and input of each box to indicate where
+the flow is going. You will notice four black circles, filled, on this
+graph. They indicate a connection between the different entities.
+</para>
+</sect1>
+
+<sect1>
+<title>For Loops</title>
+<para>
+The flow of execution is to follow the graph on the screen and behaves likes a
+for loop in the pogramming language "C". Thus, start at the beginning,
+initialise the loop variable, evaluate the termination clause and goto the
+body of the for loop or the end block (if the termination clause is false). On
+completion of the body of the for loop, return back to the start. Execute the
+increment operation and then evaluate the termination condition. If the
+termination condition is false, execute the body of the for loop. The
+initialisation, increment operator, and termination condition, consist of
+Python code that is set in the preferences at the beginning of the for loop
+(right mouse button on the for loop entity). A simple example of a for loop is
+shown in figure <xref linkend="forloopexample"/.
+<figure id="forloopexample">
+<title>Example of a for loop</title>
+<graphic fileref="forloop.png" align="center"></graphic>
+</figure>
+</para>
+
+<para> While processing each of the nodes in the supplied graph, it is
+ignoring all timer events. Execution continues until it falls of the end of
+the graph, or passes through an Eventer type structure and goes nowhere. Once
+execution has gone nowhere, the system will process pending events.
+</para>
+
+
+
+</sect1>
+
+
+<sect1>
+<title>Event handling</title>
+<para>
+We describe the handling of events in this section, with a simple example.
+Consider the figure <xref linkend="simpleeventexample"/.
+<figure id="simpleeventexample">
+<title>Example of event handling</title>
+<graphic fileref="simpleevent.png" align="center"></graphic>
+</figure>
+</para>
+
+<para>
+Execution starts at the top, moves to the next node which sends off a request
+to obtain a new worker node. Then, the eventer box is entered, where we
+register to receive any event that contains the word "NEW" (we are searching
+for all events advising of a new node). At which point, execution continues to
+the right, and goes into the lower "execute python code" box, which prints a
+message. Finally, execution moves into the bottom most box, and is suspended.
+</para>
+
+<para>
+At this point, we rely upon the twisted module in python to call methods
+indicating that things have happened (e.g. a timer, data received from network
+etc). On receipt of a message about a new node, execution is moved to the box
+on the star output of the eventer box. Thus, the left python code box is
+executed, which (in this case) reports the id of the voip node created.
+Execution then moves to the skull and cross bones and terminates.
+</para>
+
+
+<para>
+Of crucial importance is that the user should note that all events (such as network
+and timer) are only processed when execution has stopped. Thus, execution has
+to have moved to a suspend execution box. In the graphic above, execution is
+suspended when it moves to the right side of the graph and down. After the
+event has happened, execution moves to the skull and crossbones and this entire
+graph is terminated.
+</para>
+
+<para>
+The eventer object, on selecting the right mouse button, brings up a properties
+box that has multiple fields
+<informaltable frame="all">
+<tgroup cols="2">
+<tbody>
+<row> <entry>
+ <literal>Event Sought</literal></entry> <entry><para>The
+event this box waits for can be described as text or Python code, which is
+matched as a regular expression to each event. The user should specify the
+event in Python code or as text.</para></entry></row>
+<row>
+ <entry><literal>Python variable:source of the event</literal></entry>
+ <entry><para>The source of the event (node id or timer) is
+ recorded in the specified Python variable.</para></entry> </row>
+ <row>
+ <entry><literal>Python variable:name of the event</literal></entry>
+ <entry><para>The name of the event (such as <literal>RequestNode</literal>)
+ is stored in the specified Python variable</para></entry></row>
+ <row>
+ <entry><literal>Python variable:generated data</literal></entry>
+ <entry><para>This Python variable may not receive a value (and will be set
+to <literal>None</literal>), but sometimes will get a value, to be used in
+subsequent elements of this graph. One example is when the user requests a node
+from a remote <emphasis>SofaSwitch</emphasis> entity. The received node id will
+be stored in this variable. Alternatively, DTMF data received from a remote
+<emphasis>SofaSwitch</emphasis> entity will be stored in this
+variable.</para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+</para>
+</sect1>
+
+
+<sect1>
+<title>Trivial transfer audio</title>
+<para>
+Key to the operation of <emphasis>SofaSwitch</emphasis> is the ability to move
+audio from one entity to another. This audio passes directly betweeen
+entities, and does not go via the server. The <emphasis>SofaSwitch</emphasis>
+entities themselves worry about the transport of the data. The trivial example in
+figure <xref linkend="trivialtransferexample" / shows the transfer of audio from
+the sound entity back to the sound entity. Consequently, audio that is captured
+at the mic will be directed to the speaker. The sound entity has therefore been told to
+talk to itself.
+<figure id="trivialtransferexample">
+<title>Trivial example of the transfer of audio</title>
+<graphic fileref="trivialtransfer.png" align="center"></graphic>
+</figure>
+</para>
+
+<para>
+In this example, there is no request process for a "sound" entity. The code
+just assumes a "sound" entity is there, and writes directly to it. Should this
+assumption be wrong, and "sound" is not available, there will be no error. The
+message server will receive the transfer request, and silently drop it on the
+floor.
+</para>
+
+<para>
+There is no limit on the when the transfer media request is sent, or on how
+many are sent. Thus, as the call progresses, one can transfer media to an
+answering machine (to record audio/play a message), conference device or to an
+outgoing voip/tdm call. In this way, one can build a full IVR system by
+connecting the audio stream to different objects as required.
+</para>
+</sect1>
+
+
+<sect1>
+<title>Transfer audio, and timer example</title>
+<para>
+We describe the handling of events in this section, with a simple example.
+Consider the figure <xref linkend="amtestexample"/.
+<figure id="amtestexample">
+<title>Example of audio transfer between <emphasis>SofaSwitch</emphasis> nodes,
+and timers.</title>
+<graphic fileref="amtest.png" align="center"></graphic>
+</figure>
+</para>
+
+<para>
+This graph connects an answering machine node to the sound card node. The
+answering machine node, on creation, is asked to record audio from the sound
+card, and send audio to the sound card. When DTMF character is received from
+the sound card, or node termination event occurs, the test is ended. On test
+end, the sound card is asked to direct audio to itself, and a timer is started.
+</para>
+
+<para>
+ The timer is a mechanism to stop the immediate handling of items on this
+graph, and all outstanding messages are sent, and events are handled. Thus, the
+message to the sound entity is actually sent. On the timer completing, death
+happens and this graph is closed down.
+</para>
+</sect1>
+</chapter>
+
+<chapter>
+<title>Description of each control box in <emphasis>CallFlow</emphasis></title>
+<para>
+Each of the available control structures in the <emphasis>CallFlow</emphasis>
+program is described in this section. In particular, the different parameters
+available are explained. Posible applications for each control box are given,
+to aid the user in deciding which one to use.
+</para>
+
+<para>
+All of the control structures in this application have optional parameters.
+Usually, these are strings, with no quotes required, and this is the case for
+parameters such as tool tips. Sometimes, the parameters are labelled as being
+python code. In this case, you can specifiy a python variable, so a possible
+value could be <literal>self.amNode</literal>. Alternatively, you can specify
+a string, which is indicated by placing double quotes at either end. Which
+makes <literal>"voip"</literal> an example of valid string Python code.
+</para>
+
+
+
+
+<sect1>
+<title>Conditional execution</title>
+<para>
+Consider the figure <xref linkend="conditionalicon"/ which shows the icon
+and graph representation of the control structure used to direct the flow of
+execution, given the outcome of a Python statement.
+<figure id="conditionalicon">
+<title></title>
+<informaltable frame="none">
+<tgroup cols="2">
+<tbody>
+<row><entry><para>
+<graphic fileref=".png" align="center" scale="300"></graphic>
+</para></entry>
+<entry><para>
+<graphic fileref=".png" align="center"></graphic>
+</para></entry></row>
+<row><entry><para>tool bar icon</para></entry>
+ <entry><para>graph representation</para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+</figure>
+</para>
+
+<para>
+This control structure will execute the user supplied Python code, and direct
+the flow of execution to the right (true result) or bottom (false result).
+</para>
+
+<para>
+ It is valid to connect the output of this control structure to another
+structure, even though the destination structure is already connected
+elsewhere. In this case, the flow of execution is not amiguous.
+</para>
+
+<para>
+The code that is evaluated (to determine which way to go) is not evaluated
+until the compiled graph is executed. Should the condition test generate an
+exception when it is evaluated, a message will be printed and the flow of
+execution moves to the false direction.
+</para>
+
+
+<para>
+The Conditional control structure, on selecting the right mouse button, brings up a properties
+box that has multiple fields
+
+<informaltable frame="all">
+<tgroup cols="2">
+<tbody>
+
+<row> <entry><literal>
+Tool tip
+</literal></entry>
+<entry><para>
+The text which is displayed when the mouse hovers over this object for 3 seconds.
+Ideally, you should extend this to contain a description of the test to be completed.
+</para></entry></row>
+
+<row> <entry><literal> Test (Python code)
+</literal></entry>
+The Python code that generates a <literal>true</literal> or
+<literal>false</literal> value is entered here. The code has access to all the
+variables defined previously while processing the current graph.
+<entry><para>
+</para></entry></row>
+
+
+</tbody>
+</tgroup>
+</informaltable>
+
+
+</para>
+</sect1>
+
+
+
+
+
+
+<sect1>
+<title>Death - terminate processing of this graph</title>
+<para>
+Consider the figure <xref linkend="deathicon"/ which shows the icon
+and graph representation of the control structure used to immediately terminate
+all processing of this graph.
+<figure id="deathicon">
+<title></title>
+<informaltable frame="none">
+<tgroup cols="2">
+<tbody>
+<row><entry><para>
+<graphic fileref="../bitmaps/death.png" align="center" scale="300"></graphic>
+</para></entry>
+<entry><para>
+<graphic fileref="../html/Death.png" align="center"></graphic>
+</para></entry></row>
+<row><entry><para>tool bar icon</para></entry>
+ <entry><para>graph representation</para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+</figure>
+</para>
+
+<para>
+On evaluation of the compiled code, execution of all elements in this graph
+is terminated. All current or pending events are ignored. All outstanding
+timers are ignored. Messages which have been defined to be sent out (such as
+termination of a remote node) are dropped.
+</para>
+
+<para>
+If the graph which executes the death control structrue is the one launched
+from the command line, it is applied to all graphs. However, if this is a child
+graph (launched from a "load new graph" control structure), then death only
+applies the child graph. Consequently, the parent graph can receive incoming
+calls, and send all incoming calls to multiple child graphs. Each child graph
+may execute the death control structure, and not influence the other calls.
+</para>
+
+<para>
+The outcome of executing this control structure is very simple - it will remove
+the id associated with this graph (<literal>self.myId</literal>) from the
+server.
+</para>
+
+<para>
+The death control structure, on selecting the right mouse button, brings up a properties
+box that has one field
+<informaltable frame="all">
+<tgroup cols="2">
+<tbody>
+
+<row> <entry><literal>
+Tool tip
+</literal></entry>
+<entry><para>
+The text which is displayed when the mouse hovers over this object for 3 seconds.
+Ideally, you should extend this to contain some meaningful comment about the
+circumstances around the shutdown, or perhaps leave this field blank.
+</para></entry></row>
+
+
+</tbody>
+</tgroup>
+</informaltable>
+
+
+</para>
+</sect1>
+
+
+
+
+
+<sect1>
+<title>End a call</title>
+<para>
+Consider the figure <xref linkend="endcallicon"/ which shows the icon
+and graph representation of the control structure used to end a call, or
+terminate a <emphasis>SofaSwitch</emphasis> node. Thus, you could use this
+control structure to terminate a voip call or close down an answering machine
+worker node.
+<figure id="endcallicon">
+<title></title>
+<informaltable frame="none">
+<tgroup cols="2">
+<tbody>
+<row><entry><para>
+<graphic fileref="../html/endcall.png" align="center"></graphic>
+</para></entry>
+<entry><para>
+<graphic fileref="../html/EndCall.png" align="center"></graphic>
+</para></entry></row>
+<row><entry><para>tool bar icon</para></entry>
+ <entry><para>graph representation</para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+</figure>
+</para>
+
+<para>
+This control structure causes the remote worker node to die. Thus, one would
+hangup the call, and then create a new worker node to make a new call. There
+is no intention of allowing a voip node (say) to make multiple consequetive
+calls. The code is build around "One node, one call".
+</para>
+
+<para>
+Created nodes from the answering machine, and conference room will, once they
+have passed the intial "use in 2 seconds timeout", endeavour to live
+forever. There is no automatic means of destroying these nodes. On graph
+closedown, these nodes are not deleted - some other graph might have taken
+control of the nodes. To remove these created nodes, one has to use this
+control structure.
+</para>
+
+<para>
+The end call control structure, on selecting the right mouse button, brings up a properties
+box that has multiple fields
+
+<informaltable frame="all">
+<tgroup cols="2">
+<tbody>
+
+<row> <entry><literal>
+Tool tip
+</literal></entry>
+<entry><para>
+The text which is displayed when the mouse hovers over this object for 3 seconds.
+Ideally, you should extend this to contain information about the worker node to
+be closed down.
+</para></entry></row>
+
+<row> <entry><literal>Worker node for termination (Python code)
+</literal></entry>
+<entry><para>
+This field describes the identity of the remote node that is to be
+terminated. If the value could not be evaluated, there will be a
+warning message on running the generated python code. If the supplied value
+does not match any node in existance, nothing will happen - the message server
+will silenty drop the termination message.
+</para></entry></row>
+
+
+</tbody>
+</tgroup>
+</informaltable>
+
+
+</para>
+</sect1>
+
+
+
+
+
+
+
+
+<sect1>
+<title>Event collection and registration</title>
+<para>
+Consider the figure <xref linkend="eventicon"/ which shows the icon
+and graph representation of the control structure used to collect events, and register
+for events.
+<figure id="eventicon">
+<title></title>
+<informaltable frame="none">
+<tgroup cols="2">
+<tbody>
+<row><entry><para>
+<graphic fileref="../html/eventer.png" align="center" scale="300"></graphic>
+</para></entry>
+<entry><para>
+<graphic fileref="../html/Eventer.png" align="center"></graphic>
+</para></entry></row>
+<row><entry><para>tool bar icon</para></entry>
+ <entry><para>graph representation</para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+</figure>
+</para>
+
+<para>
+This control structure is central to the processing of each graph. With this
+item, we have made it possible for the system to respond to network and timer
+events. Further, this structure provides a general means of registering to
+receive an event. Multiple event control structrures can be on a graph, where
+each structure waits for a different event.
+</para>
+
+<para>
+In our implementation, events are collected in the background, and then
+processed after execution has fallen into a "Suspend Processing" box, which is
+described below.
+</para>
+
+<para>
+The Event control structure has two outputs:
+<itemizedlist>
+ <listitem><para>On the right, which is where execution goes after registering for an
+ event.</para></listitem>
+ <listitem><para>On the bottom, which is where execution returns to after detecting the
+ event. This output is labelled with a star on the graph page.</para></listitem>
+</itemizedlist>
+</para>
+
+
+
+<para>
+The Event control structure, on selecting the right mouse button, brings up a properties
+box that has multiple fields
+<informaltable frame="all">
+<tgroup cols="2">
+<tbody>
+
+<row> <entry><literal>
+Tool tip
+</literal></entry>
+<entry><para>
+The text which is displayed when the mouse hovers over this object for 3 seconds.
+Ideally, you should extend this to contain a description of the event sought.
+</para></entry></row>
+
+<row> <entry><literal>Event sought (Python code)</literal></entry>
+<entry><para>
+Either this, or the next element on this table, should be filled in. The code
+is evaluated, which should produce a string. This string is treated as a
+regular expresssion, and compared with the available events.
+</para></entry></row>
+
+<row> <entry><literal>Event sought(Regular Exp)</literal></entry>
+<entry><para>
+This string is treated as a
+regular expresssion, and compared with the available events. Thus, the string
+<literal>DTMF</literal> will match all strings containing these letters, from
+all nodes in this graph.
+</para></entry></row>
+
+<row> <entry><literal>Python variable: source of the event</literal></entry>
+<entry><para>
+Describes the identity of the <emphasis>SofaSwitch</emphasis> node that
+generated the event. In the case of a Timer event, it will be set to <literal>None</literal>.
+</para></entry></row>
+
+<row> <entry><literal>Python variable: name of the event</literal></entry>
+<entry><para>
+This Python variable describes the name of the event that has occurrd
+</para></entry></row>
+
+<row> <entry><literal>Python variable: generated data
+</literal></entry>
+<entry><para>
+Contains any associated data with the event. So, for <literal>DTMF</literal> it
+will contain the detected stream of characters. For an incoming voip call, it
+will contain the identity of the remote person who made the call.
+</para></entry></row>
+
+
+</tbody>
+</tgroup>
+</informaltable>
+</para>
+
+<para>
+ When this structure is first entered, to register to receive an event, all of
+the python variables listed in the above table are initialised to
+<literal>None</literal>.
+</para>
+</sect1>
+
+
+
+
+
+
+
+
+
+<sect1>
+<title>Join items</title>
+<para>
+Consider the figure <xref linkend="joinlinesicon"/ which shows the icon
+representation of the control structure used to
+<figure id="joinlinesicon">
+<title></title>
+<informaltable frame="none">
+<tgroup cols="1">
+<tbody>
+<row><entry><para>
+<graphic fileref="../html/joinlines.png" align="center"></graphic>
+</para></entry> </row>
+<row><entry><para>tool bar icon</para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+</figure>
+</para>
+
+<para>
+Items on the drawing screen may be joined directly - one to another, or joined
+with this structure, which is multiline segment object. Select the toolbar
+icon, move to the drawing area, and left click to mark the points on the shape
+and complete with the right mouse button. Once completed, you may move the
+shape by selecting it with the left button or shift left to select multiple
+objects.
+</para>
+
+<para>
+When there is a valid connection at both ends of this object, a filled black
+circle is drawn at each end. Attempting to connect the outputs of two control
+structures together is not valid, and no filled black circles will be drawn.
+</para>
+
+<para>
+It is entirely valid to have the output of several items connected to one
+item. There is no ambiguity over where the flow of execution should
+go. However, connecting the output of one control item to multiple other
+control items is incorrect, as the correct direction for execution is not
+determinable.
+</para>
+
+
+
+<para>
+The join items object, on selecting the right mouse button, brings up a properties
+box that has one fields
+<informaltable frame="all">
+<tgroup cols="2">
+<tbody>
+
+<row> <entry><literal>
+Tool tip
+</literal></entry>
+<entry><para>
+The text which is displayed when the mouse hovers over this object for 3 seconds.
+Ideally, you should extend this to contain comment about the logic
+flow. Alternatively, you could clear this field to minimise the amount of
+displayed text to the screen.
+</para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+
+
+</para>
+</sect1>
+
+
+
+
+
+
+
+
+
+
+<sect1>
+<title>Load new graph</title>
+<para>
+Consider the figure <xref linkend="loadnewgraphicon"/ which shows the icon
+and graph representation of the control structure used to load a new graph file
+into the currently running Python executable.
+<figure id="loadnewgraphicon">
+<title></title>
+<informaltable frame="none">
+<tgroup cols="2">
+<tbody>
+<row><entry><para>
+<graphic fileref="../html/newgraph.png" align="center"></graphic>
+</para></entry>
+<entry><para>
+<graphic fileref="../html/loadnewgraph.png" align="center"></graphic>
+</para></entry></row>
+<row><entry><para>tool bar icon</para></entry>
+ <entry><para>graph representation</para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+</figure>
+</para>
+
+
+<para>
+This item provides the means to extend one graph so that it can launch child
+processes. It is similar to the C command <literal>system</literal>, except
+that control returns immediately to the parent process and does not wait for
+execution to finish in the child process.
+</para>
+
+<para>
+It is not similar to threads in C, as the child process does not have access to
+the memory of the parent process. Nor is it similar to
+<literal>fork()</literal> in C, as there is no duplication of the parent
+process.
+</para>
+
+<para>
+As a convenience, the child process always has a Python variable,
+<literal>self.parentId</literal> defined, which contains the id of the child
+process. The child may send a message (via the server) to the parent Id
+indicating status. The variable <literal>self.parentId</literal> is
+<literal>None</literal>, if there is no parent.
+</para>
+
+<para>
+The load new graph control object, on selecting the right mouse button, brings up a properties
+box that has multiple fields
+
+<informaltable frame="all">
+<tgroup cols="2">
+<tbody>
+
+<row> <entry><literal>
+Tool tip
+</literal></entry>
+<entry><para>
+The text which is displayed when the mouse hovers over this object for 3 seconds.
+Ideally, you should extend this to contain information about the purpose of the
+child graph.
+</para></entry></row>
+
+<row> <entry><literal>new graph file (Python code)</literal></entry>
+<entry><para>
+Specifies the path and directory to the new graph file. The default path is the
+directory of the currently running Python executable.
+</para></entry></row>
+
+<row> <entry><literal>Python variable to pass to the child</literal></entry>
+<entry><para>
+One Python variable (which may be a list) is past to the child graph. This
+(typically) would contain the id of <emphasis>SofaSwitch</emphasis> worker
+nodes that are in existance which are available to do any desired task.
+</para></entry></row>
+
+</tbody>
+</tgroup>
+</informaltable>
+
+
+</para>
+</sect1>
+
+
+
+
+
+
+
+
+
+<sect1>
+<title>Make a call</title>
+<para>
+Consider the figure <xref linkend="makecallicon"/ which shows the icon
+and graph representation of the control structure used to cause a
+<emphasis>SofaSwitch</emphasis> entity to initiate a TDM or voip call.
+<figure id="makecallicon">
+<title></title>
+<informaltable frame="none">
+<tgroup cols="2">
+<tbody>
+<row><entry><para>
+<graphic fileref="../html/makecall.png" align="center" scale="300"></graphic>
+</para></entry>
+<entry><para>
+<graphic fileref="../html/MakeCall.png" align="center"></graphic>
+</para></entry></row>
+<row><entry><para>tool bar icon</para></entry>
+ <entry><para>graph representation</para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+</figure>
+</para>
+
+<para>
+One possible call destination that was used during testing is the voip node
+itself. I setup multiple concurrent incoming and outgoing calls, simply by
+getting the voip node to make a call to "h323:127.0.0.1".
+</para>
+
+
+<para>
+The Make a call control object, on selecting the right mouse button, brings up a properties
+box that has multiple fields
+
+<informaltable frame="all">
+<tgroup cols="2">
+<tbody>
+
+<row> <entry><literal>
+Tool tip
+</literal></entry>
+<entry><para>
+The text which is displayed when the mouse hovers over this object for 3 seconds.
+Ideally, you should extend this to contain information about the destination of
+this call.
+</para></entry></row>
+
+<row> <entry><literal>
+Worker node to activate (python code)
+</literal></entry>
+<entry><para>
+The worker node is a preexisting node on some external application that was
+created in response to a "Request Node" operation. Causing the node to make a
+call will mark the node as in use, and it will not be destroyed 2 seconds after creation.
+</para></entry></row>
+
+<row> <entry><literal>
+Call destination (Python code)
+</literal></entry>
+<entry><para>
+The call destination is somewhere capable of receiving a call. For a voip
+call, one possible destination is the H323 test site set up by Craig
+Southeren, which is given as "h323:h323.voxgratia.org"
+</para></entry></row>
+
+
+</tbody>
+</tgroup>
+</informaltable>
+</para>
+
+</sect1>
+
+
+
+
+
+
+
+
+<sect1>
+<title>Execute arbitrary Python command</title>
+<para>
+Consider the figure <xref linkend="pythonicon"/ which shows the icon
+and graph representation of the control structure used to define and execute an
+arbitrary Python command.
+<figure id="pythonicon">
+<title></title>
+<informaltable frame="none">
+<tgroup cols="2">
+<tbody>
+<row><entry><para>
+<graphic fileref="../html/Python.png" align="center"></graphic>
+</para></entry>
+<entry><para>
+<graphic fileref="../html/python.png" align="center"></graphic>
+</para></entry></row>
+<row><entry><para>tool bar icon</para></entry>
+ <entry><para>graph representation</para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+</figure>
+</para>
+
+<para>
+The Python code that is executed is carried out within a
+<literal>try..except</literal> environment, so graph execution is not stopped if
+the code is faulty. Further, quote marks (<literal>"</literal>) are
+correctly managed, so a valid code statement would be
+<literal>print "Id of this instance is ", self.myId</literal>
+</para>
+
+<para>
+The arbitrary Python code control object, on selecting the right mouse button,
+brings up a properties box that has multiple fields which are described in the
+table below. This control object is ideal for debugging, and can contain Python
+print statements to report on values stored in variables or program status, or
+when events have been detected.
+<informaltable frame="all">
+<tgroup cols="2">
+<tbody>
+
+<row> <entry><literal>
+Tool tip
+</literal></entry>
+<entry><para>
+The text which is displayed when the mouse hovers over this object for 3 seconds.
+Ideally, you should extend this to contain a comment about the purpose of the
+Python code
+</para></entry></row>
+
+<row> <entry><literal>
+Python code
+</literal></entry>
+<entry><para>
+The arbitrary Python code which is to be executed. You have access to all the
+internal variables used in the execution of this graph. It is possible to
+simply put a print statement in there as a debugging technique. It is
+encouraged that you put short, quickly executed statements here, as all other
+actions are suspended while processing this item.
+</para></entry></row>
+
+
+</tbody>
+</tgroup>
+</informaltable>
+</para>
+
+<para>
+When the python executable processes a graph file, the following variables are
+available for the user to access. Sometimes, it is helpful to include a print
+statement in development graphs to report on these variables. The user may
+modify these variables (at their own peril) to give interesting results. For
+example, one could modify <literal>self.data[a]</literal> to control which node
+in the graph is executed next.
+
+<informaltable frame="all">
+<tgroup cols="2">
+<tbody>
+
+<row> <entry><literal>self.data[a]</literal></entry>
+<entry><para>
+ The data structure describing this node on the graph.
+</para></entry></row>
+
+<row> <entry><literal>self.pendingEvents</literal></entry>
+<entry><para>
+Holds the name of timers waiting to expire.
+</para></entry></row>
+
+<row> <entry><literal>self.isMaster</literal></entry>
+<entry><para>
+Boolean flag, if this graph is generated directly from the command line.
+</para></entry></row>
+
+<row> <entry><literal>self.parentId</literal></entry>
+<entry><para>
+The id assigned to the parent graph by the server, or <literal>None</literal>
+(if this graph is generated directly from the command line).
+</para></entry></row>
+
+<row> <entry><literal>self.myId</literal></entry>
+<entry><para>
+The id assigned to this graph by the server.
+</para></entry></row>
+
+<row> <entry><literal>self.currentHandlers</literal></entry>
+<entry><para>
+List of registered handlers, which is populated by the Eventer control
+structure.
+</para></entry></row>
+
+<row> <entry><literal>self.generatedEvents</literal></entry>
+<entry><para>
+A list of events we have to examine at the next opportunity. This list will
+include expired timers and packets from the network.
+</para></entry></row>
+
+<row> <entry><literal>self.keepGoing</literal></entry>
+<entry><para>
+A flag to indicate that we should keep working along this graph. If set to
+<literal>false</literal> , it is equivalent to processing a Suspend Processing.
+</para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+</para>
+
+
+</sect1>
+
+
+
+
+
+<sect1>
+<title>Read from file</title>
+<para>
+Consider the figure <xref linkend="readfromfileicon"/ which shows the icon
+and graph representation of the control structure used to request an answering
+machine node to read audio from a S16_LE wav file. Audio read from the wav file
+is sent to the node designated by previous/subsequent transfer media commands.
+<figure id="readfromfileicon">
+<title></title>
+<informaltable frame="none">
+<tgroup cols="2">
+<tbody>
+<row><entry><para>
+<graphic fileref="../html/readfromfile.png" align="center"></graphic>
+</para></entry>
+<entry><para>
+<graphic fileref="../html/playfromfile.png" align="center"></graphic>
+</para></entry></row>
+<row><entry><para>tool bar icon</para></entry>
+ <entry><para>graph representation</para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+</figure>
+</para>
+
+<para>
+You may switch an answering machine node to read from a different file at any time.
+Multiple answering machine nodes may read from the same file at the same time.
+</para>
+
+<para>
+Should you specify an invalid file to read from no audio will be sent by this
+worker node.
+</para>
+
+<para>
+You may specify the file to read from at any time after the creation of the
+answering machine worker node.
+</para>
+
+<para>
+As noted before, if a requested node from the <emphasis>SofaSwitch</emphasis>
+entity answering machine is not used in the 2 second period after creation, it
+is silently destroyed. Issuing this command will stop the destruction, and mark
+the created node as being "in use"
+</para>
+
+<para>
+The eblank object, on selecting the right mouse button, brings up a properties
+box that has multiple fields
+
+<informaltable frame="all">
+<tgroup cols="2">
+<tbody>
+
+<row> <entry><literal>
+Tool tip
+</literal></entry>
+<entry><para>
+The text which is displayed when the mouse hovers over this object for 3 seconds.
+Ideally, you should extend this to contain
+</para></entry></row>
+
+<row> <entry><literal>
+</literal></entry>
+<entry><para>
+</para></entry></row>
+
+
+</tbody>
+</tgroup>
+</informaltable>
+
+
+</para>
+</sect1>
+
+
+
+
+
+
+
+<sect1>
+<title>Request Node</title>
+<para>
+Consider the figure <xref linkend="requestnodeicon"/ which shows the icon
+and graph representation of the control structure used to request a worker node
+from a <emphasis>SofaSwitch</emphasis> entity.
+<figure id="requestnodeicon">
+<title></title>
+<informaltable frame="none">
+<tgroup cols="2">
+<tbody>
+<row><entry><para>
+<graphic fileref="../html/RequestNode.png" align="center" scale="300"></graphic>
+</para></entry>
+<entry><para>
+<graphic fileref="../html/requestnode.png" align="center"></graphic>
+</para></entry></row>
+<row><entry><para>tool bar icon</para></entry>
+ <entry><para>graph representation</para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+</figure>
+</para>
+
+<para>
+Request Node is a key component of the SofaSwitch suite of applications. With
+this item, the controller asks the designated application to supply one worker
+node for use by this call graph. Alternatively, this is the mechanism by which
+this call graph gets remote entities who can handle media data.
+</para>
+
+<para>
+Once created, the requested worker has a lifetime of 2 seconds. This lifetime is
+set by the designated application. If the requested worker is not acknowledged
+after 2 seconds, it is silently destroyed by the designated application.
+</para>
+
+<para>
+On receiving advise the node has been created, and its identity, this call
+graph can advise the node to <literal>transfer media to itself</literal>. Once
+this command is made, the requested node is safe from death by timeout.
+</para>
+
+<para>
+In most cases, the controlling entity is required to request a node before
+using the node. This is certainly the case for the answering machine and
+conference server. However, when dealing with an incoming call (voip/tdm etc),
+the process is changed slightly. The remote <emphasis>SofaSwitch</emphasis>
+entity is required to create a node to deal with the incoming call. The
+controller is then advised of the incoming call, and the id of the newly
+created node. From this point, the controller deals with the incoming call by
+communicating directly with the newly created node.
+</para>
+
+<para>
+The request node object, on selecting the right mouse button, brings up a
+properties box that has multiple fields
+
+<informaltable frame="all">
+<tgroup cols="2">
+<tbody>
+
+<row> <entry><literal>
+Tool tip
+</literal></entry>
+<entry><para>
+The text which is displayed when the mouse hovers over this object for 3 seconds.
+Ideally, you should extend this to contain the destination
+<emphasis>SofaSwitch</emphasis> entity, timer duration, and or what this node
+is required for.
+</para></entry></row>
+
+<row> <entry><literal>
+Request node from (Python code)
+</literal></entry>
+<entry><para>
+Specifies the <emphasis>SofaSwitch</emphasis> entity that will supply the worker node.
+</para></entry></row>
+
+<row> <entry><literal>
+Timer period (seconds)
+</literal></entry>
+<entry><para>
+This python code specifies the maximum time we are prepared to wait for an
+answer to our requests. A float value of <literal>1.4</literal> indicates 1400
+milliseconds. If there is no response in the specified time period, we have an
+indication the remote node is "dead".
+</para></entry></row>
+
+<row> <entry><literal>
+Timer label
+</literal></entry>
+<entry><para>
+This label is used in the eventer structure, and "fires" when there has been no
+answer in the specified time period.
+</para></entry></row>
+
+<row> <entry><literal>
+Additional information (Python code)
+</literal></entry>
+<entry><para>
+The additional information field is used to provide details that some
+<emphasis>SofaSwitch</emphasis> applications want. For example, the conference
+utility needs information on which room the requested node should be in.
+</para></entry></row>
+
+
+</tbody>
+</tgroup>
+</informaltable>
+
+
+</para>
+</sect1>
+
+
+
+
+
+<sect1>
+<title>Start for loop</title>
+<para>
+Consider the figure <xref linkend="StartForLoopIcon"/ which shows the icon
+and graph representation of the control structure used to begin a <literal>for
+loop</literal>.
+<figure id="StartForLoopIcon">
+<title></title>
+<informaltable frame="none">
+<tgroup cols="2">
+<tbody>
+<row><entry><para>
+<graphic fileref="../html/Controlsfor.png" align="center" scale="300"></graphic>
+</para></entry>
+<entry><para>
+<graphic fileref="../html/startfor.png" align="center"></graphic>
+</para></entry></row>
+<row><entry><para>tool bar icon</para></entry>
+ <entry><para>graph representation</para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+</figure>
+</para>
+
+
+<para>It is entirely up to the user what the initialisation, increment and
+completion code actually is. Consequently, one may create an infinite for
+loop with ease. Further, it is acceptable to have flow paths that break out of
+the for loop without completing all preset loops.</para>
+
+<para>
+It is worth nothing that the initialisation, increment, and termination
+condition are Python code that is not tested until this code is used to manage
+different <emphasis>SofaSwitch</emphasis> entities. Thus, if you have
+supplied invalid Python code, an error message will be printed and operation
+will attempt to continue. The termination condtion will, in the case of an
+error, evaluate to TRUE, and execution will move past the end of the loop.
+</para>
+
+<para>
+The for loop control object, on selecting the right mouse button, brings up a properties
+box that has multiple fields
+<informaltable frame="all">
+<tgroup cols="2">
+<tbody>
+
+<row> <entry><literal>
+Tool tip
+</literal></entry>
+<entry><para>
+The text which is displayed when the mouse hovers over this object for 3 seconds.
+Ideally, you should extend this to contain information about the loop counter,
+intitialisation and termination.
+</para></entry></row>
+
+<row> <entry><literal>
+Initialise (Python code)
+</literal></entry>
+<entry><para>
+The python code which initialises the loop variable. It is wise to create a
+variable that is stored in the class representing this graph, so the text
+<literal>self.</literal> is at the beginning of the variable name.
+</para></entry></row>
+
+<row> <entry><literal>
+Test for terminatin (Python code)
+</literal></entry>
+<entry><para>
+This test should evaluated to <literal>true</literal> or
+<literal>false</literal>. By making this test always resulting in
+<literal>true</literal> one has an infinite loop.
+</para></entry></row>
+
+<row> <entry><literal>
+Increment (Python code)
+</literal></entry>
+<entry><para>
+This code is designed to increment the python variable. One may leave this
+field empty for special loop types. Thus, the loop could be set up to loop for
+a period of time, not number of iterations.
+</para></entry></row>
+
+</tbody>
+</tgroup>
+</informaltable>
+
+
+</para>
+</sect1>
+
+
+<sect1>
+<title>Start graph processing</title>
+<para>
+Consider the figure <xref linkend="graphprocessicon"/ which shows the icon
+and graph representation of the control structure used to initiate processing
+of this graph.
+<figure id="graphprocessicon">
+<title></title>
+<informaltable frame="none">
+<tgroup cols="2">
+<tbody>
+<row><entry><para>
+<graphic fileref="../html/Controlsstart.png" align="right" scale="300"></graphic>
+</para></entry>
+<entry><para>
+<graphic fileref="../html/startflow.png" align="center" ></graphic>
+</para></entry></row>
+<row><entry><para>tool bar icon</para></entry>
+ <entry><para>graph representation</para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+</figure>
+</para>
+
+
+<para>
+When this graph is processed, this item indicates that a new identity on the
+server will be created, for each control structure on this graph to communicate
+with. Thus, on instantiation, this graph will be identified as identity
+<literal>c290</literal> (say). Any messages sent via the server will be
+labelled as being sent by <literal>c290</literal>.
+</para>
+
+<para>
+It is mandatory that there is only one of these items on each graph. Placing
+more than Start of graph processing item on the drawing area is ambiguous -
+where would call processing start ?
+</para>
+
+
+
+<para>
+The initiate graph processing object, on selecting the right mouse button, brings up a properties
+box that has one fields
+<informaltable frame="all">
+<tgroup cols="2">
+<tbody>
+<row> <entry><literal>
+Tool tip
+</literal></entry>
+<entry><para>
+The text which is displayed when the mouse hovers over this object for 3 seconds.
+Ideally, you should extend this to contain text describing the purpose of this graph.
+</para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+</para>
+</sect1>
+
+
+
+
+
+<sect1>
+<title>Suspend graph processing</title>
+<para>
+Consider the figure <xref linkend="suspendprocessingicon"/ which shows the icon
+and graph representation of the control structure used to suspend the
+processing of the graph.
+<figure id="suspendprocessingicon">
+<title></title>
+<informaltable frame="none">
+<tgroup cols="2">
+<tbody>
+<row><entry><para>
+<graphic fileref="../html/ControlsEndHere.png" align="center"></graphic>
+</para></entry>
+<entry><para>
+<graphic fileref="current/endflow.png" align="center"></graphic>
+</para></entry></row>
+<row><entry><para>tool bar icon</para></entry>
+ <entry><para>graph representation</para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+</figure>
+</para>
+
+<para>
+This control structure is provided as a means for temporarily holding up graph
+processing, while we wait for external events. If processing does fall into
+here, external events will move graph processing to an Event Collection item as
+required. Note that if graph processing was such that some events were never
+registered for, then execution will be permanently stuck in this control structure.
+</para>
+
+<para>
+When execution is in the Suspend graph processing control
+structure, waiting for an event to happen, there is no CPU penalty.
+</para>
+
+<para>
+The Suspend graph processing control structure, on selecting the right mouse button, brings up a properties
+box that has one field,
+
+<informaltable frame="all">
+<tgroup cols="2">
+<tbody>
+
+<row> <entry><literal>
+Tool tip
+</literal></entry>
+<entry><para>
+The text which is displayed when the mouse hovers over this object for 3 seconds.
+Ideally, you could extend this to contain the event being waited on.
+</para></entry></row>
+
+</tbody>
+</tgroup>
+</informaltable>
+
+
+</para>
+</sect1>
+
+
+
+
+
+
+
+<sect1>
+<title>Timer</title>
+<para>
+Consider the figure <xref linkend="timericon"/, which contains the toolbar icon
+and graph represeentation of the control structure used to create a timer.
+<figure id="timericon">
+<title></title>
+<informaltable frame="none">
+<tgroup cols="2">
+<tbody>
+<row><entry><para>
+<graphic fileref="../html/miniclock.png" align="center"></graphic>
+</para></entry>
+<entry><para>
+<graphic fileref="../html/starttimer.png" align="center"></graphic>
+</para></entry></row>
+<row><entry><para>tool bar icon</para></entry>
+ <entry><para>graph representation</para></entry></row></tbody>
+</tgroup>
+</informaltable>
+</figure>
+</para>
+
+<para>
+The timer object, on selecting the right mouse button, brings up a properties
+box that has multiple fields
+
+<informaltable frame="all">
+<tgroup cols="2">
+<tbody>
+
+<row> <entry><literal>
+Tool Tip
+</literal></entry>
+<entry><para>
+The text which is displayed when the mouse hovers over this object for 3 seconds.
+Ideally, you should extend this to describe the purpose of this timer, or duration.
+</para></entry></row>
+<row> <entry><literal>
+Timer period (seconds, Python code)
+</literal></entry>
+<entry><para>
+The time period is specified in units of seconds. You may use a floating point
+number here with an exponent, or a python variable. Thus, one would specify a
+delay of 1200 milliseconds as <literal>1.2</literal>.
+</para></entry></row>
+<row> <entry><literal>
+timer label (Python code)
+</literal></entry>
+<entry><para>
+This text is used to determine which timer has fired that is on this graph. The
+eventer control structure should be told to match on this string (or a
+substring), when waiting for an event.
+</para></entry></row>
+<row><entry><para>tool bar icon</para></entry>
+ <entry><para>graph representation</para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+</para>
+
+<para>
+Timer events which are
+generated when processing a different graph are never passed to this
+graph. Consequently, if you have multiple instances of this graph in operation,
+the same label (to identify the timer) can be used.
+</para>
+
+<para>
+As before, note that expired timers are not detected until the flow of
+execution has been suspended, or paused.
+</para>
+
+</sect1>
+
+
+
+
+
+
+
+
+
+<sect1>
+<title>Transfer of audio between two <emphasis>SofaSwitch</emphasis> entities</title>
+<para>
+Consider the figure <xref linkend="transfermediaicon"/, which shows the icon
+and graph representation of the control structure used to enable the flow of audio between
+two <emphasis>SofaSwitch</emphasis> entities.
+<figure id="transfermediaicon">
+<title></title>
+<informaltable frame="none">
+<tgroup cols="2">
+<tbody>
+<row><entry><para>
+<graphic fileref="../html/transfermedia.png" align="right"></graphic>
+</para></entry>
+<entry><para>
+<graphic fileref="current/TransferMedia.png" align="left"></graphic>
+</para></entry></row>
+<row><entry><para>tool bar icon</para></entry>
+ <entry><para>graph representation</para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+</figure>
+</para>
+
+<para>
+One possible use is when we wish to record an incoming voip call. In this case,
+we will request and create a voip and an answering machine node. Then, issue this
+command to one of the two created nodes. It is not our responsibility to worry
+abount media format, or ports/addresses. It is our responsibility to issue the
+connect command.
+</para>
+
+<para>
+Alternatively, suppose we wish to connect one TDM (standard phone line) call
+to another TDM call. In this case, both TDM worker nodes happen to be on the
+same machine, via the same phone card. On reception of the Transfer Media
+command, the nodes will do a direct bridging of the audio between them.
+</para>
+
+<para>
+After requesting a node, it stays in existance for 2 seconds. If it is not used
+in that time, the worker node is silently deleted. One
+way of preventing that death is to do a Transfer Media command to that node
+just created. If the recipient node is not ready, one can do a transer media
+request to a non existant node. This will keep the requested node in existance,
+and the person at the other end will not hear an eacho.
+</para>
+
+<para>
+The transfer audio object, on selecting the right mouse button, brings up a properties
+box that has multiple fields
+<informaltable frame="all">
+<tgroup cols="2">
+<tbody>
+
+<row> <entry><literal>
+Tool Tip
+</literal></entry>
+<entry><para>
+The text which is displayed when the mouse hovers over this object for 3 seconds.
+Ideally, you should extend this to contain a description of the two nodes that
+will be connected
+</para></entry></row>
+
+<row> <entry><literal>
+First SofaSwitch worker(python)
+</literal></entry>
+<entry><para>
+This text is evaluated as Python code, and specifies one of the two entities
+which is to connect audio.
+</para></entry></row>
+
+<row> <entry><literal>
+Second SofaSwitch worker(python)
+</literal></entry>
+<entry><para>
+This text is evaluated as Python code, and specifies the second of the two entities
+which is to connect audio.
+</para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+</para>
+</sect1>
+
+
+
+
+
+<sect1>
+<title>Write to file</title>
+<para>
+Consider the figure <xref linkend="writetofileicon"/, which shows the icon
+and graph representation of the control structure used to cause the answering
+machine to write incoming audio to a file.
+<figure id="writetofileicon">
+<title></title>
+<informaltable frame="none">
+<tgroup cols="2">
+<tbody>
+<row><entry><para>
+<graphic fileref="../html/writetofile.png" align="center"></graphic>
+</para></entry>
+<entry><para>
+<graphic fileref="current/recordtofile.png" align="center"></graphic>
+</para></entry></row>
+<row><entry><para>tool bar icon</para></entry>
+ <entry><para>graph representation</para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+</figure>
+</para>
+
+<para>
+This control structure causes the designated answering machine node to write
+audio to the wave file (format S16_LE).
+</para>
+
+<para>
+You may switch an answering machine node to write to a different file at any
+time. On switching files, the answering machine node will close the current
+file and attempt to use the new file. It is valid to set the file name to the
+same value. In this case, the old recorded data is lost, and audio is written
+to the beginning of the current file.
+</para>
+
+<para>
+Should you specify an invalid file to write to, no audio will be written.
+</para>
+
+
+<para>
+The write to file control object, on selecting the right mouse button, brings up a properties
+box that has multiple fields
+
+<informaltable frame="all">
+<tgroup cols="2">
+<tbody>
+
+<row> <entry><literal>
+Tool Tip
+</literal></entry>
+<entry><para>
+The text which is displayed when the mouse hovers over this object for 3 seconds.
+Ideally, you should extend this to contain information about the destination
+file, or other meaningful details.
+</para></entry></row>
+
+<row> <entry><literal>
+Filename to contain new audio (Python code)
+</literal></entry>
+<entry><para>
+This python code specifies the filename and directory of the file to write
+audio to. The directory path specification is relative to the directory in
+which the answering machine entity was run from.
+</para></entry></row>
+
+<row> <entry><literal>
+Answering machine node (Python code)
+</literal></entry>
+<entry><para>
+This python code describes the id of the answering machine worker node that we
+control. The answering machine node would have been created by a "Request node" command.
+</para></entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+</para>
+</sect1>
+
+
+
+
+
+
+
+
+
+
+
+
+
+</chapter>
+
+</book>
+
+
1
0
Author: derek
Date: Mon Jun 4 19:42:06 2007
New Revision: 267
Added:
sofaswitch/trunk/callflow/docs/exchildgraph.png (contents, props changed)
Modified:
sofaswitch/trunk/callflow/docs/exloadnewgraph.png
Log:
Modify the parent graph to be more exciting,
Add the child picture.
Added: sofaswitch/trunk/callflow/docs/exchildgraph.png
==============================================================================
Binary file. No diff available.
Modified: sofaswitch/trunk/callflow/docs/exloadnewgraph.png
==============================================================================
Binary files. No diff available.
1
0
Author: derek
Date: Fri Jun 1 01:14:12 2007
New Revision: 266
Added:
sofaswitch/trunk/callflow/docs/trivialtransfer.png (contents, props changed)
Log:
Add a digram to illustrate the tranfer of audio
from one SofaSwitch node to another. This is a trivial
example, because the audio is kept to one node. Thus, the
user of the sound card hears their words in the speaker port.
Added: sofaswitch/trunk/callflow/docs/trivialtransfer.png
==============================================================================
Binary file. No diff available.
1
0
Author: derek
Date: Fri Jun 1 01:12:17 2007
New Revision: 265
Added:
sofaswitch/trunk/callflow/tests/trivialtransfer.src
Log:
Add an example which illustrates the transfer of audio from
one SofaSwitch entity to another. This example is a bit silly,
in that we transfer audio to the same node. This means that the
sound card ends up talking to itself.
Added: sofaswitch/trunk/callflow/tests/trivialtransfer.src
==============================================================================
--- (empty file)
+++ sofaswitch/trunk/callflow/tests/trivialtransfer.src Fri Jun 1 01:12:17 2007
@@ -0,0 +1,3 @@
+1<B>192<B>98<B> extra <special>Tool Tip<ms>Start Processing<ms><special> <B><Shape>2<B>193<B>194<B> extra <special>Tool Tip<ms>End Processing<ms><special> <B><Shape>15<B>193<B>150<B> extra <special>Tool Tip<ms>Transfer Media from the
+sound node back to the sound
+node.<ms><special>First SofaSwitch worker (python)<ms>"sound"<ms><special>Second SofaSwitch worker (python)<ms>"sound"<ms><special> <B><Shape>
1
0
Author: derek
Date: Thu May 31 22:56:35 2007
New Revision: 264
Modified:
sofaswitch/trunk/callflow/tests/amtest.src
Log:
Modify the graph to be more correct.
Modified: sofaswitch/trunk/callflow/tests/amtest.src
==============================================================================
--- sofaswitch/trunk/callflow/tests/amtest.src (original)
+++ sofaswitch/trunk/callflow/tests/amtest.src Thu May 31 22:56:35 2007
@@ -1,3 +1,7 @@
-14<B>334<B>212<B> extra <special>Tool Tip<ms>wait for incoming DTMF<ms><special>Event sought (Python code)<ms><ms><special>Event sought (Regular Exp)<ms>DTMF<ms><special>Python variable: source of the event<ms>self.eventSource<ms><special>Python variable: name of the event<ms>self.eventName<ms><special>Python variable: generated data<ms>self.eventData<ms><special> <B><Shape>20<B>304<B>383<B> extra <special>Tool Tip<ms>Death<ms><special> <B><Shape>14<B>298<B>186<B> extra <special>Tool Tip<ms>Catch the timer, which when fired,
-indicates no am node was found<ms><special>Event sought (Python code)<ms><ms><special>Event sought (Regular Exp)<ms>requestam<ms><special>Python variable: source of the event<ms>self.eventSource<ms><special>Python variable: name of the event<ms>self.eventName<ms><special>Python variable: data associated<ms>self.nonodefound<ms><special> <B><Shape>16<B>190<B>401<B> extra <special>Tool Tip<ms>initial wav file<ms><special>Filename to read audio from (Python code)<ms>"../prompts/instructions.wav"<ms><special>answering machine node<ms>self.amNode<ms><special> <B><Shape>1<B>191<B>15<B> extra <special>Tool Tip<ms>Start Processing<ms><special> <B><Shape>9<B>311<B>236<B>311,236,318,294<special>Tool Tip<ms>Join blocks shape<ms><special> <B><Shape>15<B>190<B>310<B> extra <special>Tool Tip<ms>Transfer Media<ms><special>First SofaSwitch worker (python)<ms>self.amNode<ms><special>Second SofaSwitch worker (python)<ms>"sound"<ms><special> <B><Shape>2<B>190<B>446<B> extra <special>Tool Tip<ms>End Processing<ms><special> <B><Shape>9<B>318<B>262<B>347,262,318,294<special>Tool Tip<ms>Join blocks shape<ms><special> <B><Shape>11<B>190<B>110<B> extra <special>Tool Tip<ms>Request Node<ms><special>Request node from (Python code)<ms>"am"<ms><special>Timer period (seconds)<ms>1<ms><special>Timer label<ms>requestam<ms><special>Additional information (Python code)<ms><ms><special> <B><Shape>17<B>190<B>357<B> extra <special>Tool Tip<ms>Write To File<ms><special>Filename to contain new audio (Python code)<ms>"recorded_audio.wav"<ms><special>answering machine node<ms>self.amNode<ms><special> <B><Shape>10<B>198<B>248<B> extra <special>Tool Tip<ms>Python<ms><special>Python Code<ms>print "Have a new am node on ", self.amNode<ms><special> <B><Shape>13<B>190<B>210<B> extra <special>Tool Tip<ms>Stop Timer<ms><special>Timer to stop<ms>requestam<ms><special> <B><Shape>2<B>362<B>231<B> extra <special>Tool Tip<ms>End Processing<ms><special> <B><Shape>15<B>292<B>298<B> extra <special>Tool Tip<ms>Transfer Media<ms><special>First SofaSwitch worker (python)<ms>"sound"<ms><special>Second SofaSwitch worker (python)<ms>"sound"<ms><special> <B><Shape>9<B>248<B>182<B>248,183,308,182<special>Tool Tip<ms>Join blocks shape<ms><special> <B><Shape>21<B>199<B>67<B> extra <special>Tool Tip<ms>sound messages come here<ms><special>Message to send (Python code)<ms>"sound:reporttome"<ms><special> <B><Shape>14<B>201<B>161<B> extra <special>Tool Tip<ms>Wait for an event to indicate
-that the am node is created<ms><special>Event sought (Python code)<ms><ms><special>Event sought (Regular Exp)<ms>amREQ<ms><special>Python variable: source of the event<ms>self.eventSource<ms><special>Python variable: name of the event<ms>self.eventName<ms><special>Python variable: data associated<ms>self.amNode<ms><special> <B><Shape>21<B>301<B>339<B> extra <special>Tool Tip<ms>terminate the am node<ms><special>Message to send (Python code)<ms>self.amNode + ":hangup"<ms><special> <B><Shape>
+14<B>305<B>447<B> extra <special>Tool Tip<ms>Eventer<ms><special>Event sought (Python code)<ms><ms><special>Event sought (Regular Exp)<ms>"deathtimer"<ms><special>Python variable: source of the event<ms>self.eventSource<ms><special>Python variable: name of the event<ms>self.eventName<ms><special>Python variable: generated data<ms>self.eventData<ms><special> <B><Shape>2<B>362<B>231<B> extra <special>Tool Tip<ms>Stop processing, while we wait
+on events from the different entitties<ms><special> <B><Shape>9<B>248<B>182<B>248,183,308,182<special>Tool Tip<ms>Join blocks shape<ms><special> <B><Shape>17<B>190<B>357<B> extra <special>Tool Tip<ms>Write To File<ms><special>Filename to contain new audio (Python code)<ms>"recorded_audio.wav"<ms><special>answering machine node<ms>self.amNode<ms><special> <B><Shape>9<B>318<B>262<B>347,262,318,294<special>Tool Tip<ms>Join blocks shape<ms><special> <B><Shape>7<B>291<B>347<B> extra <special>Tool Tip<ms>End the Answering
+machine node.<ms><special>Worker node for termination (python code)<ms>self.amNode<ms><special> <B><Shape>9<B>311<B>236<B>311,236,318,294<special>Tool Tip<ms>Join blocks shape<ms><special> <B><Shape>15<B>292<B>298<B> extra <special>Tool Tip<ms>Make the sound node
+talk to itself, so the user hears echo.<ms><special>First SofaSwitch worker (python)<ms>"sound"<ms><special>Second SofaSwitch worker (python)<ms>"sound"<ms><special> <B><Shape>9<B>355<B>469<B>355,469,355,469,355,469,355,469,355,469,395,471<special>Tool Tip<ms>Join blocks shape<ms><special> <B><Shape>2<B>190<B>446<B> extra <special>Tool Tip<ms>End Processing<ms><special> <B><Shape>14<B>334<B>212<B> extra <special>Tool Tip<ms>wait for incoming DTMF from the sound node.
+On receiving DTMF, end everything<ms><special>Event sought (Python code)<ms><ms><special>Event sought (Regular Exp)<ms>DTMF<ms><special>Python variable: source of the event<ms>self.eventSource<ms><special>Python variable: name of the event<ms>self.eventName<ms><special>Python variable: generated data<ms>self.eventData<ms><special> <B><Shape>2<B>370<B>470<B> extra <special>Tool Tip<ms>End Processing<ms><special> <B><Shape>22<B>200<B>66<B> extra <special>Tool Tip<ms>Register for events from sound node<ms><special>Node to receive events from (Python code)<ms>"sound"<ms><special> <B><Shape>16<B>190<B>401<B> extra <special>Tool Tip<ms>initial wav file<ms><special>Filename to read audio from (Python code)<ms>"../prompts/instructions.wav"<ms><special>answering machine node<ms>self.amNode<ms><special> <B><Shape>14<B>298<B>186<B> extra <special>Tool Tip<ms>Catch the timer, which when fired,
+indicates no am node was found<ms><special>Event sought (Python code)<ms><ms><special>Event sought (Regular Exp)<ms>requestam<ms><special>Python variable: source of the event<ms>self.eventSource<ms><special>Python variable: name of the event<ms>self.eventName<ms><special>Python variable: data associated<ms>self.nonodefound<ms><special> <B><Shape>14<B>201<B>161<B> extra <special>Tool Tip<ms>Wait for an event to indicate
+that the am node is created<ms><special>Event sought (Python code)<ms><ms><special>Event sought (Regular Exp)<ms>amREQ<ms><special>Python variable: source of the event<ms>self.eventSource<ms><special>Python variable: name of the event<ms>self.eventName<ms><special>Python variable: data associated<ms>self.amNode<ms><special> <B><Shape>20<B>304<B>492<B> extra <special>Tool Tip<ms>Death<ms><special> <B><Shape>10<B>198<B>248<B> extra <special>Tool Tip<ms>Python<ms><special>Python Code<ms>print "Have a new am node on ", self.amNode<ms><special> <B><Shape>13<B>190<B>210<B> extra <special>Tool Tip<ms>Stop Timer<ms><special>Timer to stop<ms>requestam<ms><special> <B><Shape>11<B>190<B>110<B> extra <special>Tool Tip<ms>Request Node<ms><special>Request node from (Python code)<ms>"am"<ms><special>Timer period (seconds)<ms>1<ms><special>Timer label<ms>requestam<ms><special>Additional information (Python code)<ms><ms><special> <B><Shape>15<B>190<B>310<B> extra <special>Tool Tip<ms>Transfer Media<ms><special>First SofaSwitch worker (python)<ms>self.amNode<ms><special>Second SofaSwitch worker (python)<ms>"sound"<ms><special> <B><Shape>12<B>291<B>396<B> extra <special>Tool Tip<ms>Timer<ms><special>Timer period (seconds, Python code)<ms>1<ms><special>Timer label (Python code)<ms>"deathtimer"<ms><special> <B><Shape>1<B>191<B>15<B> extra <special>Tool Tip<ms>Start Processing<ms><special> <B><Shape>
1
0