<sect1>
<title>Programming</title>

<sect2>
<title>Introduction</title>

<para>
The Voicetronix cards are programmed via the VPB Application
Programmer Interface (VPBAPI, or just API). This is a set of C
callable functions.  The following sections describe the VPBAPI in
detail, and also include examples of the API functions in action.  It
is recommended that the user browse the header file vpbapi.h to gain
an overview of the API.
</para>
</sect2>

<sect2>
<title>Compiling with the VPBAPI</title> 

<sect3>
<title>Linux and FreeBSD</title>

<para>
Simply link <filename>libvpb.a</filename> with your application:
</para>

<literallayout><prompt>$ </prompt><userinput> gcc test.cpp -o test -Wall -g -lvpb -pthread -lm</userinput></literallayout>
</sect3>

<sect3>
<title>Windows</title>

<orderedlist>

<listitem>
<para>Create a new project (e.g. Win32 Console Application) and insert
your source files.</para>
</listitem>

<listitem>
<para>Project-Settings-C/C++:</para>
  <itemizedlist>
  <listitem><para>set "Category" to "Code Generation"</para></listitem>
  <listitem><para>set "Use run-time library:" to "Debug Multithreaded"</para>
  </listitem>
  </itemizedlist>
</listitem>

<listitem>
<para>Project-Settings-Link:</para>
  <itemizedlist>
  <listitem><para>To the "Object/library modules" add
  <filename>../debug/libvpb.lib</filename> (you might need to change
  the path to <filename>libvpb.lib</filename>, depending on where you
  create your project).</para></listitem>
  </itemizedlist>
</listitem>

<listitem>
<para>Build your project.</para>
</listitem>

<listitem>
<para>Make sure <filename>libvpb.dll</filename> and
<filename>plxapi.dll</filename> are in your path before running. One
way is to set the Project-Settings-Debug-Working Directory to a
directory containing the DLL, or place the DLL in a directory in your path
(e.g. <filename>c:\winnt\system32</filename>)</para>
</listitem>

<listitem>
<para>
Set the path for the firmware.  The firmware is called
<filename>vpbmain_pci.out</filename>, and is in
<filename>vpb-driver/firmware/</filename>.  There are two ways to set
the path:
</para>

  <itemizedlist>
  <listitem><para>Modify <filename>vpbreg.cpp</filename>, change the
  <filename>#define FIRMWARE_FILE_PCI</filename> to your
  path and recompile <filename>libvpb.dll</filename> (see
  <filename>Readme.Win32.txt</filename> for information on how to
  recompile the driver).</para>
  </listitem>

  <listitem><para>Set an environment variable
  <filename>VPB_FIRMWARE</filename> to the path to the firmware file.
  Under NT go to control panel-system-environment.  After setting the
  env. variable, you will need to restart MSVC before running so that
  the new env. variable is available to MSVC.</para>
  </listitem>
  </itemizedlist>
</listitem>

<listitem>
<para>You should now be able to run your program from MSVC.</para>
</listitem>
</orderedlist>

</sect3>
</sect2>
</sect1>

<sect1>
<title>Initialization and Shutdown</title>

<para>
This section describes the "housekeeping" functions used to initialize
and shutdown a Voicetronix card. The initialization function
<function><link linkend="vpb-open">vpb_open()</link></function> must be called before any other API
functions will work:
</para>

<example>
<title>Initialization and Shutdown</title>
<programlisting role="C">
void main() {
        handle = vpb_open(1, 2);
        vpb_close(handle);
}
</programlisting>
</example>

<para>
This program demonstrates initialization and shutdown of a single
channel, (number 2), on the first board in the system. Each channel
(or port) of the card has an associated number.  On the OpenLine4
card, channel 1 is the port furthest from the motherboard.  Port 4 is
closest to the motherboard.
</para>

<para>
The <function><link linkend="vpb-open">vpb_open()</link></function> function returns a
<firstterm>handle</firstterm> to the open channel. This handle then
provides a reference to all other operations with this channel.  A
call to <function><link linkend="vpb-open">vpb_open()</link></function> is required for each channel
that is to be used. If a channel is not opened, then no operations can
be performed with that channel.
</para>
</sect1>

<sect1>
<title>Error Handling</title>

<para>
Under certain conditions the API functions will be unable
to successfully execute. In this case an error condition will occur that
requires handling by code outside of the API. The API provides three modes
of error handling:
</para>

<itemizedlist>
<listitem><para>Exceptions</para></listitem>
<listitem><para>Error codes</para></listitem>
<listitem><para>Debug</para></listitem>
</itemizedlist>

<para>
The current error mode is set using the <function><link linkend="vpb-seterrormode">vpb_seterrormode()</link></function>
function. The default error mode is <function>Debug</function>.
</para>

<sect2>
    <title>Debug</title>
    <para>
    If an error occurs in this mode, the program stops execution
    immediately and prints an error message. This is useful during
    debugging as it brings any problems to the programmer's immediate
    attention. However, such behavior is obviously not desirable in
    release versions of the software.  Note that this mode is only
    suitable for console mode programs, it will cause the program to
    hang when used with a windows program.
    </para>
</sect2>

<sect2>
    <title>Error Codes</title>
    <para>
    In this case the function returns an integer corresponding to the
    nature of the error. The convention used by the API is that
    positive numbers and zero indicate successful function completion,
    and negative numbers represent an error condition. The error codes
    for the API functions are listed in <filename>vpberr.h</filename>.
    There are other, undocumented error codes that lower levels of the
    API software may return, but these are not defined in
    <filename>vpberr.h</filename>.  These errors should not occur
    during normal operation.  To convert an error code into a more
    helpful error string, use <function><link linkend="vpb-strerror">vpb_strerror()</link></function>.
    </para>
</sect2>

<sect2>
    <title>Exceptions</title>
    <para>
    Exceptions are a form of error handling supported by C++.  When an
    error occurs, an exception is "thrown". In the case of the VPBAPI
    , the exception is a class <function>VpbException</function> that contains
    information describing the error. The code member of the class
    corresponds to an error number defined exactly the same way as in
    the error code error handling method. The other members contain
    strings describing the API function that generated the error and a
    brief translation of the error code.  The user must provide code
    to catch the exception at some level in their program. The
    advantage of exceptions is that it is not necessary to trap errors
    at every API call, which can become tedious from a programming
    point of view, especially for API calls deep within nested
    function calls.  Consider the following code fragments, first
    using error codes:</para>

<example>
<title>Error Handling Using Error Codes</title>
<programlisting role="C">
vpb_seterrormode(VPB_ERROR_CODE);

// Attempt to open channel 1

if ((handle1 = vpb_open(1,1)) != VPB_OK) {
        printf("Error, code = %d\n",handle1);
        exit(0);
}

// Attempt to open channel 2

if ((handle2 = vpb_open(1,2)) != VPB_OK) {
        printf("Error, code = %d\n",handle2);
        exit(0);
}
</programlisting>
</example>

    <para>And now using exceptions:</para>

<example>
<title>Error Handling Using Exceptions</title>
<programlisting role="C">

try {
        vpb_seterrormode(VPB_EXCEPTION);
        handle1 = vpb_open(1,1);
        handle2 = vpb_open(1,2);
}

catch (VpbException v) {
        printf("Error, code = %d, s = %s, api func = %s\n", v.code, 
               v.s, v.api_function);
        exit(0);
}
</programlisting>
</example>

    <para>
    Using exceptions enables the programmer to send all run time
    errors to a single point in the code, removing the need for
    handling errors after every API call. If the current function does
    not have try/catch exception handling, then the compiler aborts
    the current function, climbing up the "call stack" until an
    exception handler is found in a calling function.  If no exception
    handler is found in the calling functions, the program aborts.
    For more information on exceptions, see a C++ text, or your C++
    compiler on-line documentation.
    </para>
</sect2>

</sect1>

