1216 lines
44 KiB
C++
1216 lines
44 KiB
C++
/* @file capisuitemodule.cpp
|
|
@brief Contains the Python module and integration routines
|
|
|
|
@author Gernot Hillier <gernot@hillier.de>
|
|
$Revision: 1.10 $
|
|
*/
|
|
|
|
/***************************************************************************
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#include <Python.h>
|
|
#include <string>
|
|
#include <unistd.h> // for sleep()
|
|
#include "../backend/connection.h"
|
|
#include "../modules/audiosend.h"
|
|
#include "../modules/audioreceive.h"
|
|
#include "../modules/faxreceive.h"
|
|
#include "../modules/faxsend.h"
|
|
#include "../modules/connectmodule.h"
|
|
#include "../modules/disconnectmodule.h"
|
|
#include "../modules/switch2faxG3.h"
|
|
#include "../modules/readDTMF.h"
|
|
#include "../modules/calloutgoing.h"
|
|
#include "capisuitemodule.h"
|
|
#include "capisuite.h"
|
|
|
|
#define TEMPORARY_FAILURE 0x34A9 // see ETS 300 102-1, Table 4.13 (cause information element)
|
|
|
|
extern CapiSuite* capisuiteInstance;
|
|
|
|
static PyObject* CallGoneError=NULL;
|
|
static PyObject* BackendError=NULL;
|
|
|
|
/** @defgroup python C/Python wrapper functions
|
|
@brief These functions define the python commands you can use in your scripts.
|
|
|
|
All CapiSuite-commands available in Python will stay in a python
|
|
module called capisuite. This module and all its functions are defined here.
|
|
|
|
There's a general scheme for mapping the names of the C wrapper functions
|
|
to python names:
|
|
|
|
Python command "capisuite.command()" will be defined in the wrapper function
|
|
"capisuite_command()".
|
|
|
|
So you can use this document as reference to all available CapiSuite Python
|
|
commands. For example, if you read the documentation for the
|
|
capisuite_audio_send function here, you can use it as capisuite.audio_send in
|
|
your Python scripts.
|
|
|
|
*/
|
|
|
|
void
|
|
capisuitemodule_destruct_connection(void* ptr)
|
|
{
|
|
Connection *conn=(static_cast<Connection*>(ptr));
|
|
conn->debugMessage("Python: deleting connection object",2);
|
|
if (conn->getState()!=Connection::DOWN) {
|
|
try {
|
|
conn->errorMessage("Warning: Connection still established in capisuitemodule_desctruct_conn(). Disconnecting.");
|
|
DisconnectModule active(conn,TEMPORARY_FAILURE,true);
|
|
active.mainLoop();
|
|
}
|
|
catch (CapiError e) {
|
|
conn->errorMessage("ERROR: disconnection also failed. Too bad...");
|
|
}
|
|
}
|
|
delete conn;
|
|
}
|
|
|
|
/** @brief Private converter function to extract the contained Connection* from a PyCObject
|
|
|
|
This function is defined for the use in PyArg_ParseTuple() calls.
|
|
|
|
@param conn_ref - PyCObject pointer
|
|
@param conn address of the Connection pointer where the result will be stored
|
|
@return 1=successful, 0=error
|
|
*/
|
|
bool
|
|
convertConnRef(PyObject *conn_ref, Connection** conn)
|
|
{
|
|
if (!PyCObject_Check(conn_ref)) {
|
|
PyErr_SetString(PyExc_TypeError,"Invalid call reference given.");
|
|
return 0;
|
|
}
|
|
|
|
if (! ( *conn=static_cast<Connection*>(PyCObject_AsVoidPtr(conn_ref)) ) ) {
|
|
PyErr_SetString(PyExc_TypeError,"Call reference is NULL. This is not allowed.");
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/** @brief Private converter function to extract the contained Capi* from a PyCObject
|
|
|
|
This function is defined for the use in PyArg_ParseTuple() calls.
|
|
|
|
@param capi_ref - PyCObject pointer
|
|
@param capi address of the Capi pointer where the result will be stored
|
|
@return 1=successful, 0=error
|
|
*/
|
|
bool
|
|
convertCapiRef(PyObject *capi_ref, Capi** capi)
|
|
{
|
|
if (!PyCObject_Check(capi_ref)) {
|
|
PyErr_SetString(PyExc_TypeError,"Invalid Capi reference given.");
|
|
return 0;
|
|
}
|
|
|
|
if (! ( *capi=static_cast<Capi*>(PyCObject_AsVoidPtr(capi_ref)) ) ) {
|
|
PyErr_SetString(PyExc_TypeError,"Capi reference is NULL. This is not allowed.");
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/** @brief Write an informational message to the CapiSuite log.
|
|
@ingroup python
|
|
|
|
This function writes a message to the CapiSuite log. It's helpful if you want to write
|
|
messages in the debug log in your scripts.
|
|
|
|
The message can be either logged with the general CapiSuite prefix if they are of global
|
|
nature or with the Connection prefix if they're associated with a special connection.
|
|
|
|
@param args Contains the python parameters. These are:
|
|
- <b>message (string)</b> the log message
|
|
- <b>level (integer)</b> parameter for log_level
|
|
- <b>call (optional)</b> call reference - if given, the message is logged with Connection prefix
|
|
@return None
|
|
*/
|
|
static PyObject*
|
|
capisuite_log(PyObject*, PyObject *args)
|
|
{
|
|
|
|
Connection* conn=NULL;
|
|
char *message;
|
|
int level;
|
|
|
|
if (!PyArg_ParseTuple(args,"si|O&:log",&message,&level,convertConnRef,&conn))
|
|
return NULL;
|
|
|
|
if (conn)
|
|
conn->debugMessage(message,level);
|
|
else if (capisuiteInstance)
|
|
capisuiteInstance->logMessage(message,level);
|
|
|
|
Py_XINCREF(Py_None);
|
|
return (Py_None);
|
|
}
|
|
|
|
/** @brief Write an error message to the CapiSuite error log.
|
|
@ingroup python
|
|
|
|
This function writes a message to the CapiSuite error log. It
|
|
should be used to output error messages so they appear in the
|
|
normal error log.
|
|
|
|
@param args Contains the python parameter:
|
|
- <b>message (string)</b> the log message
|
|
@return None
|
|
*/
|
|
static PyObject*
|
|
capisuite_error(PyObject*, PyObject *args)
|
|
{
|
|
|
|
Connection* conn=NULL;
|
|
char *message;
|
|
|
|
if (!PyArg_ParseTuple(args,"s|O&:error",&message,convertConnRef,&conn))
|
|
return NULL;
|
|
|
|
if (conn)
|
|
conn->errorMessage(message);
|
|
else if (capisuiteInstance)
|
|
capisuiteInstance->errorMessage(message);
|
|
|
|
Py_XINCREF(Py_None);
|
|
return (Py_None);
|
|
}
|
|
|
|
/** @brief Send an audio file in a speech mode connection.
|
|
@ingroup python
|
|
|
|
This function sends an audio file. The audio file must be in bit-inversed A-Law format. It can be created for example
|
|
with sox using the suffix ".la". It supports abortion if DTMF signal is received.
|
|
|
|
If DTMF abort is enabled, the command will also abort immediately if DTMF was received before it is called. That allows
|
|
you to abort subsequent audio receive and send commands with one DTMF signal w/o needing to check for received DTMF
|
|
after each command.
|
|
|
|
The connction must be in audio mode (use capisuite_connect_voice()), otherwise an exception will be caused.
|
|
|
|
@param args Contains the python parameters. These are:
|
|
- <b>call</b> Reference to the current call
|
|
- <b>filename (string)</b> file to send
|
|
- <b>exit_DTMF (integer, optional)</b> if set to 1, sending is aborted when a DTMF signal is received (0=off, default)
|
|
@return int containing duration of send in seconds
|
|
*/
|
|
static PyObject*
|
|
capisuite_audio_send(PyObject*, PyObject *args)
|
|
{
|
|
Connection* conn;
|
|
char *filename;
|
|
PyThreadState *_save;
|
|
int exit_DTMF=0;
|
|
long duration=0;
|
|
|
|
if (!PyArg_ParseTuple(args,"O&s|i:audio_send",convertConnRef,&conn,&filename,&exit_DTMF))
|
|
return NULL;
|
|
|
|
try {
|
|
Py_UNBLOCK_THREADS
|
|
AudioSend active(conn,filename,exit_DTMF);
|
|
active.mainLoop();
|
|
duration=active.duration();
|
|
Py_BLOCK_THREADS
|
|
}
|
|
catch (CapiWrongState e) {
|
|
Py_BLOCK_THREADS
|
|
PyErr_SetString(CallGoneError,"Call was finished from partner.");
|
|
return NULL;
|
|
}
|
|
catch (CapiMsgError e) {
|
|
Py_BLOCK_THREADS
|
|
PyErr_SetString(BackendError,(e.message()).c_str());
|
|
return NULL;
|
|
}
|
|
catch (CapiExternalError e) {
|
|
Py_BLOCK_THREADS
|
|
PyErr_SetString(BackendError,(e.message()).c_str());
|
|
return NULL;
|
|
}
|
|
catch (CapiError e) {
|
|
Py_BLOCK_THREADS
|
|
PyErr_SetString(BackendError,(e.message()).c_str());
|
|
return NULL;
|
|
}
|
|
|
|
PyObject *r=PyInt_FromLong(duration);
|
|
return (r);
|
|
}
|
|
|
|
/** @brief Receive an audio file in a speech mode connection.
|
|
@ingroup python
|
|
|
|
This functions receives an audio file. It can recognize silence in the signal and timeout after
|
|
a given period of silence, after a general timeout or after the reception of a DTMF signal.
|
|
|
|
If the recording was finished because of silence_timeout, the silence will be truncated away.
|
|
|
|
If DTMF abort is enabled, the command will also abort immediately if DTMF was received before it is called. That allows
|
|
you to abort subsequent audio receive and send commands with one DTMF signal w/o needing to check for received DTMF
|
|
after each command.
|
|
|
|
The connction must be in audio mode (use capisuite_connect_voice()), otherwise an exception will be caused.
|
|
|
|
The created file will be saved in bit-reversed A-Law format, 8 kHz mono. Use sox to convert it to a normal wav file.
|
|
|
|
@param args Contains the python parameters. These are:
|
|
- <b>call</b> Reference to the current call
|
|
- <b>filename (string)</b> where to save received file
|
|
- <b>timeout (integer)</b> receive length in seconds (-1 = infinite)
|
|
- <b>silence_timeout (integer, optional)</b> abort after x seconds of silence (0=off, default)
|
|
- <b>exit_DTMF (integer, optional)</b> if set to 1, sending is aborted when a DTMF signal is received (0=off, default)
|
|
@return int containing duration of receive in seconds
|
|
*/
|
|
static PyObject*
|
|
capisuite_audio_receive(PyObject *, PyObject *args)
|
|
{
|
|
Connection* conn;
|
|
char *filename;
|
|
int timeout, silence_timeout=0;
|
|
PyThreadState *_save;
|
|
int exit_DTMF=0;
|
|
long duration=0;
|
|
|
|
if (!PyArg_ParseTuple(args,"O&si|ii:audio_receive",convertConnRef,&conn,&filename, &timeout, &silence_timeout,&exit_DTMF))
|
|
return NULL;
|
|
|
|
try {
|
|
Py_UNBLOCK_THREADS
|
|
AudioReceive active(conn,filename,timeout,silence_timeout,exit_DTMF);
|
|
active.mainLoop();
|
|
duration=active.duration();
|
|
Py_BLOCK_THREADS
|
|
}
|
|
catch (CapiWrongState e) {
|
|
Py_BLOCK_THREADS
|
|
PyErr_SetString(CallGoneError,"Call was finished from partner.");
|
|
return NULL;
|
|
}
|
|
catch (CapiExternalError e) {
|
|
Py_BLOCK_THREADS
|
|
PyErr_SetString(BackendError,(e.message()).c_str());
|
|
return NULL;
|
|
}
|
|
|
|
PyObject *r=PyInt_FromLong(duration);
|
|
return (r);
|
|
}
|
|
|
|
/** @brief Receive a fax in a fax mode connection
|
|
@ingroup python
|
|
|
|
This command receives an analog fax (fax group 3). It starts the reception and waits for the end of the connection.
|
|
So it should be the last command before capisuite_disconnect.
|
|
|
|
The connction must be in fax mode (use capisuite_connect_faxG3 or capisuite_switch_to_faxG3), otherwise an exception will be caused.
|
|
|
|
The created file will be saved in the Structured Fax File (SFF) format.
|
|
|
|
@param args Contains the python parameters. These are:
|
|
- <b>call</b> Reference to the current call
|
|
- <b>filename (string)</b> where to save received fax
|
|
@return None or a tuple (stationID,rate,hiRes,format,pages) containing the values:
|
|
- fax station ID from the calling party (String)
|
|
- bit rate which was used for connecting (Integer)
|
|
- high (1) or low (0) resolution (Integer)
|
|
- transmit format: 0=SFF,black&white, 1=ColorJPEG (Integer)
|
|
- number of received pages (Integer)
|
|
*/
|
|
static PyObject*
|
|
capisuite_fax_receive(PyObject *, PyObject *args)
|
|
{
|
|
Connection *conn;
|
|
char *filename;
|
|
PyThreadState *_save;
|
|
|
|
if (!PyArg_ParseTuple(args,"O&s:fax_receive",convertConnRef,&conn,&filename))
|
|
return NULL;
|
|
|
|
try {
|
|
Py_UNBLOCK_THREADS
|
|
FaxReceive active(conn,filename);
|
|
active.mainLoop();
|
|
Py_BLOCK_THREADS
|
|
}
|
|
catch (CapiWrongState e) {
|
|
Py_BLOCK_THREADS
|
|
PyErr_SetString(CallGoneError,"Call was finished from partner.");
|
|
return NULL;
|
|
}
|
|
catch (CapiExternalError e) {
|
|
Py_BLOCK_THREADS
|
|
PyErr_SetString(BackendError,(e.message()).c_str());
|
|
return NULL;
|
|
}
|
|
|
|
Connection::fax_info_t* fax_info = conn->getFaxInfo();
|
|
if (fax_info) {
|
|
PyObject *r=Py_BuildValue("siiii",fax_info->stationID.c_str(),fax_info->rate,fax_info->hiRes,fax_info->format,fax_info->pages);
|
|
return (r);
|
|
} else {
|
|
Py_XINCREF(Py_None);
|
|
return (Py_None);
|
|
}
|
|
}
|
|
|
|
/** @brief Send a fax in a fax mode connection
|
|
@ingroup python
|
|
|
|
This command sends an analog fax (fax group 3). It starts the send and waits for the end of the connection.
|
|
So it should be the last command before capisuite_disconnect.
|
|
|
|
The connction must be in fax mode (use capisuite_call_faxG3 or capisuite_switch_to_faxG3), otherwise an exception will be caused.
|
|
|
|
The created file will be saved in the Structured Fax File (SFF) format.
|
|
|
|
@param args Contains the python parameters. These are:
|
|
- <b>call</b> Reference to the current call
|
|
- <b>filename (string)</b> file to send
|
|
@return None or a tuple (stationID,rate,hiRes,format,pages) containing the values:
|
|
- fax station ID from the called party (String)
|
|
- bit rate which was used for connecting (Integer)
|
|
- high (1) or low (0) resolution (Integer)
|
|
- transmit format: 0=SFF,black&white, 1=ColorJPEG (Integer)
|
|
- number of sent pages (Integer)
|
|
@return None
|
|
*/
|
|
static PyObject*
|
|
capisuite_fax_send(PyObject *, PyObject *args)
|
|
{
|
|
Connection *conn;
|
|
char *filename;
|
|
PyThreadState *_save;
|
|
|
|
if (!PyArg_ParseTuple(args,"O&s:fax_send",convertConnRef,&conn,&filename))
|
|
return NULL;
|
|
|
|
try {
|
|
Py_UNBLOCK_THREADS
|
|
FaxSend active(conn,filename);
|
|
active.mainLoop();
|
|
Py_BLOCK_THREADS
|
|
}
|
|
catch (CapiWrongState e) {
|
|
Py_BLOCK_THREADS
|
|
PyErr_SetString(CallGoneError,"Call was finished from partner.");
|
|
return NULL;
|
|
}
|
|
catch (CapiMsgError e) {
|
|
Py_BLOCK_THREADS
|
|
PyErr_SetString(BackendError,(e.message()).c_str());
|
|
return NULL;
|
|
}
|
|
catch (CapiExternalError e) {
|
|
Py_BLOCK_THREADS
|
|
PyErr_SetString(BackendError,(e.message()).c_str());
|
|
return NULL;
|
|
}
|
|
catch (CapiError e) {
|
|
Py_BLOCK_THREADS
|
|
PyErr_SetString(BackendError,(e.message()).c_str());
|
|
return NULL;
|
|
}
|
|
|
|
Connection::fax_info_t* fax_info = conn->getFaxInfo();
|
|
if (fax_info) {
|
|
PyObject *r=Py_BuildValue("siiii",fax_info->stationID.c_str(),fax_info->rate,fax_info->hiRes,fax_info->format,fax_info->pages);
|
|
return (r);
|
|
} else {
|
|
Py_XINCREF(Py_None);
|
|
return (Py_None);
|
|
}
|
|
}
|
|
|
|
/** @brief Disconnect connection.
|
|
@ingroup python
|
|
|
|
This will cause an immediate disconnection. It should be always the last command in every flow of a script.
|
|
It will return a tuple of two result values. The first is the disconnect cause of the physical connection,
|
|
the second the disconnect cause of the logical connection. See CAPI spec for the logical causes and
|
|
ETS 300 102-01 for the physical causes.
|
|
|
|
@param args Contains the python parameters. These are:
|
|
- <b>call</b> Reference to the current call
|
|
@return Tuple containing (ReasonPhysical,ReasonLogical)
|
|
*/
|
|
static PyObject*
|
|
capisuite_disconnect(PyObject *, PyObject *args)
|
|
{
|
|
Connection *conn;
|
|
PyThreadState *_save;
|
|
|
|
if (!PyArg_ParseTuple(args,"O&:disconnect",convertConnRef,&conn))
|
|
return NULL;
|
|
|
|
try {
|
|
Py_UNBLOCK_THREADS
|
|
DisconnectModule active(conn);
|
|
active.mainLoop();
|
|
Py_BLOCK_THREADS
|
|
}
|
|
catch (CapiMsgError e) {
|
|
Py_BLOCK_THREADS
|
|
PyErr_SetString(BackendError,(e.message()).c_str());
|
|
return NULL;
|
|
}
|
|
catch (CapiExternalError e) {
|
|
Py_BLOCK_THREADS
|
|
PyErr_SetString(BackendError,(e.message()).c_str());
|
|
return NULL;
|
|
}
|
|
|
|
PyObject *r=Py_BuildValue("ii",conn->getCause(),conn->getCauseB3());
|
|
return (r);
|
|
}
|
|
|
|
/** @brief Reject an incoming call.
|
|
@ingroup python
|
|
|
|
If you don't want to accept an incoming call for any reason (e.g. if it has a service or comes from a number
|
|
you don't want to accept), use this command. There are several reasons you can give when rejecting a call.
|
|
Some important ones are:
|
|
- 1=ignore call
|
|
- 2=normal call clearing
|
|
- 3=user busy
|
|
- 7=incompatible destination
|
|
- 8=destination out of order
|
|
- 0x34A9=temporary failure
|
|
|
|
You can find many more reasons in the ETS 300 201-01 specification or on the web (search for ISDN cause)
|
|
if you really need them.
|
|
|
|
@param args Contains the python parameters. These are:
|
|
- <b>call</b> Reference to the current call
|
|
- <b>rejectCause (integer)</b> which cause to signal when rejecting call (see above)
|
|
@return None
|
|
*/
|
|
static PyObject*
|
|
capisuite_reject(PyObject *, PyObject *args)
|
|
{
|
|
Connection *conn;
|
|
int rejectCause;
|
|
PyThreadState *_save;
|
|
|
|
if (!PyArg_ParseTuple(args,"O&i:reject",convertConnRef,&conn,&rejectCause) )
|
|
return NULL;
|
|
|
|
try {
|
|
Py_UNBLOCK_THREADS
|
|
DisconnectModule active(conn,rejectCause);
|
|
active.mainLoop();
|
|
Py_BLOCK_THREADS
|
|
}
|
|
catch (CapiMsgError e) {
|
|
Py_BLOCK_THREADS
|
|
PyErr_SetString(BackendError,(e.message()).c_str());
|
|
return NULL;
|
|
}
|
|
catch (CapiExternalError e) {
|
|
Py_BLOCK_THREADS
|
|
PyErr_SetString(BackendError,(e.message()).c_str());
|
|
return NULL;
|
|
}
|
|
|
|
Py_XINCREF(Py_None);
|
|
return (Py_None);
|
|
}
|
|
|
|
|
|
/** @brief helper function for capisuite_connect_voice() and capisuite_connect_faxG3()
|
|
|
|
@param delay delay in seconds before connection will be established
|
|
@param service with which service we should connect
|
|
@param faxStationID only used for fax connections
|
|
@param faxHeadline only used for fax connections
|
|
@return false if exception was rased -> calling function must return NULL then
|
|
*/
|
|
bool
|
|
capisuite_connect(Connection *conn, int delay, Connection::service_t service, string faxStationID, string faxHeadline)
|
|
{
|
|
PyThreadState *_save;
|
|
try {
|
|
Py_UNBLOCK_THREADS
|
|
if (delay) {
|
|
conn->acceptWaiting(); // so that connection doesn't timeout
|
|
sleep(delay);
|
|
}
|
|
ConnectModule active(conn,service, faxStationID, faxHeadline);
|
|
active.mainLoop();
|
|
Py_BLOCK_THREADS
|
|
}
|
|
catch (CapiMsgError e) {
|
|
Py_BLOCK_THREADS
|
|
PyErr_SetString(BackendError,(e.message()).c_str());
|
|
return false;
|
|
}
|
|
catch (CapiWrongState e) {
|
|
Py_BLOCK_THREADS
|
|
PyErr_SetString(CallGoneError,(e.message()).c_str());
|
|
return false;
|
|
}
|
|
catch (CapiExternalError e) {
|
|
Py_BLOCK_THREADS
|
|
PyErr_SetString(BackendError,(e.message()).c_str());
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/** @brief Accept an incoming call and connect with voice service.
|
|
@ingroup python
|
|
|
|
This will accept an incoming call and choose voice as service, so you can use the audio commands
|
|
(like audio_receive and audio_send) with this connection. After this command has finished, the call
|
|
is connected successfully.
|
|
|
|
It's also possible to accept a call with some delay. This is for example useful for an answering
|
|
machine if you want to have the chance to get a call with your phone before your computer answers it.
|
|
|
|
@param args Contains the python parameters. These are:
|
|
- <b>call</b> Reference to the current call
|
|
- <b>delay (integer, optional)</b> delay in seconds _before_ connection will be established (default: 0=immediate connect)
|
|
@return None
|
|
*/
|
|
static PyObject*
|
|
capisuite_connect_voice(PyObject *, PyObject *args)
|
|
{
|
|
Connection *conn;
|
|
int delay=0;
|
|
|
|
if (!PyArg_ParseTuple(args,"O&|i:connect_voice",convertConnRef,&conn,&delay))
|
|
return NULL;
|
|
|
|
if (capisuite_connect(conn,delay,Connection::VOICE,"","")) {
|
|
Py_XINCREF(Py_None);
|
|
return (Py_None);
|
|
} else
|
|
return NULL;
|
|
}
|
|
|
|
/** @brief Accept an incoming call and connect with fax (analog, group 3) service.
|
|
@ingroup python
|
|
|
|
This will accept an incoming call and choose fax group 3 as service, so you can use the fax commands
|
|
(like fax_receive) with this connection. After this command has finished, the call is connected successfully.
|
|
|
|
It's also possible to accept a call with some delay. This is for example useful if you want to have the chance
|
|
to get a call with your phone before your computer answers it.
|
|
|
|
@param args Contains the python parameters. These are:
|
|
- <b>call</b> Reference to the current call
|
|
- <b>faxStationID (string)</b> the station ID to use
|
|
- <b>faxHeadline (string)</b> the fax headline to use
|
|
- <b>delay (integer, optional)</b> delay in seconds _before_ connection will be established (default: 0=immediate connect)
|
|
@return If faxInfo is available, a tuple (stationID,rate,hiRes,format) otherwise None. Tuple contains:
|
|
- fax station ID from the calling party (String)
|
|
- bit rate which was used for connecting
|
|
- high (1) or low (0) resolution
|
|
- transmit format: 0=SFF,black&white, 1=ColorJPEG
|
|
*/
|
|
static PyObject*
|
|
capisuite_connect_faxG3(PyObject *, PyObject *args)
|
|
{
|
|
Connection *conn;
|
|
int delay=0;
|
|
char *faxStationID, *faxHeadline;
|
|
|
|
if (!PyArg_ParseTuple(args,"O&ss|i:connect_faxG3",convertConnRef,&conn,&faxStationID,&faxHeadline,&delay))
|
|
return NULL;
|
|
|
|
if (capisuite_connect(conn,delay,Connection::FAXG3,faxStationID,faxHeadline)) {
|
|
Connection::fax_info_t* fax_info = conn->getFaxInfo();
|
|
if (fax_info) {
|
|
PyObject *r=Py_BuildValue("siii",fax_info->stationID.c_str(),fax_info->rate,fax_info->hiRes,fax_info->format);
|
|
return (r);
|
|
} else {
|
|
Py_XINCREF(Py_None);
|
|
return (Py_None);
|
|
}
|
|
} else
|
|
return NULL;
|
|
}
|
|
|
|
/** @brief helper function for capisuite_call_voice() and capisuite_call_faxG3()
|
|
|
|
@param capi reference to object of Capi to use
|
|
@param controller controller number to use
|
|
@param call_from string containing the own number to use
|
|
@param call_to string containing the number to call
|
|
@param service service to call with as described in Connection::service_t
|
|
@param timeout timeout to wait for connection establishment
|
|
@param faxStationID fax station ID, only necessary when connecting in FAXG3 mode
|
|
@param faxHeadline fax headline, only necessary when connecting in FAXG3 mode
|
|
@param clir set to true to disable sending of own number
|
|
@return tuple (call,result) - call=reference to the created call object / result(int)=result of the call establishment
|
|
*/
|
|
static PyObject*
|
|
capisuite_call(Capi *capi, unsigned short controller, string call_from, string call_to, Connection::service_t service, int timeout, string faxStationID, string faxHeadline, bool clir)
|
|
{
|
|
PyThreadState *_save;
|
|
Connection* conn=NULL;
|
|
int result;
|
|
try {
|
|
Py_UNBLOCK_THREADS
|
|
CallOutgoing active(capi,controller,call_from,call_to,service,timeout,faxStationID,faxHeadline,clir);
|
|
active.mainLoop();
|
|
conn=active.getConnection();
|
|
result=active.getResult();
|
|
Py_BLOCK_THREADS
|
|
}
|
|
catch (CapiMsgError e) {
|
|
Py_BLOCK_THREADS
|
|
PyErr_SetString(BackendError,(e.message()).c_str());
|
|
return NULL;
|
|
}
|
|
catch (CapiExternalError e) {
|
|
Py_BLOCK_THREADS
|
|
PyErr_SetString(BackendError,(e.message()).c_str());
|
|
return NULL;
|
|
}
|
|
|
|
PyObject *r=Py_BuildValue("Ni",PyCObject_FromVoidPtr(conn,capisuitemodule_destruct_connection),result);
|
|
return (r);
|
|
}
|
|
|
|
/** @brief Initiate an outgoing call with service voice and wait for successful connection
|
|
@ingroup python
|
|
|
|
This will initiate an outgoing call and choose voice as service, so you can
|
|
use the audio commands (like audio_receive and audio_send) with this
|
|
connection. After this command has finished, the call is connected
|
|
successfully or the given timeout has exceeded. The timeout is measured
|
|
beginning at the moment when the call is signalled (it's "ringing") to the
|
|
called party.
|
|
|
|
A python tuple (call,result) is returned by this function. It contains:
|
|
- <b>call</b> reference to the created call object - use this for subsequent calls like audio_send
|
|
- <b>result (int)</b> result of the call establishment process.
|
|
- 0 = connection established
|
|
- 1 = connection timeout exceeded, no connection was established
|
|
- 2 = connection wasn't successful and no reason for this failure is available
|
|
- 0x3301-0x34FF: Error reported by CAPI. For a complete description see
|
|
the annex of the user manual
|
|
|
|
@param args Contains the python parameters. These are:
|
|
- <b>capi</b> reference to object of Capi to use (given to the idle function as parameter)
|
|
- <b>controller (int)</b> ISDN controller ID to use (1=first controller)
|
|
- <b>call_from (string)</b>own number to use
|
|
- <b>call_to (string)</b>the number to call
|
|
- <b>timeout (int)</b>timeout to wait for connection establishment in seconds
|
|
- <b>clir (int, optional)</b>set to 1 to disable sending of own number (0=default)
|
|
@return tuple (call,result) - see above.
|
|
*/
|
|
static PyObject*
|
|
capisuite_call_voice(PyObject *, PyObject *args)
|
|
{
|
|
Capi *capi;
|
|
int controller, timeout, clir=0;
|
|
char *call_from,*call_to;
|
|
|
|
if (!PyArg_ParseTuple(args,"O&issi|i:call_voice",convertCapiRef,&capi,&controller,&call_from,&call_to,&timeout,&clir))
|
|
return NULL;
|
|
|
|
return capisuite_call(capi,controller,call_from,call_to,Connection::VOICE,timeout,"","",clir);
|
|
}
|
|
|
|
/** @brief Initiate an outgoing call with service faxG3 and wait for successful connection
|
|
@ingroup python
|
|
|
|
This will initiate an outgoing call and choose fax group 3 as service, so
|
|
you can use the fax commands (like fax_send and fax_receive) with this
|
|
connection. After this command has finished, the call is connected
|
|
successfully or the given timeout has exceeded. The timeout is measured
|
|
beginning at the moment when the call is signalled (it's "ringing") to the
|
|
called party.
|
|
|
|
A python tuple (call,result) is returned by this function. It contains:
|
|
- <b>call</b> reference to the created call object - use this for subsequent calls like audio_send
|
|
- <b>result (int)</b> result of the call establishment process.
|
|
- 0 = connection established
|
|
- 1 = connection timeout exceeded, no connection was established
|
|
- 2 = connection wasn't successful and no reason for this failure is available
|
|
- 0x3301-0x34FF: Error reported by CAPI. For a complete
|
|
description see the annex of the user manual
|
|
|
|
@param args Contains the python parameters. These are:
|
|
- <b>capi</b> reference to object of Capi to use (given to the idle function as parameter)
|
|
- <b>controller (int)</b> ISDN controller ID to use (1=first controller)
|
|
- <b>call_from (string)</b>own number to use
|
|
- <b>call_to (string)</b>the number to call
|
|
- <b>timeout (int)</b>timeout to wait for connection establishment in seconds
|
|
- <b>faxStationID (string)</b>fax station ID
|
|
- <b>faxHeadline (string)</b> fax headline to print on every page
|
|
- <b>clir (int, optional)</b>set to 1 to disable sending of own number (0=default)
|
|
@return tuple (call,result) - see above.
|
|
*/
|
|
static PyObject*
|
|
capisuite_call_faxG3(PyObject *, PyObject *args)
|
|
{
|
|
Capi *capi;
|
|
int controller, timeout, clir=0;
|
|
char *call_from,*call_to,*faxStationID,*faxHeadline;
|
|
|
|
if (!PyArg_ParseTuple(args,"O&ississ|i:call_faxG3",convertCapiRef,&capi,&controller,&call_from,&call_to,&timeout,&faxStationID,&faxHeadline,&clir))
|
|
return NULL;
|
|
|
|
return capisuite_call(capi,controller,call_from,call_to,Connection::FAXG3,timeout,faxStationID,faxHeadline,clir);
|
|
}
|
|
|
|
/** @brief Switch a connection from voice mode to fax mode.
|
|
@ingroup python
|
|
|
|
This will switch from voice mode to fax group 3 after you have connected, so you can use the fax commands afterwards.
|
|
|
|
<em><b>Attention:</b></em> This command isn't supported by every ISDN card / CAPI driver!
|
|
|
|
@param args Contains the python parameters. These are:
|
|
- <b>call</b> Reference to the current call
|
|
- <b>faxStationID (string)</b> the station ID to use
|
|
- <b>faxHeadline (string)</b> the fax headline to use
|
|
@return If faxInfo is available, a tuple (stationID,rate,hiRes,format) otherwise None. Tuple contains:
|
|
- fax station ID from the calling party (String)
|
|
- bit rate which was used for connecting
|
|
- high (1) or low (0) resolution
|
|
- transmit format: 0=SFF,black&white, 1=ColorJPEG
|
|
*/
|
|
static PyObject*
|
|
capisuite_switch_to_faxG3(PyObject *, PyObject *args)
|
|
{
|
|
Connection *conn;
|
|
char *faxStationID, *faxHeadline;
|
|
PyThreadState *_save;
|
|
|
|
if (!PyArg_ParseTuple(args,"O&ss:switch_to_faxG3",convertConnRef,&conn,&faxStationID,&faxHeadline))
|
|
return NULL;
|
|
|
|
try {
|
|
Py_UNBLOCK_THREADS
|
|
Switch2FaxG3 active(conn,faxStationID,faxHeadline);
|
|
active.mainLoop();
|
|
Py_BLOCK_THREADS
|
|
}
|
|
catch (CapiWrongState e) {
|
|
Py_BLOCK_THREADS
|
|
PyErr_SetString(CallGoneError,"Call was finished from partner.");
|
|
return NULL;
|
|
}
|
|
catch (CapiExternalError e) {
|
|
Py_BLOCK_THREADS
|
|
PyErr_SetString(BackendError,(e.message()).c_str());
|
|
return NULL;
|
|
}
|
|
|
|
Connection::fax_info_t* fax_info = conn->getFaxInfo();
|
|
if (fax_info) {
|
|
PyObject *r=Py_BuildValue("siii",fax_info->stationID.c_str(),fax_info->rate,fax_info->hiRes,fax_info->format);
|
|
return (r);
|
|
} else {
|
|
Py_XINCREF(Py_None);
|
|
return (Py_None);
|
|
}
|
|
}
|
|
|
|
/** @brief Enable recognition of DTMF tones.
|
|
@ingroup python
|
|
|
|
You have to enable the recognition of DTMF tones if you want to use them in your script.
|
|
|
|
@param args Contains the python parameters. These are:
|
|
- <b>call</b> Reference to the current call
|
|
@return None
|
|
*/
|
|
static PyObject*
|
|
capisuite_enable_DTMF(PyObject *, PyObject *args)
|
|
{
|
|
Connection *conn;
|
|
|
|
if (!PyArg_ParseTuple(args,"O&:enable_DTMF",convertConnRef,&conn) )
|
|
return NULL;
|
|
|
|
try {
|
|
conn->enableDTMF();
|
|
}
|
|
catch (CapiWrongState) { // issued when we have no connection
|
|
PyErr_SetString(CallGoneError,"Call was finished from partner.");
|
|
return NULL;
|
|
}
|
|
catch (CapiMsgError e) {
|
|
PyErr_SetString(BackendError,(e.message()).c_str());
|
|
return NULL;
|
|
}
|
|
|
|
Py_XINCREF(Py_None);
|
|
return (Py_None);
|
|
}
|
|
|
|
/** @brief Disable recognition of DTMF tones.
|
|
@ingroup python
|
|
|
|
You can disable the recognition of DTMF tones again if you want to.
|
|
|
|
@param args Contains the python parameters. These are:
|
|
- <b>call</b> Reference to the current call
|
|
@return None
|
|
*/
|
|
static PyObject*
|
|
capisuite_disable_DTMF(PyObject *, PyObject *args)
|
|
{
|
|
Connection *conn;
|
|
|
|
if (!PyArg_ParseTuple(args,"O&:disable_DTMF",convertConnRef,&conn) )
|
|
return NULL;
|
|
|
|
try {
|
|
conn->disableDTMF();
|
|
}
|
|
catch (CapiWrongState) { // issued when we have no connection
|
|
PyErr_SetString(CallGoneError,"Call was finished from partner.");
|
|
return NULL;
|
|
}
|
|
catch (CapiMsgError e) {
|
|
PyErr_SetString(BackendError,(e.message()).c_str());
|
|
return NULL;
|
|
}
|
|
|
|
Py_XINCREF(Py_None);
|
|
return (Py_None);
|
|
}
|
|
|
|
/** @brief Read the received DTMF tones or wait for a certain amount of them.
|
|
@ingroup python
|
|
|
|
This function allows to just read in the DTMF tones which were already received. But it also supports to
|
|
wait for a certain amount of DTMF tones if you want the user to always input some digits at a certain
|
|
step in your script.
|
|
|
|
You can specify how much DTMF tones you want in several ways - see the parameter description. To just
|
|
see if something was entered before, use capisuite.read_DTMF(0). If you want to get at least 1 and mostly 4 digits
|
|
and want to wait 5 seconds for additional digits, you'll use capisuite.read_DTMF(5,1,4).
|
|
|
|
Valid DTMF characters are '0'...'9','A'...'D' and two special fax tones: 'X' (CNG), 'Y' (CED)
|
|
|
|
@param args Contains the python parameters. These are:
|
|
- <b>call</b> Reference to the current call
|
|
- <b>timeout (integer)</b> timeout in seconds after which reading is terminated, only applied when min_digits are reached! (-1 = infinite)
|
|
- <b>min_digits (integer, optional)</b> minimum number of digits which must be read in ANY case, i.e. timout doesn't count here (default: 0)
|
|
- <b>max_digits (integer, optional)</b> maximum number of digits to read (aborts immediately if this number is reached) (0=infinite, i.e. only timeout counts, default)
|
|
@return python string containing the received DTMF characters
|
|
*/
|
|
static PyObject*
|
|
capisuite_read_DTMF(PyObject *, PyObject *args)
|
|
{
|
|
Connection *conn;
|
|
PyThreadState *_save;
|
|
int timeout, min_digits=0, max_digits=0;
|
|
|
|
if (!PyArg_ParseTuple(args,"O&i|ii:read_DTMF",convertConnRef,&conn, &timeout, &min_digits, &max_digits) )
|
|
return NULL;
|
|
|
|
string dtmf_received;
|
|
try {
|
|
Py_UNBLOCK_THREADS
|
|
ReadDTMF active(conn,timeout,min_digits,max_digits);
|
|
active.mainLoop();
|
|
dtmf_received=conn->getDTMF();
|
|
conn->clearDTMF();
|
|
Py_BLOCK_THREADS
|
|
}
|
|
catch (CapiWrongState e) {
|
|
Py_BLOCK_THREADS
|
|
PyErr_SetString(CallGoneError,"Call was finished from partner.");
|
|
return NULL;
|
|
}
|
|
|
|
PyObject* result=Py_BuildValue("s",dtmf_received.c_str());
|
|
return (result);
|
|
}
|
|
|
|
|
|
/** PCallControlMethods - array of functions in module capisuite
|
|
*/
|
|
static PyMethodDef PCallControlMethods[] = {
|
|
{"audio_receive", capisuite_audio_receive, METH_VARARGS, "Receive audio. For further details see capisuite module reference."},
|
|
{"audio_send", capisuite_audio_send, METH_VARARGS, "Send audio. For further details see capisuite module reference."},
|
|
{"fax_receive", capisuite_fax_receive, METH_VARARGS, "Receive fax. For further details see capisuite module reference."},
|
|
{"fax_send", capisuite_fax_send, METH_VARARGS, "Send fax. For further details see capisuite module reference."},
|
|
{"disconnect", capisuite_disconnect, METH_VARARGS, "Disconnect call. For further details see capisuite module reference."},
|
|
{"connect_voice", capisuite_connect_voice, METH_VARARGS, "Connect pending call with Telephony services. Arguments: call, delay"},
|
|
{"connect_faxG3", capisuite_connect_faxG3, METH_VARARGS, "Connect pending call with FaxG3 services. For further details see capisuite module reference."},
|
|
{"call_voice", capisuite_call_voice, METH_VARARGS, "Initiate an outgoing call with service voice. For further details see capisuite module reference."},
|
|
{"call_faxG3", capisuite_call_faxG3, METH_VARARGS, "Initiate an outgoing call with service FaxG3. For further details see capisuite module reference."},
|
|
{"switch_to_faxG3", capisuite_switch_to_faxG3, METH_VARARGS, "Switch from telephony to FaxG3 services. For further details see capisuite module reference."},
|
|
{"reject", capisuite_reject, METH_VARARGS, "Reject waiting call. For further details see capisuite module reference."},
|
|
{"enable_DTMF", capisuite_enable_DTMF, METH_VARARGS, "Enable DTMF recognition. For further details see capisuite module reference."},
|
|
{"disable_DTMF", capisuite_disable_DTMF, METH_VARARGS, "Disable DTMF recognition. For further details see capisuite module reference."},
|
|
{"read_DTMF", capisuite_read_DTMF, METH_VARARGS, "Read and clear received DTMF. For further details see capisuite module reference."},
|
|
{"log", capisuite_log, METH_VARARGS, "Write log message. For further details see capisuite module reference."},
|
|
{"error", capisuite_error, METH_VARARGS, "Write error message. For further details see capisuite module reference."},
|
|
{NULL,NULL,0,NULL}
|
|
};
|
|
|
|
void
|
|
capisuitemodule_init () throw (ApplicationError)
|
|
{
|
|
PyObject *mod,*d;
|
|
try {
|
|
if ( ! ( mod=Py_InitModule3("_capisuite", PCallControlMethods, "Python module for controlling CapiSuite") ) ) // m=borrowed ref
|
|
throw ApplicationError("unable to init python module capisuite (InitModule failed)","capisuite_init()");
|
|
|
|
if ( ! ( d=PyModule_GetDict(mod) ) ) // d=borrowed ref
|
|
throw ApplicationError("unable to init python module capisuite (GetDict(mod) failed)","capisuite_init()");
|
|
|
|
if (!CallGoneError)
|
|
if (! (CallGoneError=PyErr_NewException("capisuite.CallGoneError", NULL, NULL) ) )
|
|
throw ApplicationError("unable to init python module capisuite (NewException for CallGoneError failed)","capisuite_init()");
|
|
if (!BackendError)
|
|
if (! (BackendError=PyErr_NewException("capisuite.BackendError", NULL, NULL) ) )
|
|
throw ApplicationError("unable to init python module capisuite (NewException for BackendError failed)","capisuite_init()");
|
|
|
|
if (PyDict_SetItemString(d, "CallGoneError", CallGoneError)!=0)
|
|
throw ApplicationError("unable to init python module capisuite (SetItemString for CallGoneError failed)","capisuite_init()");
|
|
if (PyDict_SetItemString(d, "BackendError", BackendError)!=0)
|
|
throw ApplicationError("unable to init python module capisuite (SetItemString for BackendError failed)","capisuite_init()");
|
|
|
|
if (PyModule_AddIntConstant(mod, "SERVICE_VOICE", Connection::VOICE) != 0)
|
|
throw ApplicationError("unable to init python module capisuite (adding constant SERVICE_VOICE failed)","capisuite_init()");
|
|
if (PyModule_AddIntConstant(mod, "SERVICE_FAXG3", Connection::FAXG3) != 0)
|
|
throw ApplicationError("unable to init python module capisuite (adding constant SERVICE_FAXG3 failed)","capisuite_init()");
|
|
if (PyModule_AddIntConstant(mod, "SERVICE_OTHER", Connection::OTHER) != 0)
|
|
throw ApplicationError("unable to init python module capisuite (adding constant SERVICE_OTHER failed)","capisuite_init()");
|
|
}
|
|
catch(ApplicationError) {
|
|
if (CallGoneError)
|
|
Py_DECREF(CallGoneError);
|
|
if (BackendError)
|
|
Py_DECREF(BackendError);
|
|
throw;
|
|
}
|
|
}
|
|
|
|
|
|
/* History
|
|
|
|
Old Log (for new changes see ChangeLog):
|
|
Revision 1.7 2003/08/24 12:49:21 gernot
|
|
- switch_to_faxG3: return faxInfo structure instead of None
|
|
|
|
Revision 1.6 2003/08/10 12:00:57 gernot
|
|
- added better description for controller ID
|
|
|
|
Revision 1.5 2003/07/20 10:31:52 gernot
|
|
- return information about transfers in fax receive/send, audio receive
|
|
|
|
Revision 1.4 2003/05/25 13:38:30 gernot
|
|
- support reception of color fax documents
|
|
|
|
Revision 1.3 2003/04/17 10:53:54 gernot
|
|
- update documentation of capisuite_call_* to the new behaviour (timeout for
|
|
outgoing calls starts when other party gets signalled), moved error code
|
|
description to manual
|
|
|
|
Revision 1.2 2003/02/21 23:21:44 gernot
|
|
- follow some a little bit stricter rules of gcc-2.95.3
|
|
|
|
Revision 1.1.1.1 2003/02/19 08:19:53 gernot
|
|
initial checkin of 0.4
|
|
|
|
Revision 1.21 2003/01/31 11:26:46 ghillie
|
|
- add "extern capisuiteInstance"
|
|
- add two missing Py_BLOCK_THREADS in capisuite_reject()
|
|
|
|
Revision 1.20 2003/01/19 16:50:27 ghillie
|
|
- removed severity in exceptions. No FATAL-automatic-exit any more.
|
|
Removed many FATAL conditions, other ones are exiting now by themselves
|
|
|
|
Revision 1.19 2003/01/19 12:07:47 ghillie
|
|
- new functions capisuite_log and capisuite_error (resolves TODO)
|
|
|
|
Revision 1.18 2003/01/16 13:01:21 ghillie
|
|
- updated comment of audio_receive: truncates silence now
|
|
|
|
Revision 1.17 2003/01/04 15:54:58 ghillie
|
|
- use new *Message functions of Connection
|
|
|
|
Revision 1.16 2002/12/16 13:12:06 ghillie
|
|
- destruct_connection now uses correct debug stream
|
|
- changed disconnect() to return cause and causeB3
|
|
|
|
Revision 1.15 2002/12/13 11:44:34 ghillie
|
|
added support for fax send
|
|
|
|
Revision 1.14 2002/12/13 09:57:10 ghillie
|
|
- error message formatting done by exception classes now
|
|
|
|
Revision 1.13 2002/12/11 13:37:25 ghillie
|
|
- use quick_disconnect in destruct when connection is still established
|
|
because this is the result of some error
|
|
|
|
Revision 1.12 2002/12/11 13:00:19 ghillie
|
|
- modified capisuitemodule_call_* and convertFlowControlRef (now named
|
|
convertCapiRef) to use Capi ptr instead of FlowControl ptr
|
|
|
|
Revision 1.11 2002/12/10 15:03:53 ghillie
|
|
- capisuitemodule_destruct_connection does nice disconnection now
|
|
|
|
Revision 1.10 2002/12/07 22:35:46 ghillie
|
|
- capisuite_connect(): removed PyErr_Occured() check
|
|
- capisuitemodule_init: doesn't return __main__ namespace any more
|
|
- FIX in capisuitemodule_init: don't double create exceptions any more!
|
|
- capisuitemodule_init: use shorter PyModule_AddIntConstant() instead of
|
|
manual creation and registration
|
|
|
|
Revision 1.9 2002/12/06 15:24:25 ghillie
|
|
- reject uses DisconnectModule, too, now and waits for disconnection
|
|
|
|
Revision 1.8 2002/12/06 12:53:08 ghillie
|
|
- added destruction function for Connection objects
|
|
- removed capisuitemodule_call_gone()
|
|
- changed capisuite_disconnect(): use DisconnectModule, wait for disconnect,
|
|
return ISDN disconnect cause
|
|
- fixed some typos in PyArg_ParseTuple() calls
|
|
- changed capisuite_call* to return a tuple (call,result)
|
|
|
|
Revision 1.7 2002/12/05 15:54:22 ghillie
|
|
- removed checks for PyErr_Occured() as exceptions won't be thrown in from outside any more
|
|
|
|
Revision 1.6 2002/12/05 14:49:47 ghillie
|
|
- added convertFlowControlRef()
|
|
- new python functions: call_voice and call_faxG3 for initiating outgoing calls
|
|
|
|
Revision 1.5 2002/12/04 10:38:14 ghillie
|
|
- audio_send and audio_receive do return duration now
|
|
|
|
Revision 1.4 2002/12/02 16:53:23 ghillie
|
|
- some minor fixes in the docu strings
|
|
- typo (SERVICE_SPEECH->SERVICE_VOICE)
|
|
|
|
Revision 1.3 2002/12/02 12:26:31 ghillie
|
|
- renamed Connection::SPEECH to Connection::VOICE
|
|
- 3 new constants defined in init function: SERVICE_VOICE, SERVICE_FAXG3, SERVICE_OTHER
|
|
- moved DECREF's to exception handler where appropriate
|
|
|
|
Revision 1.2 2002/11/29 11:37:39 ghillie
|
|
- missed some changes from CapiCom to CapiSuite
|
|
|
|
Revision 1.1 2002/11/29 11:06:22 ghillie
|
|
renamed CapiCom to CapiSuite (name conflict with MS crypto API :-( )
|
|
|
|
Revision 1.5 2002/11/29 10:20:44 ghillie
|
|
- updated docs, use doxygen format now
|
|
|
|
Revision 1.4 2002/11/27 15:56:56 ghillie
|
|
renamed connect_telephony to connect_voice
|
|
|
|
Revision 1.3 2002/11/25 11:48:48 ghillie
|
|
- improved parameter descriptions for python functions
|
|
- made more python parameter optional
|
|
- removed CIPvalue from application layer, use service type instead
|
|
- renamed get_DTMF() to read_DTMF(), added additional parameters (timeout, min_/max_digits), uses ReadDTMF-module now
|
|
|
|
Revision 1.2 2002/11/23 15:55:51 ghillie
|
|
changed some misleading function names
|
|
|
|
Revision 1.1 2002/11/22 15:44:54 ghillie
|
|
renamed pcallcontrol.* to capicommodule.*
|
|
|
|
Revision 1.18 2002/11/22 15:07:09 ghillie
|
|
- new python function switch_to_faxG3
|
|
- new parameter exit_DTMF for audio_send() and audio_receive()
|
|
- new parameters faxStationID and faxHeadline for connect_faxG3
|
|
- get_DTMF calls conn->clearDTMF() now
|
|
|
|
Revision 1.17 2002/11/21 15:26:19 ghillie
|
|
- removed some unnecessary commands (we don't need result of mainLoop() any more, no need to use pointers for call modules any more)
|
|
- removed python command connect(call,CIP), added connect_telephony() and connect_faxG3()
|
|
- connect_telephony() and connect_faxG3 take delay in seconds before connect as parameter now
|
|
- unified python function names (enableDTMF -> enable_DTMF, disableDTMF -> disable_DTMF, getDTMF -> get_DTMF
|
|
|
|
Revision 1.16 2002/11/20 17:23:04 ghillie
|
|
- fixed locking in the case of an exception. Python locks weren't set-up again when an exception occurred
|
|
- removed unnecessary conn->isUp() calls (handled via exceptions now)
|
|
- CapiWrongState exception causes CallGoneError to be issued in Python now
|
|
- removed unnecessary PyErr_Occured() calls at the end of each function
|
|
- added missing Py_XDECREF in _init()
|
|
|
|
Revision 1.15 2002/11/19 15:57:18 ghillie
|
|
- Added missing throw() declarations
|
|
- phew. Added error handling. All exceptions are caught now.
|
|
|
|
Revision 1.14 2002/11/18 14:21:07 ghillie
|
|
- moved global severity_t to ApplicationError::severity_t
|
|
- added throw() declarations to header files
|
|
|
|
Revision 1.13 2002/11/18 12:08:46 ghillie
|
|
return reference to GetDict(__main__) instead of GetDict(pcallcontrol), so that callIncoming can live in __main__
|
|
|
|
Revision 1.12 2002/11/17 14:36:32 ghillie
|
|
improved error handling: script will now terminate if B3 connection is lost
|
|
(each function checks for PyErr_Occurred() and conn->isUp() now)
|
|
|
|
Revision 1.11 2002/11/14 17:04:05 ghillie
|
|
* major structural changes - much is easier, nicer and better prepared for the future now:
|
|
- added DisconnectLogical handler to CallInterface
|
|
- DTMF handling moved from CallControl to Connection
|
|
- new call module ConnectModule for establishing connection
|
|
- python script reduced from 2 functions to one (callWaiting, callConnected
|
|
merged to callIncoming)
|
|
- call modules implement the CallInterface now, not CallControl any more
|
|
=> this freed CallControl from nearly all communication stuff
|
|
|
|
* converter function for PyCObject -> Connection pointer introduced
|
|
-> this saves us many identical code lines in all Python/C integration
|
|
functions
|
|
|
|
Revision 1.10 2002/11/13 15:23:21 ghillie
|
|
added new parameter to audio_receive (silence_timeout)
|
|
fixed deadlock: in deletion of call modules must happen w/o holding python global lock
|
|
|
|
Revision 1.9 2002/11/13 08:34:54 ghillie
|
|
moved history to the bottom
|
|
|
|
Revision 1.8 2002/11/10 17:03:45 ghillie
|
|
now CallControl reference is passed directly to the called Pyhton functions
|
|
|
|
Revision 1.7 2002/11/06 16:16:07 ghillie
|
|
added code to raise CallGoneError in any case so the script is cancelled when the call is gone surely
|
|
|
|
Revision 1.6 2002/10/31 12:35:58 ghillie
|
|
added DTMF support
|
|
|
|
Revision 1.5 2002/10/30 16:05:20 ghillie
|
|
cosmetic fixes...
|
|
|
|
Revision 1.4 2002/10/30 14:25:54 ghillie
|
|
added connect,disconnect,reject functions, changed init function to return the module dictionary
|
|
|
|
Revision 1.3 2002/10/29 14:07:38 ghillie
|
|
changed to implecete pass call parameter so the user doesn't have to type it in the script...
|
|
|
|
Revision 1.2 2002/10/27 12:47:20 ghillie
|
|
- added multithread support for python
|
|
- changed callcontrol reference to stay in the python namespace
|
|
- changed ApplicationError to support differen severity
|
|
|
|
Revision 1.1 2002/10/25 13:29:38 ghillie
|
|
grouped files into subdirectories
|
|
|
|
Revision 1.3 2002/10/24 09:55:52 ghillie
|
|
many fixes. Works for one call now
|
|
|
|
Revision 1.2 2002/10/23 15:42:11 ghillie
|
|
- added standard headers
|
|
- changed initialization code (object references now set in extra function)
|
|
- added some missing Py_None
|
|
|
|
*/
|