PIKA GrandPrix 1.3 Programmer's Guide Copyright (c) 2007. All rights reserved.
Table of Contents Copyright Information 1 Contacting PIKA Technologies 2 Introduction 3 Purpose and Scope 4 Assumed Knowledge 4 Related Documentation GrandPrix SDK Architecture GrandPrix Object Descriptions System Object States GrandPrix SDK Object Relationships Application Development 6 7 9 9 11 API Principles 11 Design Guidelines 13 Basic Functions 1 System Start 1 Event Queue 21 Application Logging 24 Log File Management 2 User Application Logging 27 Call Processing Initiating a Call 28 32 iii
Call Analysis 36 Called and Calling Number Formats 40 Call Initiation Examples 43 Receiving a Call 4 Joining Calls 49 Call Transfer 0 Terminating a Call 7 Skype Calls 61 Media Processing 63 Playing a Stored Message 64 Recording Audio Data From a Channel 71 Collecting DTMF Digits From a Channel 78 Sending DTMF Digits to a Channel 83 Generating Tones on a Channel 83 Detecting Tones on a Channel 8 Detecting Speech on a Channel 86 Audio Flags 87 Media Processing Termination Conditions 89 Conferencing Virtual Channels in Conferences Phones iv 92 96 97 Building a PIKA GrandPrix SDK Application 100 Distributing a PIKA GrandPrix SDK Application 104 Advanced Topics 106 Configuring a Channel 106 Modifying PIKA GrandPrix SDK Source Code 107 Bypassing the PIKA GrandPrix SDK to Make Low-level Function Calls 113
Sample Applications 123 Glossary 124 Index a v
1 1 Copyright Information 1 COPYRIGHTS Copyright 2007 PIKA Technologies Inc. TRADEMARKS PIKA is a registered trademark of PIKA Technologies Inc. All other trademarks, product names and company names and/or logos cited herein, if any, are the property of their respective holders. DISCLAIMER This document is provided to you for informational purposes only and is believed to be accurate as of the date of its publication, and is subject to change without notice. PIKA Technologies Inc. assumes no responsibility for any errors or omissions in this document and shall have no obligation to you as a result of having made this document available to you or based upon the information it contains. 1
2 2 Contacting PIKA Technologies Customer Care 2 PIKA Technologies provides free technical support to all customers. For support issues, phone or e-mail our Customer Care department at the following: Tel: +1-613-91-1 FAX: +1-613-91-929 Email: support@pikatech.com International Headquarters PIKA Technologies Inc. 3 Legget Drive, Suite 400 Ottawa, Ontario, Canada K2K 3B8 Tel: +1-613-91-1 FAX: +1-613-91-929 Email: sales@pikatech.com Internet Visit our website at www.pikatechnologies.com for the latest news, product announcements, downloads, online community, documentation updates, and contact information. 2
3 3 Introduction The PIKA MonteCarlo suite is made up of an SDK that contains three components: AllOnBoard (AoB), AllOnHost (AoH), and GrandPrix (GP). There are various hardware boards that provide connectivity to digital (T1 and E1) and analog devices. The PIKA AoB SDK and PIKA AoH SDK are low-level APIs providing a detailed control of voice media processing and call protocol messaging. The PIKA GrandPrix SDK is a high-level API providing an abstraction of call signaling (analog, digital, and IP) and call control for SIP (AoB and AoH), ISDN (AoB and AoH), CAS (AoB), 3 and Analog with Caller-ID (AoB and AoH). GP is designed to work directly with the AoH or AoB SDKs and provides mechanisms allowing user applications to access the finer control provided by these low-level APIs. GP is a collection of high-level function calls that make it easier and faster for designers to develop user applications based on PIKA hardware and software. It removes most of the in-depth knowledge required to develop user applications to make calls (TDM, Analog or VoIP); play and record files; and perform media analysis such as digit and tone detection, call progress, and call analysis. At the same time, it has the flexibility to co-exist with the low-level API. The following features are available in GP: Abstraction of AoB and AoH technology Basic call progress and call analysis for all call protocols Play to and record from a file or buffer, with terminating conditions Digit collection with terminating conditions Tone detection and generation Switching and conferencing NOTE: Only one user application can be supported by GP on each deployment platform at the same time. Guide Organization - This guide is organized as follows: Introduction - explains the purpose and scope of the guide, how to use the guide, and lists other related documents. Architecture (pg. 6) - provides a detailed description of the high level API architecture, including what high-level objects can be accessed through the API. Application Development (pg. 11) - provides the basic information required to develop an application using GP, including system start up and shutdown, event queues, media processing, call processing, and conferencing. Building Applications with the PIKA GrandPrix SDK (pg. 100) - provides guidelines for building user applications on Linux and Windows platforms. 3
3.3 Related Documentation Distributing Applications - (pg. 104) describes the components that must be distributed with the user application, and where these components must reside on the target platform for proper user application operation. Advanced Topics - (pg. 106) describes how to modify the source code and how to call the low-level API functions from a GP user application. The PIKA MonteCarlo Software License Agreement constitutes a legal agreement ("License Agreement") between you and PIKA Technologies Inc. ("PIKA") and covers software, media, and accompanying on-line or printed documentation distributed by PIKA. The full version of the agreement appears as you install the software. 3 3.1 Purpose and Scope GrandPrix (GP) makes full use of host and DSP media processing technology. It builds on the the AoH and AoB rich feature set to allow for simpler system architectures, reduced development time, and significantly reduced cost of ownership in comparison to the traditional Computer Telephony Integration (CTI) solutions. This guide describes how to use GP to create typical voice processing applications based on either the AoH SDK or AoB SDK. These applications include VoIP and ISDN call processing, and voice processing such as record, play, DTMF detection, and tone detection and generation. 3.2 Assumed Knowledge GP provides users with a highly-flexible API. We assume you are familiar with: Telephony concepts (such as pulse dialing, hookflash, ring patterns, and general call processing states and events) An understanding of ISDN to create GP configuration files (See http://www.itu.int/home/index.html for more information on the ISDN standard) An understanding of VoIP to create GP configuration files: SIP (See http://www.ietf.org/ for more information on the SIP standard) RTP (See http://www.ietf.org/ for more information on the RTP standard) PC hardware and software usage and architecture C/C++ programming 4
3.3 Related Documentation 3.3 Related Documentation The following documents are related to the PIKA GrandPrix Programmers Guide. These documents are linked together and constitute the complete set of documentation for the GP SDK. PIKA GrandPrix Getting Started Guide: This guide provides a step-by-step procedure for installing GP. 3 PIKA GrandPrix Configuration Guide: This guide describes how to use the GPConfig tool, how configuration files are set up, and how to modify the configuration files. PIKA GrandPrix API Reference: This guide provides a reference for all function calls, error codes, event codes, type codes, and other important information for GP. PIKA GrandPrix Release Notes: These notes describe the contents of the release. This includes a list of new hardware and software, new software features, and known product issues.
4 4 GrandPrix SDK Architecture This topic describes the architecture of GP. To develop a call processing user application, it is important to understand what GP objects are defined in the API and the relationships between them. The architectural description is broken into the following topics: PIKA GrandPrix SDK Object Descriptions (pg. 7) that describes the objects in GP architecture PIKA GrandPrix SDK Object Relationships (pg. 9) that describes how GP objects are related to each other The following diagram shows the GP architecture: 4 Typically the user application has at least two threads: one thread to manage the interface with the user, and a second thread to wait for and process events generated by GP. Both threads communicate through the GP interface with the 6
4.1 GrandPrix Object Descriptions AoH or AoB SDK components. Both the AoH and AoB SDK components may be integrated into the same user application. NOTE: Channels controlled by one component can NOT be connected to channels controlled by another component. GP Main spawns three other threads: GP Timer Thread: responsible for managing timers within GP. AoH Product Thread: responsible for executing user application requests on AoH resources and for handling AoH events and converting them into GP events. AoB Product Thread: responsible for executing user application requests on AoB resources and for handling AoB events and converting them into GP events. NOTE: Only one user application can be supported by GP on each deployment platform. 4 4.1 GrandPrix Object Descriptions The following diagram shows the objects available through GP. All GP objects can generate events. An event is a message about a significant occurrence that has happened to the object during its operation. Events are specific to each type of object. See the Event Queue (pg. 21) section for more information on the generation and processing of events. The System object allows the user application to: 7
System Object States 4.1 GrandPrix Object Descriptions Load in the system configuration Start and stop GP call processing engines Retrieve an event for processing Get and set the user data field for object events Inject events into the event queue Group objects allow user applications to group together related channels of the same type. The group defines the number of channels controlled by the group and the protocols used for incoming and outgoing calls on those channels. The group types are: VoIP groups SIP Skype 4 TDM groups ISDN CAS FXO (analog trunks) FXS (analog phones) Virtual groups Group objects defined in configuration files are automatically created when the system object is opened. Channel objects represent bearer channels that carry voice media. Media processing functions, such as play, record, tone detection, tone generation, digit detection, and digit generation, can be applied to channels. Channels can be connected to other channels to make full- or half-duplex connections. Channel objects are defined in configuration files and are automatically created when the system object is opened. Virtual channels are an exception in that they are created and destroyed dynamically by the user. Conference objects represent audio conferences, which allow more than two channels to be joined. Channels can be added to and removed from conference objects. Conference objects are dynamically created by the user application. Call objects represent incoming or outgoing calls made or received by the user application. The interface to call objects is the same, regardless of the protocol used for the call. Call objects are automatically created when calls are received or made by the user application. 8
4.2 GrandPrix SDK Object Relationships 4.1.1 System Object States The typical GP object transitions through the life-cycle states shown in the following figure: disabled, enabled, and running. In the disabled state, nothing happens. In the enabled state, an object handle can be retrieved by the user application for configuration purposes, but no events are raised. In the running state, events can occur at any time. 4 4.2 GrandPrix SDK Object Relationships The following diagram shows the relationships between GP objects. There is one system object that contains many groups. A group can contain many channels, and a channel belongs to one group. A call is associated with one channel and a channel may be associated with at most one call. 9
4.2 GrandPrix SDK Object Relationships A channel may be connected to at most one other channel, and a connection can be made between two channels. A channel may be a member of one conference and a conference may have many channels as members. A virtual channel may be connected to one other channel, but may not be associated with any CALL object (may not make or accept calls). A virtual channel may be a member of one conference, but may not be associated with any CALL object (may not make or accept calls). Many media processing functions can be applied to a channel and many channels can have a media processing function applied to them. 4 10
.1 API Principles Application Development This topic provides the information required to successfully develop a user application using GP. It is organized as follows: API Principles - (pg. 11) provides information on the basic features of GP, such as functions, structures, and configuration files. Design Guidelines - (pg. 13) describes requirements for designing user applications with GP. Basic Functions - (pg. 1) describes the basic functions common to all user applications, such as system start-up, event queues, application logging, timers, application licenses, call processing, switching, conferencing, and media streams. NOTE: Only one user application can be supported by GP on each deployment platform at the same time..1 API Principles GrandPrix comprises: Sets of C function interfaces Structures used by the functions Configuration files GP Functions - Detailed information on purpose, parameters, and return values for each function is provided in the PIKA GrandPrix API Reference. All GP functions have the prefix PKX_. GP functions are broken into groups based on the GP object or processing function they perform. The function groups are: PKX_CALL - Functions to accept incoming calls and to make outgoing calls. PKX_CHANNEL - Functions to connect and disconnect channels (half duplex or full duplex), and to perform media processing functions (such as play, record, tone generation and detection, and digit detection and generation) on a channel. PKX_CONF - Functions to create and destroy conference objects, and to add channels to and remove channels from conferences. PKX_ERROR - A function to translate PK_STATUS error codes from a numeric value to a meaningful text string. PKX_EVENT - A function to translate event identifiers from a numeric value to a meaningful text string. PKX_GROUP - Functions to get group object handles and information about the configuration of the group. PKX_SYSTEM - Functions to allow the user application to control the state of the system object, and to configure, 11
.2 Design Guidelines inject, and retrieve events from the event queue. All functions (except PKX_ERROR_GetText and PKX_EVENT_GetText) return a value of type PK_STATUS. A return value of PK_SUCCESS indicates the function was performed properly. Any other return value indicates an error occurred. PIKA Errors in the PIKA GrandPrix API Reference lists the return values that may be returned from GP functions. All error return values are negative and are in the range of 0X000 to 0XFFF. PKX_ERROR_GetText and PKX_EVENT_GetText return PK_CHAR* pointers to a string, which simplifies using them in string generation functions (for example, printf). When the system object is opened, the configuration files are read and all objects are created. The configuration files define the groups that can be created and the channels that belong to each group. The system object provides the list of the names of the groups defined in the configuration files through the PKX_SYSTEM_GetConfig function. Handles to the group objects can be retrieved by passing the group name to the PKX_GROUP_GetHandle function. Handles to the channels for each group can be retrieved through the PKX_CHANNEL_GetHandle function. The user application may retrieve these handles and determine group types and configurations before calling the PKX_SYSTEM_Start function. The PKX_SYSTEM_Start function starts all call processing. This means that call events may be generated immediately after the PKX_SYSTEM_Start function is called. When a call arrives at the user application, a PKX_EVENT_GROUP_INCOMING_CALL event is generated. The event specifies the group and channel on which the call is arriving as well as the call handle created to manage the call. When initiating a call, the user application may select any unused channel of the appropriate type of group. Two channels can be connected to each other using either the PKX_CHANNEL_HalfDuplexConnect or the PKX_CHANNEL_FullDuplexConnect functions. Channels can be added to a conference through the PKX_CONF_AddMember function. Media processing functions, such as play, record, tone detection, and tone generation, can be applied to channels. GP Structures - Detailed information on the structures used by the functions is provided in the PIKA GrandPrix API Reference. All GP structures have the prefix PKX_T. Information about the base types and constants used in GP is found in Base Types in the PIKA GrandPrix API Reference. GP Configuration Files - Detailed information on the format and contents of the configuration files can be found in the PIKA GrandPrix Configuration Guide. 12
.2 Design Guidelines.2 Design Guidelines User applications should be designed to take into account the asynchronous, real-time nature of typical telephony application and follow best practices coding standards. Asynchronous Applications - To develop an effective application using GP, the design must take into account the asynchronous nature of the GP architecture. Events can be generated at any time. These events reflect significant changes (such as the arrival of an incoming call, calls being disconnected from the other end, or call state change protocol messages being received) on the underlying interface boards. As these events are generated, they are placed, in chronological order, in the event queue. The user application is responsible for retrieving the events from the queue and processing the event. Events are retrieved from the queue in the order in which they were placed in the queue. Real-Time Applications - When designing a media processing application, it is important to consider the real-time aspects of the system, the resource needs of the system, and what other devices and applications will compete for processor resources. If the deployment platform does not have sufficient resources to meet the requirements of the user application and all other applications running on it, the quality of the media processed by the user application may deteriorate. To design user applications, you must take into account: Typical Deployed System Sizes - Tests should be performed to determine the minimum requirements for the applications to be deployed. This allows you to specify system requirements (such as CPU power, memory, and number of threads), ensuring sufficient resources are available for the application to run efficiently. The application may need different configuration specifications for small, medium, or large deployments. Operating System I/O - In a real-time system, it is important to limit the file open, close, read, and write operations. For example, when audio messages and prompts are played often, read and store them into memory at application start. This reduces the file I/O burden on the system during application operation. Memory Management - System calls are very processor intensive. If the application can avoid executing system calls during normal operations, the application uses fewer processor resources. One method of reducing system calls is to create a self-managed memory pool within the application, which is much more efficient than requesting and returning memory to the operating system each time it is required. The user application can create or open sufficient conference objects for typical operation at system start-up. The user application then manages pools of these objects, assigning them as needed. This reduces processing time during peak load application operation. One approach to memory management is to allocate memory and objects at program initialization, based on a typical deployment. As more memory or objects are required, allocate or create them and add them to the pools. This allows the amount of memory in the pool and the number of objects created to grow, ensuring all 13
.3 Basic Functions requirements of the application are met. Another approach to memory management is to create templates for different system deployment sizes (for example: small, medium, and large). Have each template allocate and create sufficient memory and objects for the expected maximum use for the deployment size. Logging - During application development, application logging is an extremely useful tool, however, extensive logging can significantly reduce application performance. When an application is deployed, it should perform a minimal amount of application logging. If more logging information is required to debug field issues, the logging level can be increased as required to isolate the problem. The logging level should be returned to normal once the problem is resolved. If more extensive debugging is required, a debugger can be attached to a deployed application. Where possible, send the debug information to a separate platform. This reduces the effect the debugger has on the processor of the deployed application. Please contact Customer Care (pg. 2) for the symbol files. Competing Resources - Hard drives, NICs, and other third-party devices can heavily load a system. It is important to choose the right devices. It is also important to use a device's native drivers. The default OS drivers for these devices are not as efficient as the native drivers. Backups and virus checkers heavily load a system as well. These applications should be scheduled for off-peak hours and not be run during busy times on a real-time system. Multi-threading and Multi-processor Configurations - To allow the application to take advantage of multi-processor and hyper-threading processor systems, use the following compile option: Windows: In Visual Studio, under Configuration Options / C/C++ / Code Generation, the runtime library "Multi-threaded (/MT)" or "Multi-threaded Debug (/MTd)" should be selected. Coding Guidelines - PIKA Technologies recommends that software developers follow a standard set of coding guidelines. Each of these guidelines helps to produce code easy to understand, debug, and modify. These guidelines become especially important when contacting PIKA Technologies Customer Care department. A properly designed program helps technical support personnel identify problem areas in code, resulting in faster, more efficient technical support. Checking GP Return Status - All API functions return a status of type PK_STATUS. User applications should compare this status to PK_SUCCESS after every API function call. A complete list of API error return status codes can be found in PIKA GrandPrix SDK API Reference - PIKA Errors. Defines and Type Definitions - The API uses a specific set of defines and type definitions for identifying parameters passed to and from functions. These defines and type definitions should be used whenever possible to keep GP-specific code consistent. See PIKA GrandPrix SDK API Reference - Base Types for a complete listing. 14
.3 Basic Functions System Start.3 Basic Functions Basic GP functions can be broken into the following categories: System Start and Shutdown (pg. 1) Event Queue (pg. 21) Application Logging (pg. 24) Call Processing Initiating a Call (pg. 32) Receiving a Call (pg. 4) Joining Calls (pg. 49) Terminating a Call (pg. 7) Skype Calls (pg. 61) Media Processing Playing a Stored Message (pg. 64) Recording Audio Data from a Channel (pg. 71) Collecting DTMF Digits from a Channel (pg. 78) Sending DTMF Digits to a Channel (pg. 83) Generating Tones on a Channel (pg. 83) Detecting Tones on a Channel (pg. 8) Conferencing (pg. 92) Phones (pg. 97).3.1 System Start The first function called when the user application starts must be PKX_SYSTEM_Open function. This function reads the configuration files and creates all the group and channel objects specified by the configuration files. The user application can then retrieve the group object handles using the PKX_SYSTEM_GetConfig and PKX_GROUP_GetHandle functions. The group type and number of channels can be determined using the 1
System Start.3 Basic Functions PKX_GROUP_GetConfig function. The user application typically initializes its own internal structures in anticipation of processing calls. At this point, no media processing can be performed and no events are generated. After the user application is ready to process calls, it calls the PKX_SYSTEM_Start function. PKX_SYSTEM_Start initializes any underlying hardware, starts the call processing message stacks, and makes the media processing function available. Immediately after the PKX_SYSTEM_Start function is called, the user application can receive events and perform media processing. The user application then either initiates calls using the PKX_CALL_Make function or waits for an event using the PKX_SYSTEM_WaitOnEvent function. The following diagram shows the typical flow of processing during the user application start-up. 16
.3 Basic Functions System Start When the user application is shutting down, it should first call the PKX_SYSTEM_Stop function. This terminates all call and media processing within the system. All existing calls are terminated. The user application should then call PKX_SYSTEM_Close as the last function to shut down the PIKA software cleanly. This invalidates all handles, closes all opened low-level resources, and discards any outstanding events. Pending calls to PKX_SYSTEM_WaitOnEvent immediately return the PKX_EVENT_SYSTEM_SHUTDOWN event. Subsequent calls to PKX_SYSTEM_WaitOnEvent fail and return a status of PKX_ERROR_SYSTEM_IS_NOT_ENABLED. A user application can determine the current state of the system object using the PKX_SYSTEM_GetState function. The following table lists the object states returned by this function: Object State Value Returned The object does not exist or has not been opened. PKX_OBJECT_STATE_DISABLED The object has been opened but not started. PKX_OBJECT_STATE_ENABLED The object has been started. PKX_OBJECT_STATE_RUNNING Tips For user applications that do not initiate calls (such as IVR applications), it is not necessary to get the group names and handles at application start-up. The PKX_EVENT_GROUP_INCOMING_CALL event contains the group handle in the event handle field, the channel handle in the event p0 field, and the call handle in the event p1 field. Example This example shows the Initialize and Cleanup functions in ivr.ccp source file of the Interactive Voice Response sample application. The initialization function: Opens the system object Retrieves the group names Retrieves the group handles Retrieves the number of channels in each group Retrieves the channel handles Starts the system object The Cleanup function: 17
System Start.3 Basic Functions Stops the system object Closes the system object.3.1.1 System Start-up Example */ // ---------------------------------------------------------------------------// Initialize the system. This sample works with either MonteCarlo AOB or // AOH resources. By default, the configuration files are set for MonteCarlo // AOB ISDN calls. // ---------------------------------------------------------------------------PK_BOOL Initialize ( IN PK_CHAR *configfile ) { PK_STATUS status; PK_CHAR errortext[pkx_error_max_name_length]; PK_INT i, j; // Open the system using the configuration file passed in. if ((status = PKX_SYSTEM_Open(configFile))!= PK_SUCCESS) { printf("pkx_system_open failed('%s'), status = [%s0x%04x] %sn", configfile, (status < 0? "-" : ""), -status, PKX_ERROR_GetText(status, errortext, sizeof(errortext))); return PK_FALSE; // Retrieve the configuration of the system. This configuration information // includes the names of all groups defined in the configuration files. if ((status = PKX_SYSTEM_GetConfig(&g_System.config))!= PK_SUCCESS) { printf("pkx_system_getconfig() failed, status = [%s0x%04x] %sn", (status < 0? "-" : ""), -status, PKX_ERROR_GetText(status, errortext, sizeof(errortext))); return PK_FALSE; printf("system - Configuration dumpn"); printf(" numberofgroups = %dn", g_system.config.numberofgroups); printf("n"); // Loop over each group configured in the system. for (i = 0; i < g_system.config.numberofgroups; i++) { // Retrieve the group handle. status = PKX_GROUP_GetHandle(g_System.config.groupName[i], &g_system.group[i].handle); 18
.3 Basic Functions System Start if (status!= PK_SUCCESS) { printf("pkx_group_gethandle('%s') failed, status = [%s0x%04x] %sn", g_system.config.groupname[i], (status < 0? "-" : ""), -status, PKX_ERROR_GetText(status, errortext, sizeof(errortext))); return PK_FALSE; // Retrieve the configuration of the group. This configuration information // includes the number and type of channels contained in the group. status = PKX_GROUP_GetConfig(g_System.group[i].handle, &g_system.group[i].config); if (status!= PK_SUCCESS) { printf("pkx_group_getconfig('%s') failed, status = [%s0x%04x] %sn", g_system.config.groupname[i], (status < 0? "-" : ""), -status, PKX_ERROR_GetText(status, errortext, sizeof(errortext))); return PK_FALSE; printf("group %d: '%s' - Configuration dumpn", i, g_system.config.groupname[i]); switch (g_system.group[i].config.type) { case PKX_GROUP_TYPE_SIP: printf(" type break; case PKX_GROUP_TYPE_ISDN: printf(" type break; case PKX_GROUP_TYPE_CAS: printf(" type break; case PKX_GROUP_TYPE_TRUNK: printf(" type break; case PKX_GROUP_TYPE_PHONE: printf(" type break; case PKX_GROUP_TYPE_SKYPE: printf(" type break; case PKX_GROUP_TYPE_VIRTUAL: printf(" type break; default:; printf(" numberofchannels = %dn", g_system.group[i].config.numberofchannels); printf("n"); = sipn"); = isdnn"); = casn"); = trunkn"); = phonen"); = skypen"); = virtualn"); // Loop over all channels in the group. for (j = 0; j < g_system.group[i].config.numberofchannels; j++) { // Retrieve the channel handle. status = PKX_CHANNEL_GetHandle(g_System.group[i].handle, j, &g_system.group[i].channel[j].handle); if (status!= PK_SUCCESS) { printf("pkx_channel_gethandle('%s', %d) failed," " status = [%s0x%04x] %sn", 19
Event Queue.3 Basic Functions g_system.config.groupname[i], j, (status < 0? "-" : ""), -status, PKX_ERROR_GetText(status, errortext, sizeof(errortext))); return PK_FALSE; // All channels are assumed down at the start of the application. g_system.group[i].channel[j].state = PKX_CHANNEL_STATE_DOWN; // Start handling call processing events in the system. if ((status = PKX_SYSTEM_Start())!= PK_SUCCESS) { printf("pkx_system_start() failed, status = [%s0x%04x] %sn", (status < 0? "-" : ""), -status, PKX_ERROR_GetText(status, errortext, sizeof(errortext))); return PK_FALSE; return PK_TRUE; // ---------------------------------------------------------------------------// Cleanup the system. // ---------------------------------------------------------------------------PK_BOOL Cleanup() { PK_STATUS status; PK_CHAR errortext[pkx_error_max_name_length]; // Stop handling call processing events in the system. if ((status = PKX_SYSTEM_Stop())!= PK_SUCCESS) { printf("pkx_system_stop() failed, status = [%s0x%04x] %sn", (status < 0? "-" : ""), -status, PKX_ERROR_GetText(status, errortext, sizeof(errortext))); return PK_FALSE; // // // if Close the system and clean up all resources used. This function will also cause a PKX_EVENT_SYSTEM_SHUTDOWN event to be raised to the EventProcessing function, causing the event handling thread to terminate. ((status = PKX_SYSTEM_Close())!= PK_SUCCESS) { printf("pkx_system_close() failed, status = [%s0x%04x] %sn", (status < 0? "-" : ""), -status, PKX_ERROR_GetText(status, errortext, sizeof(errortext))); return PK_FALSE; return PK_TRUE; /* 20
.3 Basic Functions Event Queue.3.2 Event Queue All GP objects generate events asynchronously. An event is a message about a significant occurrence that happened to the object during its operation. To manage events, GP creates an event queue when the system is started. As events are created, they are placed in the event queue in chronological order. The user application retrieves events from the event queue using the PKX_SYSTEM_WaitOnEvent function. Event information is placed in the application-supplied PKX_TEvent structure. The PKX_TEvent structure returned contains the following information: Event Description Member id The event identifier. See PIKA Events for a description of the event identifiers associated with each type of object. handle The handle of the object that generated the event. This handle can be PK_HANDLE_NONE for an application-injected event, a PKX_EVENT_SYSTEM_WAIT_TIMEOUT event and a PKX_EVENT_SYSTEM_SHUTDOWN event. timestamp The time the event occurred (in milliseconds since the computer was started). This value can be used to determine the relative time between events. userdata The userdata value for the object set through the PKX_SYSTEM_SetEventUserData function. A value of NULL is provided unless the user application has called the PKX_SYSTEM_SetEventUserData function to set a new value for the object generating the event. p0 Event dependent data. See PIKA Events for a description of the data associated with each type of event. p1 Event dependent data. See PIKA Events for a description of the data associated with each type of event. p2 Event dependent data. See PIKA Events for a description of the data associated with each type of event. The timeout parameter provided to the PKX_SYSTEM_WaitOnEvent function determines whether the function blocks until an event is available, returns immediately, or waits for the specified period if no event is available. The following table details the timeout values and under what conditions the PKX_SYSTEM_WaitOnEvent function returns. 21
Event Queue.3 Basic Functions Timeout Value Return Conditions PKX_SYSTEM_QUEUE_NON_BLOCKING The function returns immediately, whether an event is available in the queue or not. If an event is not available, the function returns an event with an identifier of PKX_EVENT_SYSTEM_WAIT_TIMEOUT. PKX_SYSTEM_QUEUE_WAIT_FOREVER If an event is available, the function returns immediately with the event. The function does not return until an event is available. Any other value If an event is available, the function returns immediately with the event. The function does not return until an event is available. If no event is available before the number of milliseconds specified by the timeout value, the function returns an event with an identifier of PKX_EVENT_SYSTEM_WAIT_TIMEOUT. The following diagram shows the AoH thread, AoB thread, and the user application (using the PKX_SYSTEM_InjectEvent function) adding events to the end of the queue as they are generated. The user application retrieves these events (using the PKX_SYSTEM_WaitOnEvent function) from the head of the queue. When events are retrieved from the event queue, they should be checked to determine if the event is a PKX_EVENT_SYSTEM_WAIT_TIMEOUT or PKX_EVENT_SYSTEM_SHUTDOWN event. A PKX_EVENT_SYSTEM_WAIT_TIMEOUT event indicates that no event has been generated in the timeout period. The user application may perform any housekeeping activities and then call the PKX_SYSTEM_WaitOnEvent function again to wait for the next event to occur. The PKX_EVENT_SYSTEM_SHUTDOWN is generated by the 22
.3 Basic Functions Event Queue PKX_SYSTEM_Close GP function and indicates the application is shutting down. No more events are received and no media processing can be performed. GP provides the following additional functions to allow the application to manage the event queue: GP API Function Description PKX_SYSTEM_FlushEvents Discards all events in the system event queue. Events should not be discarded in a normal production system. PKX_SYSTEM_SetEventUserData Sets the userdata field of the PKX_TEvent structure for all events pertaining to the specified object. This function is normally called the first time a new handle is retrieved by the application. PKX_SYSTEM_GetEventUserData Retrieves the application-defined information set in the userdata field of the PKX_TEvent structure for all events pertaining to the specified object. A value of NULL is returned when the user application has not called the PKX_SYSTEM_SetEventUserData function to set a userdata value. PKX_SYSTEM_InjectEvent Allows a user application to raise custom events to their event processing thread. These events are received in the same fashion as any other event. When injecting an event into the event queue, the user application must provide a valid object handle or specify PK_HANDLE_NONE in the PKX_TEvent handle field. When a valid object handle is used, the userdata value for that object is automatically placed in the userdata field of the event. User application defined events should use id values in the range 0x7000 to 0x7FFF. Tips The value for the event identifier specified is not restricted to the values generated by GP objects. This allows the user application to signal special events to the event handler. Injecting events can be used for a number of purposes: Signaling from the main application to the event handler thread Testing application event handling Simulating error conditions Recreating a series of events that cause an application failure Example This example is taken from the EventProcessing function of the faxrecv.cpp file of the Receiving a FAX sample. The 23
Application Logging.3 Basic Functions function waits until an event is available. When an event is received, the event is check to see if it is the shutdown event. When the shutdown event is received, the function exits. Otherwise the function processes the event and then loops back and calls the PKX_SYSTEM_WaitOnEvent function again to wait for the next event..3.2.1 Wait On Event Example */ // Wait for events. PKX_TEvent event; while (PK_TRUE) { status = PKX_SYSTEM_WaitOnEvent(PKX_SYSTEM_QUEUE_WAIT_FOREVER, &event); if (status!= PK_SUCCESS) { printf("pkx_system_waitonevent() failed, status = [%s0x%04x] %sn", (status < 0? "-" : ""), -status, PKX_ERROR_GetText(status, errortext, sizeof(errortext))); break; if (event.id == PKX_EVENT_SYSTEM_SHUTDOWN) break; /*.3.3 Application Logging Logs are used to track the progress of the application and to determine what is happening within the application. GP provides extensive capabilities and flexibility for AoH, AoB, and GP logging for debugging user applications. Log entries can be generated by: API calls (GP, AoH, and AoB) HSP internal media processing engine (AoH) Objects (GP and AoH) DSP (AoB) Internal SIP processing (AoB and AoH) Internal Skype processing (AoH) Internal ISDN processing (AoB and AoH) Internal CAS processing (AoB) Internal objects (GP and AoH) Events (AoB and AoH) 24
.3 Basic Functions Application Logging License manager (AoB) The user application GP controls which log messages are generated for itself and the AoH or AoB components. Logging for each component can be configured separately. See the PIKA GrandPrix Configuration Guide for more information on how to configure the generated log messages. Tips Care should be taken to log only information necessary to determine that the application is performing correctly..3.3.1 Log File Management Managing the log files refers to controlling the location, size, and number of log files generated by the application. These items are controlled by the environment variable PKX_LOGS_DIR, and entries in the root and product configuration files (Default: pikagp.cfg and product(aob/aoh).cfg), see the PIKA GrandPrix Configuration Guide for more information. The size and number of log files determine the amount of disk space consumed by the logs. Log File Names - The format of log file names is: pikagp_#.log, where # is the log sequence number. The sequence numbers start at one and are incremented by one for each new file. Log File Location - GP log files are placed in the directory specified in the PKX_LOGS_DIR environment variable (default: Windows - C:\Program Files\PIKA\grandprix\logs\; Linux - /var/log/pika) under a separate sub-folder for each run of the application. The format of the sub-folders name is: gp_<date>_<time in 24 hour format> Log files generated by AoH and AoB are placed in separate directories. Refer to AoH and AoB documentation, available at www.pikatechnologies.com. The timestamps on the log messages are used to coordinate log entries of the GP, AoH, and AoB components. Log File Size - The size of each log file is controlled by the size=key (default: 12 M) in the log settings section of the 2
Application Logging.3 Basic Functions root and product configuration files. When a log file grows to be larger than the size specified, the log file is closed. A new log file, with the log number incremented, is opened. New log entries are recorded in the new log file. Number of Log Files - When opening a new log file causes the number of log files in the current log directory to exceed the maximum number of log files specified by the files=key (default: 2) in the log settings section of the product configuration file (product.cfg), the oldest log file is deleted. Example Configuration files, log number, and size examples: pikagp.cfg - The following key values generate five 20 MB GP logs. When the sixth file is opened, the first file generated is deleted. [logs] files= size=20 product_aob.cfg - The following key values generate ten 10 MB AoB logs. When the eleventh file is opened, the first file generated is deleted. [logs] files=10 size=10 wrap=yes product_aoh.cfg - The following key values generate two 100 MB AoH logs. When the third file is opened, the first file generated is deleted. [logs] files=2 size=100 File name examples: 26
.3 Basic Functions Application Logging C:\Program Files\PIKA\grandprix\logs\gp_060327_14213\pikagp_2.log C:\Program Files\PIKA\grandprix\logs\gp_060327_14213\pikagp_3.log.3.3.2 User Application Logging GP provides a mechanism to allow the programmer to log messages to the log file from code outside the GP libraries. The function PKX_SYSTEM_LogUserMessage is used to add messages to the PIKA system log file. Each call to the PKX_SYSTEM_LogUserMessage function specifies the following information: Log message type Log level Log message format string Optional log message parameters Log Message Type - The log message type determines how the message is constructed. Normal messages start on a new line and have a header that contains a date and time stamp and thread id prefixed to the message text. The following table lists the different message types and how the log message is constructed for each type. Log Message Type Message Construction PKX_LOG_TYPE_NORMAL Start the log message with the standard log prefix (new line, time and date stamp, thread id). PKX_LOG_TYPE_INDENT Start the log message on a new line without a timestamp. PKX_LOG_TYPE_CONTINUE Display the log message without the standard prefix. This is normally used to continue adding information to an existing log message. Log Level - This bitmap assigns a user-defined numerical value from 1 to 31 to the log. This value is a means to filter the logs output by the user application. The bits set in the bitmap and the value of the level parameter under the [logs] section in the root configuration file determine which logs are output. If the level parameter in the configuration file is set to brief, only user logs with levels 1 or 2 are output (0x00000001 or 0x00000010). If level is set to debug, all user logs are output. 27
Call Processing.3 Basic Functions Log Message Format String and Parameters - The log message format string and optional parameters follow the same rules as printf. If parameters follow the format string, the format string must contain printf-style format specifications that determine the output format for each parameter. NOTE: No "\n" is required at the end of the string. Log messages (other than PKX_LOG_TYPE_CONTINUE log messages) automatically start on a new line. Log messages are flushed to the file immediately after being written. Example PK_STATUS status; PK_CHAR errorstring[max_string_length]; if ((status = PKX_SYSTEM_LogUserMessage(PKX_LOG_ALL_ERROR, PKX_LOG_TYPE_NORMAL, "Invalid user option entered: %s.",user_option))!= PK_SUCCESS) cout << "\nuser log call failed." << PKX_ERROR_GetText(status,errorString,sizeof(errorString)) << endl; if ((status = PKX_SYSTEM_LogUserMessage(PKX_LOG_ALL_ERROR, PKX_LOG_TYPE_CONTINUE, "This line is appended to the last log message"))!= PK_SUCCESS) cout << "\nuser log call failed." << PKX_ERROR_GetText(status,errorString,sizeof(errorString)) << endl; if ((status = PKX_SYSTEM_LogUserMessage(PKX_LOG_ALL_ERROR, PKX_LOG_TYPE_INDENT, "This line starts on a new line without a time stamp"))!= PK_SUCCESS) cout << "\nuser log call failed." << PKX_ERROR_GetText(status,errorString,sizeof(errorString)) << endl;.3.4 Call Processing Call processing comprises: Initiating a call (pg. 32) Receiving a call (pg. 4) Joining calls (pg. 49) Terminating a call (pg. 7) Two of the key features GP provides are call progress and call analysis. Call progress defines the meaning of tone patterns (such as, ringing, busy, fastbusy) received from remote devices. Refer to the Call Progress section of the GP Configuration Guide for information about configuring call progress tones. Call analysis detects what answered the call 28
.3 Basic Functions Call Processing (live person, answering machine, modem, FAX, or SIT message). When a call progress signal is detected, an event is generated and placed in the queue. Refer to section Call Analysis (pg. 36). Call States As a call is being made or received, it goes through a number of states. The user application can determine the current state of a call using the PKX_CALL_GetState function. This function can be used at any time during the existence of a call. The state parameter is set to PKX_CALL_STATE_IDLE when the call object no longer exists, and the PKX_ERROR_OBJECT_INVALID_HANDLE error is returned. The following table lists the call states that can be returned and are defined in enumerated type PKX_TCallState. Call State Description PKX_CALL_STATE_IDLE Call is idle or non-existent. PKX_CALL_STATE_DIALING Outgoing call is dialing using the specified address information. PKX_CALL_STATE_PROCEEDING Outgoing call has transmitted all necessary address information. PKX_CALL_STATE_ALERTING Incoming or outgoing call is alerting (ringing). PKX_CALL_STATE_OFFERED Incoming call is being offered to the user application. PKX_CALL_STATE_CONNECTED Incoming or outgoing call is connected. PKX_CALL_STATE_DISCONNECTED Incoming or outgoing call is disconnected. PKX_CALL_STATE_INITIATED An outgoing call attempt has started. The following diagrams show the call state machine for outgoing and incoming calls. Call state transitions can be caused by: Function calls (for example: PKX_CALL_Drop()) Actions of the remote device (for example: Remote reject) Actions of the lower-level components (for example: Low-level or protocol resources released) The cause of each state transition is shown in blue. When a call enters some states, events can be generated. The events that can be generated when the call enters a state are shown in red. When a call enters the Idle state, a PKX_EVENT_CALL_DISCONNECTED event is generated if the remote device caused the disconnection, or a PKX_EVENT_CALL_DROPPED event is generated if the user application disconnected the call using the PKX_CALL_Drop function. The NULL state indicates the call does not exist and does not have a valid handle. A call is initiated (and has a state) by 29
Call Processing.3 Basic Functions the user application calling the PKX_CALL_Make or PKX_CALL_Transfer function, or a call is detected by the lower-level components. The call transitions to PKX_CALL_STATE_DIALING shortly after passing through PKX_CALL_STATE_INITIATED. The call handle is provided in the PKX_EVENT_GROUP_INCOMING_CALL event. The PKX_CALL_Release function releases the call and invalidates the call handle. 30
.3 Basic Functions Call Processing The PKX_EVENT_CHANNEL_IN_USE event is only generated by the Offered state if the call has gone from the NULL state to the Offered state directly, without passing through the Detected state. The PKX_EVENT_CHANNEL_READY event is only generated by the NULL state if the call was rejected. The PKX_CALL_Release function does not actually change the state of the call but rather destroys the call object, invalidating the call handle. Channel States Channels can be in one of the following states: Channel State Description PKX_CHANNEL_STATE_DOWN Channel is out-of-service and not available for initiating or receiving calls. 31
Call Processing.3 Basic Functions PKX_CHANNEL_STATE_READY Channel is in-service and available for initiating or receiving calls. PKX_CHANNEL_STATE_IN_USE Channel is in-service and in use by an active call. When a channel changes state, an event is generated indicating its new state. The following diagram shows the channel states, the events generated for each state (in red) and the actions (in blue) that caused the channel to change state. The lower level components move a channel into and out of the Down state. The user application cannot place a channel in or remove a channel from the Down state. A channel in the Down state cannot be used to make a call..3.4.1 Initiating a Call The user application calls the PKX_CALL_Make function. The following diagram shows the typical processing flow when a call is initiated: 32
.3 Basic Functions Call Processing The information that must be specified when initiating a call is channelhandle, info, and settings. channelhandle The handle of the channel on which to make the call. Channel handles may be retrieved using the PKX_CHANNEL_GetHandle function. info The following information should be supplied in the PKX_TCallInfo structure when placing the call: to - called party identification from - calling party identification display - calling party display information callingnumberrestricted - a flag indicating to the remote party that they are not authorized to view the calling party information; as opposed to the information is simply not available forwardedfrom - indicates the party that forwarded the call to the current destination custom - custom call settings, not applicable to all channel types 33
Call Processing.3 Basic Functions The format of the called and calling number or identification depends on the channel group type. Refer to Called and Calling Number Formats (pg. 40). NOTE: The far end may ignore calling number and caller identification depending on the protocol used and the terminating device. settings Settings that affect call behavior: timeout - The amount of time (in milliseconds) to wait for the remote end to answer the call. If the call is not answered within the timeout period, the call is dropped and a PKX_EVENT_CALL_DISCONNECTED event is generated with a disconnected reason of PKX_CALL_DROP_CAUSE_NOANSWER. callanalysis - Specifies the call analysis parameters to use for detection: enable - indicates whether call analysis should be enabled for the call. type - specifies the analysis to perform to determine who/what answered the call: person, answering machine, fax, modem, or SIT message. This value may be ORed combinations of the call analysis detect constants or PKX_CALL_ANALYSIS_DETECT_SPEECH (default). The table in section Call Analysis (pg. 36) lists the events generated each type entity answers the call. speechdebounceon - minimum time (in milliseconds) of continuous speech before a sound segment is recognized as speech. Filters out short clicks, tones, and noise. [30 to 300 ms; default: 20 ms] speechdebounceoff - minimum time (in milliseconds) specified to filter out short periods of time where no speech is detected, for example, a short pause between words. Only if speech is not detected for longer than speechdebounceoff, is an end of speech segment declared. [30 to 300 ms; default: 20 ms] livepersonwords - maximum number of live person words. A larger number of words is considered to come from an answering machine. [1 to 10; default: 3] maxduration - maximum time (in milliseconds) to wait before terminating the attempt to identify the specified analysis type [default: 2000 ms] speechendtime - maximum silence time (in milliseconds) after speech for call analysis to determine if the response came from a live person or answering machine. [00 to 3000 ms; default: 100 ms] livepersonmaxtime - maximum duration (in milliseconds) of a speech segment for a live person response. A longer speech segment is considered to come from an answering machine. [00 to 3000 ms; default: 200 ms] Refer to the section Call Analysis (pg. 36) for information on how the parameters are used. The PKX_CALL_Make function returns immediately. At this point, the call has not been made but the processing required to make the call proceeds in another thread. As the call progresses, the user application asynchronously receives call events indicating the call progress. The following table lists the call events the user application may receive after calling the PKX_CALL_Make function. 34
.3 Basic Functions Call Processing Call Event Indicates PKX_EVENT_CALL_DIALING dialing has started. PKX_EVENT_CALL_PROCEEDING dialing has successfully completed PKX_EVENT_CALL_ALERTING remote device has begun alerting the called party. PKX_EVENT_CALL_ANALYSIS_DETECTED_ANSWERING_MACHINE call was answered by an answering machine. PKX_EVENT_CALL_ANALYSIS_DETECTED_LIVE_PERSON call was answered by a live person. PKX_EVENT_CALL_ANALYSIS_DETECTED_MODEM_FAX call was answered by either a modem or fax machine. PKX_EVENT_CALL_ANALYSIS_DETECTED_SILENCE call was answered, but no audio is present PKX_EVENT_CALL_ANALYSIS_DETECTED_SIT_MESSAGE call was answered by a SIT message: non-standard, no circuit, operator intercept, vacant circuit, or system busy, and is determined by the p1 field in the event. PKX_EVENT_CALL_ANALYSIS_DETECTED_UNKNOWN call was answered but none of the analysis types enabled for the call matched the audio received PKX_EVENT_CALL_CONNECTED called party has answered the call. PKX_EVENT_CALL_DISCONNECTED call has been terminated. The p1 field of the event contains the reason the call was terminated. PKX_EVENT_CALL_HELD call has been put on hold by a remote switch as part of a call transfer. PKX_EVENT_CALL_RESUMED call placed on hold as part of a call transfer has been resumed. The following table lists the reasons a call may be disconnected. 3
Call Processing.3 Basic Functions Call Disconnected Reason Description PKX_CALL_DROP_CAUSE_NORMAL The remote end has dropped the call in a normal fashion (hung up). PKX_CALL_DROP_CAUSE_BUSY The remote end is busy and cannot respond to the call attempt. PKX_CALL_DROP_CAUSE_FASTBUSY An error in routing the call has occurred, resulting in a fast busy tone being received from the remote end. PKX_CALL_DROP_CAUSE_REORDER An error in routing the call has occurred, resulting in a re-order tone being received from the remote end. PKX_CALL_DROP_CAUSE_NOANSWER The remote end did not answer the call within the timeout specified. PKX_CALL_DROP_CAUSE_NODIALTONE No dial tone was present on the line when the call was attempted. PKX_CALL_DROP_CAUSE_RESET The call has been reset due to the channel going down or the reset command being issued. PKX_CALL_DROP_CAUSE_TRANSFER The call has been transferred to the remote switch. PKX_CALL_DROP_CAUSE_FAILED The call has been dropped because the bearer path was not established. If the PKX_CALL_Make call specifies a channel in use (possibly the channel was used by an incoming call and that call's PKX_EVENT_GROUP_INCOMING_CALL has not yet been retrieved from the event queue), the user application receives a PKX_EVENT_CALL_TASK_FAILED event with PKX_ERROR_CHANNEL_ALREADY_IN_USE specified in the p1 field of the event..3.4.1.1 Call Analysis Call analysis is the process used to determine who/what has answered the call: live person, answering machine, fax/modem, or Special Information Tone (SIT) message. Call analysis is based on the speech response duration to determine whether a live person or an answering machine answered the call, and tone detection to determine whether a fax/modem or SIT message answered the call. When using call analysis, the detection of a live person will always be enabled. Some speech analysis application examples are: Telemarketing and outbound call centers: connecting an agent to a call only if a live person answers the call. Some centers also wish to differentiate between business and residential phones, only connecting for a residential live person. Voice messaging: playing a prerecorded message to live persons and answering machines, but not fax machines. 36
.3 Basic Functions Call Processing The following table shows some examples of how speech response durations affect the decision: live responses from home/cell phones are short words or phrases with relatively long periods of silence between them, answering machine responses are typically one or more sentences with a few short periods of silence between them, and live responses from business phones fall somewhere between the two. Response Usually Indicates One short word: Hello? live person on a home/cell phone Short burst word/sentences: Hello? Who is this? Hello? live person on a home/cell phone Short burst sentences: PIKA Technologies. How can I help you? live person on a business phone One long sentence: Good morning, this is PIKA Technologies. live person on a business phone One long sentence: You have reached the main office of PIKA Technologies, please leave a message. answering machine More than one long sentence: Welcome to PIKA Technologies. If you know the extension of the person you wish to speak to, enter it now. If you wish to access the directory, press 1 now. If you wish. answering machine One short sentence: Leave a message. or You know what to do. answering machine NOTE: The business phone long response is very similar to an answering machine response; an answering machine with one short sentence is very much like a live person. Debounce is used to remove speech detection glitches, and filter speech segments from clicks, ringback tones, noise, etc. The parameters used to configure debounce are speechdebounceon and speechdebounceoff. Speech ON and OFF segments, after debounce, are processed according to livepersonmaxtime, speechendtime, and livepersonwords. The maxduration paremeter specifies the amount of time to allow before ending the attempt to detect the specified analysis type. If this time expires and no audio was detected, the PKX_EVENT_CALL_ANAYLSIS_DETECTED_SILENCE event will be raised. If audio was detected, but did not match the pattern specified in the type field, the PKX_EVENT_CALL_ANALYSIS_DETECTED_UNKNOWN event will be raised. If speech is detected and the length of speech after debounce is within specified limits, a live person is assumed to have answered the phone. The following illustration demonstrates how the parameters are used. 37
Call Processing.3 Basic Functions Tone detection detects a fax, modem, or SIT message. SIT messages are prerecorded messages played by Telcos indicating a problem handling a call request. Each SIT message is preceded by a sequence of three special tones that are recognized by the call-processing algorithm. The following illustration shows how the tones are processed to determine whether a SIT message was received and which message it is. 38
.3 Basic Functions Call Processing Applications may be set up to delete numbers not in service from the database, or move a busy number to the bottom of the queue to try again. SIT message types and the corresponding GP messages (indicated by the p1 field in the event) are described in the following table. SIT Message Indicates GP Message Non-standard A user-defined message. The incoming SITs are PKX_CALL_ANALYSIS_SIT_MESSAGE_USER coded in hexadecimal by multiplying the first detected SIT id by 100 (hex), the second SIT id by 10 (hex), and the third SIT id by 1 (hex). The three results are added and returned as the p2 field in the event. Constants can be defined for non-standard SIT messages and assigned to corresponding p2 values. 39
Call Processing.3 Basic Functions No Circuit There is a failure to find a trunk or calls affected PKX_CALL_ANALYSIS_SIT_MESSAGE_NO_ by network management controls. Try again CIRCUIT later. Operator Intercept The number has been disconnected, changed, PKX_CALL_ANALYSIS_SIT_MESSAGE_OPE temporarily suspended, has incoming call RATOR_INTERCEPT restrictions, etc. An announcement specifies the reason and gives instructions. Vacant Circuit The number dialed is not currently assigned to a PKX_CALL_ANALYSIS_SIT_MESSAGE_VACA customer. An announcement specifies the NT_CIRCUIT reason and gives instructions. For example, "The number you have dialed is not in service." System Busy (ReOrder) There is congestion in the network. An announcement specifies the reason and gives instructions. For example, "All circuits are currently busy, please hang up and try your call again." PKX_CALL_ANALYSIS_SIT_MESSAGE_SYST EM_BUSY.3.4.1.2 Called and Calling Number Formats ISDN, CAS, and Trunk Channels For calls made on channels controlled by groups of type isdn, cas, trunk, or phone, the format of the calling and called numbers consists of a string containing only the characters: 0 to 9, A to D, *, #. Trunks allow the following additional special characters to be inserted into the string: Special Meaning Trunk Character 40 P Use pulse dialing to transmit the remainder of the string. T Use tone dialing to transmit the remainder of the string. W Wait for dial tone to be received before dialing the remainder of the string. & Transmit a hook flash on the trunk.
.3 Basic Functions! Ground the tip and ring for ground start lines. This is typically used to trigger the remote switch to generate dial-tone., Pause for one second. Call Processing The user application should insert a "!w" at the beginning of the analog trunk dial string for Ground Start Lines and a "w" at the beginning of the analog trunk dial string for Loop Start Lines. ISDN Channels Additional information can be specified in the calling and called party number for ISDN calls. This may be useful, for example, if the information for the calling and called party are different. The additional fields are separated by a " " in the value. For any of the fields listed below, a hexadecimal value may be specified in the form of "0xXXXXXXXX" to use a value other than those provided. Both the calling and called party fields may specify the type of number and the numbering plan. The type of number is specified as numbertype=<value>. The valid values are: "unknown" "international" "national" "network" "subscriber" "abbreviated" The default value is defined by the "numbertype" ISDN configuration parameter or "unknown" if not present. The numbering plan is specified as numberplan=<value>.the valid values are: "unknown" "isdn" "data" "telex" "standard" 41
Call Processing.3 Basic Functions "private" The default value is defined by the "numberplan" ISDN configuration parameter or "unknown" if not present. The numbering plan is normally ignored if the type of number field is set to a value other than "unknown", "international", "national", or "subscriber". However, no restriction is enforced. In addition to the type of number and the numbering plan information, the value for the calling number may also include screening information and presentation indicator information. The screening value is specified as screening=<value>. The valid values are: "user" "passed" "failed" "network" Presentation indicator information is specified as presentation=<value>. The valid values are: "allowed" "restricted" "notavailable" A value in this field, if present, will override the callingnumberrestricted field. The "custom" field in the PKX_TCallInfo structure can be used to supply custom call information. Currently it is used only for establishing outgoing ISDN calls. The default bearer capability for ISDN calls is speech. The "custom" field can be used to specify alternate bearer capability information. The field is specified as "bearercap=<value>". In addition to the valid values below, a hexadecimal value may be specified in the form of "0xXXXXXXXX" to use a value other than those provided. speech unrestricted restricted 3.1 tones video The following example shows how the additional fields may be specified when setting the information required to 42
.3 Basic Functions Call Processing initiate a call. PKX_TCallInfo info; memset(&info, 0, sizeof(pkx_tcallinfo)); snprintf(info.to, PKX_CALL_MAX_INFO_LENGTH, "%s numbertype=national numberplan=isdn", callednumber); snprintf(info.from, PKX_CALL_MAX_INFO_LENGTH, "%s numbertype=national numberplan=abbreviated screening=user presentation=all owed", callingnumber); snprintf(info.display, PKX_CALL_MAX_INFO_LENGTH, "%s", callingname); snprintf(info.custom, PKX_CALL_MAX_INFO_LENGTH, "bearercap=unrestricted"); SIP Channels For calls made on channels controlled by SIP groups, the format of the calling and called numbers resembles an email address. For example: john_doe@sip_provider.com, john_doe@sip_provider.com:062 or 192.63.78.2. Skype Channels For calls made on channels controlled by Skype groups, the format of the calling and called numbers is either the Skype handle of the user or, for SkypeOut calls, the phone number preceeded by a + character. SkypeOut is the ability to call a phone number on the PSTN network from a Skype client. SkypeOut credits are available from Skype..3.4.1.3 Call Initiation Examples Example The first example is taken from the initialize function in msgblast.ccp of the Message Distribution sample application and sets up the caller information used for all outgoing calls. The second example is taken from the getnextphonenumber function in the same source file and demonstrates how to make an outgoing call using the PIKA GrandPrix SDK. The number to call is retrieved from a file and inserted into call information structure..3.4.1.3.1 Initiating a Call Setup Example */ // Fill in the calling party location information. strncpy(g_system.callinfo.from, MSGBLAST_SAMPLE_CALLING_NUMBER, PKX_CALL_MAX_INFO_LENGTH); g_system.callinfo.from[pkx_call_max_info_length - 1] = '0'; // Fill in the calling party display information. Not all protocols will // pass this information. 43
Call Processing.3 Basic Functions strncpy(g_system.callinfo.display, MSGBLAST_SAMPLE_CALLING_NAME, PKX_CALL_MAX_INFO_LENGTH); g_system.callinfo.display[pkx_call_max_info_length - 1] = '0'; /*.3.4.1.3.2 Initiating a Call Example */ PKX_TCallSettings callsettings; memset(&callsettings, 0, sizeof(pkx_tcallsettings)); callsettings.timeout = MSGBLAST_SAMPLE_MAKE_TIMEOUT; // Check for all types of answering devices. callsettings.callanalysis.enable = PK_TRUE; callsettings.callanalysis.type = PKX_CALL_ANALYSIS_DETECT_FAX PKX_CALL_ANALYSIS_DETECT_MODEM PKX_CALL_ANALYSIS_DETECT_ANSWERING_MACHIN E PKX_CALL_ANALYSIS_DETECT_SPEECH PKX_CALL_ANALYSIS_DETECT_SIT_MESSAGES; // Configure the analysis parameters for a standard residential environment. // To qualify for a live person answering, a maximum of 3 speech segments of // no more than 2. seconds each is allowed. The last speech segment will be // declared if 1. seconds of silence has been observed. Within a speech // segement, a maximum silence period of 20 milliseconds between words or // sylables is allowed. Bursts of noise or speech of less than 20 // milliseconds is ignored. callsettings.callanalysis.livepersonmaxtime = 200; callsettings.callanalysis.livepersonwords = 3; callsettings.callanalysis.speechdebounceoff = 20; callsettings.callanalysis.speechdebounceon = 20; callsettings.callanalysis.speechendtime = 100; // Retrieve the next phone number and place it in the outgoing call info. memset(g_system.callinfo.to, 0, sizeof(g_system.callinfo.to)); if (!getnextphonenumber(g_system.group[groupid].config.type, g_system.callinfo.to)) { return PK_TRUE; // Make a call to the returned address. status = PKX_CALL_Make(channelHandle, &g_system.callinfo, &callsettings, &g_system.group[groupid].call[channelid].handle); if (status!= PK_SUCCESS) { printf("pkx_call_make(0x%08x) failed, status = [%s0x%04x] %sn", (PK_UINT)channelHandle, (status < 0? "-" : ""), -status, 44
.3 Basic Functions Call Processing PKX_ERROR_GetText(status, errortext, sizeof(errortext))); return PK_FALSE; /*.3.4.2 Receiving a Call When an incoming call arrives, the user application receives a PKX_EVENT_GROUP_INCOMING_CALL event. The handle of the group receiving the call is specified in the event handle field. The handle of the channel on which the call was received is specified in the p0 field. The handle of the object created to represent the call is specified in the p1 field. The user application then calls the PKX_CALL_GetInfo function which returns the call information (PKX_TCallInfo), including the called address and calling identification information. The user application uses this information to determine who is calling and who they are attempting to call. The PKX_TCallInfo structure contains the following: to - the called number or identification from - the calling number or identification display - caller identification information callingnumberrestricted - if set to PK_TRUE, the calling number information has been restricted by the remote party forwardedfrom - indicates the party that forwarded the call to the current destination party custom - custom ISDN call setting used to specify bearer capability information When the call is destined for a device other than the user application, the PKX_CALL_Accept function should be called to indicate the user application is attempting to reach the called party. The PKX_CALL_Accept function returns immediately, while lower level processes send the appropriate accept message to the calling party. When the accept message has been sent, the user application receives a PKX_EVENT_CALL_ACCEPTED event. If the user application does not wish to accept the call or doesn't know how to route the call, it can reject the call by calling the PKX_CALL_Reject function. When the called party answers the call, the user application calls the PKX_CALL_Answer function. The PKX_CALL_Answer function returns immediately while lower-level processes send the appropriate answer message to 4
Call Processing.3 Basic Functions the calling party. When the answer message is acknowledged and the call is established, the user application receives a PKX_EVENT_CALL_ANSWERED event. Billing at the Telco normally starts when a call is answered. When the user application is the called party (such as an IVR application), the user application does not have to accept the call before answering it. The following diagrams show the typical processing flow for handling incoming calls. The diagram below shows the process flow when the call must be routed by the user application to another device. The user application accepts the call and makes a call to the destination. When the destination indicates that alerting has started, a one-way voice path from the called party to the calling party is made to provide the audio path for alerting tones being received from the destination to the original caller. When the destination answers, both channels of the calls are connected. The following diagram shows the process flow when the user application answers the call. In this case, the call is answered immediately, without going through the call accept process. When the call answered event (PKX_EVENT_CALL_ANSWERED) is received, processing is performed on the channels of the call. 46
.3 Basic Functions Call Processing Example This example is taken from the EventProcessing function in faxrecv.ccp of the Receiving a FAX sample application. It demonstrates the processing of the events received during an incoming call. When the PKX_EVENT_GROUP_INCOMING_CALL event is received, the application retrieves the call information and accepts the call. When the PKX_EVENT_CALL_ACCEPTED event is received, the application answers the call. When the PKX_EVENT_CALL_ANSWERED event is received, the channel is ready to receive or transmit audio data. The channel can be joined with another channel or, as is the case in this application, processed as an incoming FAX..3.4.2.1 Incoming Call Example */ case PKX_EVENT_GROUP_INCOMING_CALL: { printf("group 0x%08x: <-- %sn", (PK_UINT)event.handle, PKX_EVENT_GetText(event.id, eventtext, sizeof(eventtext))); TPikaHandle channelhandle = (TPikaHandle)event.p0; TPikaHandle callhandle = (TPikaHandle)event.p1; // Retrieve the call information and determine if this application will // handle the call. In this example, all incoming calls will be // handled. PKX_TCallInfo callinfo; if ((status = PKX_CALL_GetInfo(callHandle, &callinfo))!= PK_SUCCESS) 47
Call Processing.3 Basic Functions { printf("pkx_call_getinfo(0x%08x) failed, status = [%s0x%04x] %sn", (PK_UINT)callHandle, (status < 0? "-" : ""), -status, PKX_ERROR_GetText(status, errortext, sizeof(errortext))); break; printf(" printf(" printf(" Info: to from display [%s]n", callinfo.to); [%s]n", callinfo.from); [%s]n", callinfo.display); // Retrieve the indexes into the global data structure where the // channel information is stored. if (FindChannel(event.handle, channelhandle, &groupid, &channelid)) { // Save the call information in the call array at the same index. g_system.group[groupid].call[channelid].handle = callhandle; // Accept the incoming call. This means that the application has // decided to process the incoming call. If this is the final // destination for this call (e.g. IVR server, FAX receiver), you could // immediately answer the call here with the PKX_CALL_Answer function. if ((status = PKX_CALL_Accept(callHandle))!= PK_SUCCESS) { printf("pkx_call_accept(0x%08x) failed, status = [%s0x%04x] %sn", (PK_UINT)callHandle, (status < 0? "-" : ""), -status, PKX_ERROR_GetText(status, errortext, sizeof(errortext))); break; printf("call 0x%08x: --> ACCEPTn", (PK_UINT)callHandle); break; case PKX_EVENT_CALL_ACCEPTED: { printf("call 0x%08x: <-- %sn", (PK_UINT)event.handle, PKX_EVENT_GetText(event.id, eventtext, sizeof(eventtext))); // Answer the call now that it has been accepted. if ((status = PKX_CALL_Answer(event.handle))!= PK_SUCCESS) { printf("pkx_call_answer(0x%08x) failed, status = [%s0x%04x] %sn", (PK_UINT)event.handle, (status < 0? "-" : ""), -status, PKX_ERROR_GetText(status, errortext, sizeof(errortext))); break; printf("call 0x%08x: --> ANSWERn", (PK_UINT)event.handle); break; case PKX_EVENT_CALL_ANSWERED: 48
.3 Basic Functions Call Processing { printf("call 0x%08x: <-- %sn", (PK_UINT)event.handle, PKX_EVENT_GetText(event.id, eventtext, sizeof(eventtext))); TPikaHandle channelhandle = (TPikaHandle)event.p0; // Retrieve the indexes into the global data structure where the // channel information is stored. if (FindChannel(PK_HANDLE_NONE, channelhandle, &groupid, &channelid)) { // Receive an incoming fax on the channel. if (!recvfax(groupid, channelid)) cleanupfax(groupid, channelid); break; /*.3.4.3 Joining Calls GP provides the following functions to connect and disconnect channels involved in calls. These functions return immediately, before the channels are connected or disconnected. The user application receives the corresponding event when the channels have been connected or disconnected. GP API Function Description Corresponding Event PKX_CHANNEL_ This function takes two channel handles as input parameters. The media received on the first channel is sent to the second channel and the media received on the second channel is sent to the first channel. PKX_EVENT_CHANNEL_FULL_ FullDuplexConnect PKX_CHANNEL_ DUPLEX_CONNECT This function takes two channel handles as input FullDuplexDisconnect parameters and disconnects the media path between the two channels. Both directions of the media path are disconnected. PKX_EVENT_CHANNEL_FULL_ PKX_CHANNEL_ PKX_EVENT_CHANNEL_HALF_ HalfDuplexConnect PKX_CHANNEL_ This function takes two channel handles as input parameters. The media received on the first channel is sent to the second channel. This function takes two channel handles as input HalfDuplexDisconnect parameters and disconnects the media path from the first channel to the second channel. When used on a full-duplex connection, the media path from the second channel to the first channel is unaffected. DUPLEX_DISCONNECT DUPLEX_CONNECT PKX_EVENT_CHANNEL_HALF_ DUPLEX_DISCONNECT If a connect or disconnect function fails, a PKX_EVENT_CHANNEL_TASK_FAILED event is generated. The 49
Call Processing.3 Basic Functions channel on which the failure occurred is identified in the event handle field. The event p1 field contains the error code of the failure. The following table lists the error codes that may be returned: Error Code Description PKX_ERROR_CHANNEL_ALREADY_CONNECTED The channel is already connected to another channel. PKX_ERROR_CHANNEL_INVALID_REMOTE_HANDLE The remote handle does not refer to a channel present in the system. PKX_ERROR_CHANNEL_NOT_CONNECTED A disconnect has been issued for this channel and the channel is not connected. PKX_ERROR_CHANNEL_INVALID_CONNECTION_TYPE A full duplex disconnect function has been issued on a half duplex connection. Echo Cancellation Echo cancellation is automatically applied when connecting an RTP channel to a TDM channel using the PKX_CHANNEL_FullDuplexConnect function. If other configurations of echo cancellation are required by the user application, the bypass (pg. 113) feature must be used. When echo cancellation is enabled, there is a potential delay due to the distance between the echo canceller and the echo source, or tail. Delays can be fixed by setting a value for this tail for the RTP channel. See the parameter taillength under SIP Resources in the PIKA GrandPrix Configuration Guide for more information on the value range and default..3.4.4 Call Transfer Call transfer applies to Trunks only. Transferring a call involves: 1. Establishing a first call. 2. Having a remote switch place the first call on hold. 3. Establishing a second call. 4. Having the remote switch connect the first and second called parties and remove the person initiating the transfer from the circuit. 0
.3 Basic Functions Call Processing The following diagram shows the steps in transferring a call: The remote switch must be provisioned with the appropriate call transfer service to allow this feature to operate. To configure a trunk to allow GP to perform call transfers, the transfer key in the trunk parameters section of the product configuration file is set to yes. Some remote switches require a second hookflash to complete the transfer. If the switch does require the second hookflash, the transfer_extrahf key in the trunk parameters section of the product configuration file is set to yes. Transfers may be supervised, where the person initiating the transfer converses with the second called party before transferring the call. Transfers may also be performed blindly where the person initiating the transfer, transfers the call when the call to the second party is ringing. 1
Call Processing.3 Basic Functions To transfer a call using GP, the user application requires an established call (or first call). The first call can be either an incoming or outgoing call. After the first call has been established, the user application calls the PKX_CALL_Transfer function to transfer the call to a second called party. The PKX_CALL_Transfer function is passed the handle of the first call, and the call information for the second called party. The first call is placed on hold by the remote switch and the PKX_CALL_Transfer function returns the handle of the second call. After the second call has been established to at least the PKX_CALL_STATE_PROCEEDING state, indicated by the PKX_EVENT_CALL_PROCEEDING event, the call can be transferred by calling the PKX_CALL_Drop function, passing it the handle of the second call and providing a cause of PKX_CALL_DROP_CAUSE_TRANSFER. After the transfer process is started, the user application receives the following events indicating the progress of the call: Call Progress Event Event Handle Description PKX_EVENT_CHANNEL_READY First calls channel Indicates the channel used by the first call is now free for use in the second call. PKX_EVENT_CALL_HELD First call Indicates the first call has been put on hold by the remote switch. PKX_EVENT_CHANNEL_IN_USE Second calls channel (the channel is the same as that used by the first call) Indicates a channel has been seized to make the second call. PKX_EVENT_CALL_DIALING Second call Indicates dialing has been started for the second call. PKX_EVENT_CALL_ALERTING Second call Indicates the dialing for the second call is complete and the far end is ringing. PKX_EVENT_CALL_CONNECTED Second call Indicates the far end has answered the call. PKX_EVENT_CALL_DROPPED Second call Indicates the application has terminated the second call. PKX_EVENT_CALL_DISCONNECTED First call 2 Indicates the remote switch has terminated the connection to the application for the first call. The far end of the first call is still connected to the remote switch.
.3 Basic Functions Call Processing PKX_EVENT_CHANNEL_READY Second calls channel (the channel is the same as that used by the first calls) Indicates the channel used for the first and second call has been released. PKX_EVENT_CALL_RESUMED First call Indicates the original call has been reestablished. This event is only generated after a PKX_CALL_Transfer was issued, but the transfer could not be completed due to a manual or automatic abort. The following diagrams show the function calls made and the events generated when transferring a call. The first diagram shows an incoming call supervised before it is transferred to a second party. The second diagram shows an outgoing call transferred blindly. 3
Call Processing.3 Basic Functions 4
.3 Basic Functions Call Processing When a call is transferred, both the first and second calls must be released to release PIKA GrandPrix SDK resources and invalidate the call handles. The first call may be resumed, either automatically in the case where a busy signal is received, or manually by the user application calling PKX_CALL_Drop and passing in the second call handle, and a cause of PKX_CALL_DROP_CAUSE_NORMAL. If the second call is dropped before the transfer is completed (by dropping with a cause other than PKX_CALL_DROP_CAUSE_TRANSFER), the first call is resumed. The following diagrams show the function calls made and the events generated when the first call is resumed. The first diagram shows the first call being resumed automatically after a busy signal is returned. The second diagram shows the first call being resumed manually by the user application calling PKX_CALL_Drop.
Call Processing.3 Basic Functions 6
.3 Basic Functions Call Processing When the first call is resumed, the second call must be released to release GP resources and invalidate the call handle. Tips Call progress should always be configured for analog channels, otherwise dial and busy tones are not detected..3.4. Terminating a Call A call can be terminated by one of the following events: The incoming call is rejected. The user application terminates the call. The remote party terminates the call. Rejecting incoming calls - If the user application does not wish to accept an incoming call, it calls the PKX_CALL_Reject function after the PKX_EVENT_GROUP_INCOMING_CALL event is retrieved from the event queue. This function must be used immediately after receiving the PKX_EVENT_GROUP_INCOMING_CALL event and before invoking any call function (other than PKX_CALL_GetInfo) using the callhandle specified in p1 of the event. The user application must not call the 7
Call Processing.3 Basic Functions PKX_CALL_Release function after rejecting the call. The user application terminates the call - The user application calls the PKX_CALL_Drop function to terminate a call. The cause parameter should be set to PKX_CALL_DROP_CAUSE_NORMAL. The PKX_CALL_Drop function returns immediately, while lower-level processes send the appropriate messages to terminate the call. When the disconnect message has been sent, the user application receives a PKX_EVENT_CALL_DROPPED event. The user application also receives a PKX_EVENT_CHANNEL_READY when the channel is free. The user application should then call the PKX_CALL_Release function to free the resources used by the call. When the disconnected call was joined to another call, the user application must also terminate the second call. Dropping a call automatically disconnects the channels associated with the call. The remote party terminates the call - When the remote party in a call hangs up, the user application receives a PKX_EVENT_CALL_DISCONNECTED event to indicate the call has been disconnected. The reason the call was disconnected is specified in p1 of the event. The user application also receives a PKX_EVENT_CHANNEL_READY when the channel is free. The user application should then call the PKX_CALL_Release function to free the resources used by the call. When the disconnected call was joined to another call, the user application must also disconnect the channels associated with the call and terminate the second call. The following diagram shows the process flow for all methods of terminating a call. 8
.3 Basic Functions Call Processing Example There are two examples shown below. The both examples are taken from the EventProcessing function in irv.ccp source file of the Interactive Voice Response sample application. The first example demonstrates dropping a call. The second example demonstrates the processing of the events received when a call is terminated. When a PKX_EVENT_CALL_DISCONNECTED event is received (the far-end terminated the call) or a PKX_EVENT_CALL_DROPPED event is received (the application terminated the call), the application retrieves the call handle from the event and releases the call..3.4..1 Terminating a Call Example */ case PKX_EVENT_CALL_DISCONNECTED: case PKX_EVENT_CALL_DROPPED: { printf("call 0x%08x: <-- %sn", (PK_UINT)event.handle, PKX_EVENT_GetText(event.id, eventtext, sizeof(eventtext))); // Retrieve the indexes into the global data structure where the call // information is stored. if (FindCall(event.handle, &groupid, &callid)) { // Clear the call information. g_system.group[groupid].call[callid].handle = PK_HANDLE_NONE; g_system.group[groupid].call[callid].terminate = PK_FALSE; 9
Call Processing.3 Basic Functions // Release the call resources. if ((status = PKX_CALL_Release(event.handle))!= PK_SUCCESS) { printf("pkx_call_release(0x%08x) failed, status = [%s0x%04x] %sn", (PK_UINT)event.handle, (status < 0? "-" : ""), -status, PKX_ERROR_GetText(status, errortext, sizeof(errortext))); break; printf("call 0x%08x: RELEASEDn", (PK_UINT)event.handle); break; /*.3.4..2 Dropping a Call Example */ //---------------------------------------------------------------------------// Terminate the call //---------------------------------------------------------------------------PK_BOOL cleanupcall ( IN PK_INT groupid, IN PK_INT channelid ) { PK_STATUS status; PK_CHAR errortext[pkx_error_max_name_length]; TPikaHandle callhandle = g_system.group[groupid].call[channelid].handle; // Terminate the call when a failure occurs. status = PKX_CALL_Drop(callHandle, PKX_CALL_DROP_CAUSE_NORMAL); if (status!= PK_SUCCESS) { printf("pkx_call_drop(0x%08x) failed, status = [%s0x%04x] %sn", (PK_UINT)callHandle, (status < 0? "-" : ""), -status, PKX_ERROR_GetText(status, errortext, sizeof(errortext))); return PK_FALSE; return PK_TRUE; /* 60
.3 Basic Functions Call Processing.3.4.6 Skype Calls GP supports the call-related features of Skype; other Skype features, such as call transfer, text messaging, file transfers, and video, are not supported. To take advantage of Skype features with GP, the PIKA Windows Client Manager for Skype is required. Refer to the www.pikatechnologies.coms/skype for more information. To initiate a Skype call, use the PKX_CALL_Make function and set the PKX_TCallInfo address information as follows: to - Skype handle of the user to call or the phone number preceded by a + character for SkypeOut calls. from - not used display - not used callingnumberrestricted - not used forwardedfrom - not used custom - not used When receiving an incoming Skype call, the PKX_TCallInfo address information will be set as follows: to - the Skype handle associated with the channel receiving the call from - the Skype handle of the calling user display - the field is in the form <Full Name> " "< Mobile Phone> " " <Office Phone> " " <Home Phone> callingnumberrestricted - not used forwardedfrom - indicates the last Skype party to forward the call, if any, to the receiving Skype channel custom - not used Hunt Groups Although call transfer is not supported, an incoming hunt group is. A hunt group is a set of channels that cover for each other so if a specified incoming channel is busy, another channel in the hunt group takes the call. A hunt group is provisioned in the GP AoH product configuration file for the Skype resource group by setting the huntgroup key to yes. When an incoming call arrives for a Skype channel already involved in a call, the hunt group looks for a free channel and, using the Skype client Forwarding feature, forwards the call to the free channel. If another call arrives on that 61
Call Processing.3 Basic Functions channel before the forwarding is complete, the hunt group searches for another channel. If all the channels in the hunt group are busy, the call is rejected. When a hunt group is configured, a single Skype client handle is advertised to potential callers. All incoming calls arrive at the one handle and are redirected to other handles within the group. If needed, the PKX_TCallInfo::forwardedFrom field is set to the original incoming Skype client handle. The information in the forwardedfrom field allows GP to determine who forwarded the call. Refer to the section Skype Resources in the Configuration Guide for information about all the configuration settings for Skype channels. Setting up the Skype Client GP supports Skype client versions 2. and newer. To ensure all supported and non-supported Skype features are properly handled by GP, the local Skype client must be configured appropriately. Configuration information is set using the tabs under the "Tools / Options " menu. Go to the "Tools" menu, then section "Options " Under the General tab, select: Show me as 'Away' when I am inactive for 0 minutes Show me as 'Not Available' when I am inactive for 0 minutes Under the Privacy tab, select: Allow calls from anyone (or as appropriate for the application). Allow chats from only people I have shared my details with. Under the Video tab, select: Do not enable Skype video. Under the Advanced tab, select: Do not start Skype when I start Windows. (This is handled by the PIKA Windows Client Manager software.) Do not automatically answer calls. 62
.3 Basic Functions Note: Media Processing Occasionally, the local client Skype login credentials need to be re-entered. Example This example is taken from the EventProcessing function in skypgateway.cpp of the Skye Gateway sample..3.4.6.1 Initiating a Skype Call Example */ // Update outgoing call information. This code is the only bit that // is specific to SIP and Skype channels. This could easily be // rewritten to implement another means of determining the recipient // (e.g. menuing system) and then could be used for all types of // channels. switch (g_system.group[groupid2].config.type) { case PKX_GROUP_TYPE_SIP: strcpy(callinfo2.to, SIP_RECIPIENT_NAME); strcpy(callinfo2.from, ""); // Uses the default user agent strcpy(callinfo2.display, callinfo.from); break; case PKX_GROUP_TYPE_SKYPE: strcpy(callinfo2.to, SKYPE_RECIPIENT_NAME); // The following fields are automatically overriden by the outgoing // Skype client. There are currently no means to set these fields. strcpy(callinfo2.from, ""); strcpy(callinfo2.display, ""); break; default:; channelhandle = g_system.group[groupid2].channel[channelid2].handle; // Make outgoing call status = PKX_CALL_Make(channelHandle, &callinfo2, &callsettings, &g_system.group[groupid2].call[channelid2].handle); /*.3. Media Processing The following topics describe how to perform media processing functions on a channel: Playing a stored message (pg. 64) Recording (pg. 71) Collecting DTMF digits (pg. 78) 63
Media Processing.3 Basic Functions Sending DTMF digits (pg. 83) Generating tones (pg. 83) Detecting tones (pg. 8) Detecting speech (pg. 86).3..1 Playing a Stored Message There are two methods of playing a stored message on a channel: 1. Queue one or more stored messages to the channel using the PKX_CHANNEL_PlayAddData function and then start playing the message(s) using the PKX_CHANNEL_Play function. The messages to be played can be stored in either a memory buffer or a file. A structure (PKX_TAudioData) is passed in as a parameter to the PKX_CHANNEL_PlayAddData function. This structure defines where the stored message is located (in a memory buffer or in a file), which portion (offset and length) of the data to play, and whether this is the last segment of data to play. 2. Play one message file to a channel using the PKX_CHANNEL_PlayFile function. This method can play only one file. Both the PKX_CHANNEL_PlayAddData and PKX_CHANNEL_PlayFile functions are use a flags parameter that defines the audio properties of the data. See the Audio Flags (pg. 87) section for more information on the flags that can be passed to these functions. Both the PKX_CHANNEL_Play and PKX_CHANNEL_PlayFile functions are passed a set of termination conditions. See the Media Processing Termination Conditions (pg. 89) section for more information on conditions that can be used to terminate these functions. These functions can also be terminated using the PKX_CHANNEL_Stop function. The PKX_CHANNEL_PlayAddData function requires a PKX_TAudioData structure to be passed to it. This structure defines the location of the audio data block to be added to the queue of data to be played. The following table describes the fields defined in the PKX_TAudioData structure: 64
.3 Basic Functions Media Processing PKX_TAudioData Description Field location.buffer Pointer to the memory buffer where the audio data block to be played is stored. This location is used if the PKX_AUDIO_DATA_TYPE_FILE flag is not set in the typeflags field. location.filename Name of the file where the audio data block to be played is stored. This location is used if the PKX_AUDIO_DATA_TYPE_FILE flag is set in the typeflags field. offset The offset within the location to start processing the audio data. length Number of bytes to play from the specified offset. The PKX_AUDIO_PLAY_ALL_DATA constant is used in this field to indicate all the audio data in the file is to be played. This constant cannot be used with buffer locations as it is not possible to determine the size of the buffer. typeflags Bit mask of indicators describing the data. These flags can be ORed together. PKX_AUDIO_LAST_BUFFER indicates to the PKX_CHANNEL_Play function that it should terminate playing after this data block is played. If this flag is not set on the last data block, a PKX_EVENT_CHANNEL_UNDERFLOW_PLAY event is raised and the play function pauses until more data is provided. PKX_AUDIO_DATA_TYPE_FILE indicates the audio data to be played is located in the file location field. The PKX_CHANNEL_Play and PKX_CHANNEL_PlayFile functions return immediately. Lower-level processes manage the playing of the audio data blocks. As these lower-level processes play the data, events are generated indicating progress. The following table lists the events that can be generated while playing data: Play Event Description PKX_EVENT_CHANNEL_UNDERFLOW_PLAY Indicates the PKX_CHANNEL_Play asynchronous function has run out of audio data to play and has not received a PKX_TAudioData structure indicating it is the last block of audio data. The play function plays silence until more data is added, or the media function is terminated by meeting one of its termination conditions or using the PKX_CHANNEL_Stop function. PKX_EVENT_CHANNEL_DATAREADY_PLAY Indicates a block of data has been played. This event can be used by the user application to maintain a constant number of pending play audio data blocks when playing a very long (or infinitely long) audio stream. 6
Media Processing.3 Basic Functions PKX_EVENT_CHANNEL_DONE_PLAY Indicates the PKX_CHANNEL_PlayFile or PKX_CHANNEL_Play asynchronous function has completed successfully. PKX_EVENT_CHANNEL_STOPPED_PLAY Indicates the PKX_CHANNEL_PlayFile or PKX_CHANNEL_Play asynchronous function has been terminated successfully using the PKX_CHANNEL_Stop function. PKX_EVENT_CHANNEL_TERM_xxx Indicates the PKX_CHANNEL_PlayFile or PKX_CHANNEL_Play asynchronous function has been terminated because one of its termination conditions has been met. The xxx corresponds to the termination condition that was met. See Media Processing Termination Conditions (pg. 89) for more information on which termination conditions are allowed for these functions. If a second call to PKX_CHANNEL_PlayFile is executed before the first call has completed playing the data, the second PKX_CHANNEL_PlayFile returns a status of PKX_ERROR_CHANNEL_MEDIA_IN_USE. The following diagrams demonstrate when these events are generated. In the first scenario, the PKX_CHANNEL_Play function is executed before any buffers have been added. The user application receives a PKX_ERROR_CHANNEL_AUDIO_DATA_NOT_AVAILABLE event. In the second scenario, the buffer with the last buffer flag set is added before the PKX_CHANNEL_Play function is executed. The stored message is played on the channel and the user application receives two events, PKX_EVENT_CHANNEL_DATAREADY_PLAY and PKX_EVENT_CHANNEL_DONE_PLAY, when the message has completed playing. 66
.3 Basic Functions Media Processing In the third scenario,the PKX_CHANNEL_PlayFile function is used to play data from a file. The stored message is played on the channel and the user application receives two events, PKX_EVENT_CHANNEL_DATAREADY_PLAY and PKX_EVENT_CHANNEL_DONE_PLAY, when the message has completed playing. In the fourth scenario, four buffers are added, with the fourth buffer having the last buffer flag set. When the PKX_CHANNEL_Play function is executed, the buffers are played sequentially, in the order they were added. The user application receives a PKX_EVENT_CHANNEL_DATAREADY_PLAY event after each buffer completes playing. After the fourth buffer is played, the user application receives a PKX_EVENT_CHANNEL_DONE_PLAY event. In the fifth scenario, four buffers are added, with the fourth buffer having the last buffer flag set. When the PKX_CHANNEL_Play function is executed, the buffers are played sequentially, in the order they were added. The user application receives a PKX_EVENT_PLAY_DATA_PLAYED event after each buffer completes playing. In the middle of playing the third buffer, the PKX_CHANNEL_Stop function is executed. This causes the playback of the third buffer to stop. The rest of the third buffer and the fourth buffer are discarded. The user application receives one event, PKX_EVENT_CHANNEL_STOPPED_PLAY. No events are generated for the third or fourth buffers. 67
Media Processing.3 Basic Functions In the sixth scenario, one of the termination conditions specified in the PKX_CHANNEL_Play function has been met before all the data has been played. When the termination condition is met, the playing of the data stops and a PKX_EVENT_CHANNEL_TERM_xxx is generated. The xxx corresponds to the termination condition that was met. The rest of the third buffer and the fourth buffer are discarded. In the seventh scenario, two buffers are added and then the PKX_CHANNEL_Play function is executed. While the initial two buffers are playing, two more buffers are added. As long as the additional buffers are added before the initial buffers have completed playing, a continuous audio stream is played. The user application receives a PKX_EVENT_CHANNEL_DATAREADY_PLAY event after each buffer completes playing. After the fourth buffer is played, the user application receives a PKX_EVENT_CHANNEL_DONE_PLAY event. 68
.3 Basic Functions Media Processing In the eighth scenario, two buffers are added before the PKX_CHANNEL_Play function is executed. The second buffer does not have the last buffer flag set. The first two buffers are played before the third buffer is added. Since there is no more data queued to be played and the last buffer flag was not set in the last buffer played, a PKX_EVENT_CHANNEL_UNDERFLOW_PLAY event is generated. When the third and fourth buffers are added, the data continues playing. Example Two examples are shown: The first example is the playfile function in ivr.ccp of the Interactive Voice Response sample application. It demonstrates playing a message stored in a file to a channel. The flag for WAVE file header is set. This indicates the specification of the encoding format and sampling rate are contained in the WAVE header appended to the file. No termination conditions are specified so the entire file is played. The second example is the queueplaybuffer function in meetme.cpp of the MeetMe sample application. It demonstrates using a single buffer to store separate message data and then play them back. This approach saves memory if multiple channels need simultaneous access to play the same data..3..1.1 Playing a Message Example */ // ---------------------------------------------------------------------------// Play the specified file. There are no termination conditions specified with // this play operation. // ---------------------------------------------------------------------------PK_BOOL playfile 69
Media Processing.3 Basic Functions ( IN IN IN PK_INT groupid, PK_INT channelid, PK_CHAR *filename ) { PK_STATUS status; PK_CHAR errortext[pkx_error_max_name_length]; TPikaHandle channelhandle = g_system.group[groupid].channel[channelid].handle; PKX_TTermCond termcond; memset(&termcond, 0, sizeof(pkx_ttermcond)); status = PKX_CHANNEL_PlayFile(channelHandle, filename, &termcond, PKX_AUDIO_WAVE_HEADER); if (status!= PK_SUCCESS) { printf("pkx_channel_playfile(0x%08x) failed, status = [%s0x%04x] %sn", (PK_UINT)channelHandle, (status < 0? "-" : ""), -status, PKX_ERROR_GetText(status, errortext, sizeof(errortext))); return PK_FALSE; printf("channel 0x%08x: Playing '%s'...n", (PK_UINT)channelHandle, filename); return PK_TRUE; /*.3..1.2 Play Buffers Example - Add data to Buffer */ // First add the recorded name to PKX_TAudioData nextbufferdetails; nextbufferdetails.location.buffer nextbufferdetails.offset nextbufferdetails.length nextbufferdetails.typeflags the play buffer = = = = buffer; bufferoffset; buffersize; islastbuffer?pkx_audio_last_buffer:0; status = PKX_CHANNEL_PlayAddData(channelHandle, &nextbufferdetails, PKX_AUDIO_ENCODING_MU_LAW PKX_AUDIO_SAMPLING_RATE_8KHZ); if (status!= PK_SUCCESS) { printf("pkx_channel_playadddata(0x%08x) failed, status = [%s0x%04x] %sn", (PK_UINT)channelHandle, (status < 0? "-" : ""), -status, PKX_ERROR_GetText(status, errortext, sizeof(errortext))); return PK_FALSE; /* 70
.3 Basic Functions Media Processing.3..1.3 Play Buffers Example - Play Buffers In Sequence */ // Play the recorded name first if (!queueplaybuffer(g_system.conference.announcehandle, g_system.group[groupid].call[channelid].namebuffer, 0, g_system.group[groupid].call[channelid].namebuffersize, PK_FALSE)) { return PK_FALSE; // Next add the ' has joined the conference' to the play buffer if (!queueplaybuffer(g_system.conference.announcehandle, g_namebuffer, 0, g_namebuffersize, PK_TRUE)) { return PK_FALSE; // No termination condition PKX_TTermCond termcond; memset(&termcond, 0, sizeof(pkx_ttermcond)); // Start playing the buffered data status = PKX_CHANNEL_Play(g_System.conference.announceHandle, &termcond); if (status!= PK_SUCCESS) { printf("pkx_channel_playfile(0x%08x) failed, status = [%s0x%04x] %sn", (PK_UINT)g_System.conference.announceHandle, (status < 0? "-" : ""), -status, PKX_ERROR_GetText(status, errortext, sizeof(errortext))); return PK_FALSE; /*.3..2 Recording Audio Data From a Channel There are two methods of recording audio data from a channel: 1. Start recording the audio data from a channel using the PKX_CHANNEL_Record function. The user application receives PKX_EVENT_CHANNEL_DATAREADY_RECORD events to indicate a block of recorded audio data is ready for the user application to retrieve using the PKX_CHANNEL_RecordGetData function. NOTE: When a PKX_EVENT_CHANNEL_DATAREADY_RECORD event is returned by the PKX_SYSTEM_WaitOnEvent function, the buffer of recorded data must be retrieved before the next call to PKX_SYSTEM_WaitOnEvent or the recorded data is lost. 2. Record the audio data from a channel directly to a file using the PKX_CHANNEL_RecordFile function. Both the PKX_CHANNEL_Record and PKX_CHANNEL_RecordFile functions are passed a flags parameter that 71
Media Processing.3 Basic Functions defines the audio properties of the data recorded. See the Audio Flags (pg. 87) section for more information on the flags that can be passed to these functions. Both the PKX_CHANNEL_Record and PKX_CHANNEL_RecordFile functions are passed a set of termination conditions. See Media Processing Termination Conditions (pg. 89) for more information on conditions used to terminate these functions. These functions can also be terminated using the PKX_CHANNEL_Stop function. The PKX_CHANNEL_RecordGetData function requires a PKX_TAudioData structure to be passed to it. This structure defines the buffer into which the audio data block recorded is copied. The following table describes the fields defined in the PKX_TAudioData structure used for the PKX_CHANNEL_RecordGetData function. PKX_TAudioData Description Field location.buffer Pointer to the memory buffer where the recorded audio data block is stored. location.filename Not used. offset Not used. length IN: The number of bytes allocated by the user application for the buffer. If the size is insufficient, the error PKX_ERROR_INSUFFICIENT_MEMORY_PROVIDED will be returned. OUT: The actual number of bytes copied into the buffer. The number of bytes of data available in the record buffer is specified in the PKX_EVENT_CHANNEL_DATAREADY_RECORD event. typeflags Not used. The PKX_CHANNEL_Record and PKX_CHANNEL_RecordFile functions return immediately. Low-level processes manage the recording of the audio data blocks. As these low-level processes record the data, events are generated indicating progress. The following table lists the events that can be generated while recording data. 72
.3 Basic Functions Play Event Description Media Processing PKX_EVENT_CHANNEL_DATAREADY_RECORD Indicates the PKX_CHANNEL_Record asynchronous function has a block of recorded audio data ready for the user application to retrieve using the PKX_CHANNEL_RecordGetData function. The p0 field of the event specifies the number of bytes available in the internal audio buffer. PKX_EVENT_CHANNEL_OVERFLOW_RECORD Indicates the PKX_CHANNEL_Record asynchronous function has run out of internal memory to temporarily store the recorded audio data. Incoming audio data is lost until the user application retrieves a block of audio data using the PKX_CHANNEL_RecordGetData function. There are five 16 kb internal audio buffers. PKX_EVENT_CHANNEL_STOPPED_RECORD Indicates the PKX_CHANNEL_RecordFile or PKX_CHANNEL_Record function has been terminated using the PKX_CHANNEL_Stop function. PKX_EVENT_CHANNEL_TERM_xxx Indicates the PKX_CHANNEL_RecordFile or PKX_CHANNEL_Record function has been terminated because one of its termination conditions has been met. See Media Processing Termination Conditions (pg. 89) for more information on which termination conditions are allowed for these functions. The following diagrams demonstrate when these events are generated. In the first scenario, the PKX_CHANNEL_RecordFile function is executed. The audio data on the channel is recorded to the file until one of the termination conditions specified in the PKX_CHANNEL_RecordFile function 73
Media Processing.3 Basic Functions call is met. When the termination condition is met, the recording of the data stops, all the recorded data is written to the file, the file is closed, and a PKX_EVENT_CHANNEL_TERM_xxx is generated. The xxx corresponds to the termination condition that was met. In the second scenario, the PKX_CHANNEL_Record function is executed. As each buffer of audio data is recorded, a PKX_EVENT_CHANNEL_DATAREADY_RECORD event is generated. The user application periodically retrieves the recorded audio data buffers using the PKX_CHANNEL_RecordGetData function and stores or processes the data. The user application stops the recording of audio data using the PKX_CHANNEL_Stop function. This causes recording of audio data on the channel to stop, a final PKX_EVENT_CHANNEL_DATAREADY_RECORD event to be generated, and a PKX_EVENT_CHANNEL_STOPPED_RECORD event to be generated. In the third scenario, the PKX_CHANNEL_Record function is executed. GP has only five internal audio buffers. The user application receives five PKX_EVENT_CHANNEL_DATAREADY_RECORD events but does not retrieve any of the audio data. A PKX_EVENT_CHANNEL_RECORD_OVERFLOW event is generated and audio data recording stops. Later, the user application executes a PKX_CHANNEL_RecordGetData function, retrieving the data from one of the internal audio data buffers. This frees the audio buffer and audio data recording restarts. The user application stops the audio data recording using the PKX_CHANNEL_Stop function. This causes audio data recording on the channel to stop, a final PKX_EVENT_CHANNEL_DATAREADY_RECORD event to be generated, and a PKX_EVENT_CHANNEL_STOPPED_RECORD event to be generated. The audio data received or transmitted on the channel between the generation of the PKX_EVENT_CHANNEL_RECORD_OVERFLOW event and the PKX_CHANNEL_RecordGetData function call is lost. 74
.3 Basic Functions Media Processing GP uses large audio buffers (16 kb) for record functions. The size of these buffers may become an issue to some user applications processing the audio because they introduce latency. A user application must wait until the entire buffer is filled with data before getting an event indicating that audio data is available to be processed. Refer to section Configuring a Channel (pg. 106) for information on customizing the recording buffer size. Tips Performing active call logging when two or more calls are conferenced together requires a virtual channel to be used to record the audio. Example There are three examples shown: The first example is the function recordfile and can be found in the irv.ccp source file of the Interactive Voice Response sample application. It demonstrates recording the audio data from a channel directly into a file. The encoding format is set to mu-law, the sampling rate is set to 8 khz, and the flag to play an initial beep to indicate recording is being performed is set. Two termination conditions are set for the recording process, either the pound (#) phone key tone or a period of silence is detected on the channel. The second example is taken from from the handleivrevents function in irv.ccp source file of the Interactive Voice Response sample application. It demonstrates the processing required when one of the termination conditions has been met. In this example the call is dropped. The third example is taken from the the EventProcessing function in the meetme.cpp source file of the MeetMe sample application. It shows how to record data to a buffer. This approach allows the application to access the data as it is recorded instead of waiting until one of the termination conditions is met to retrieve the entire block of data from a file. The example shows data being appended to the end of a buffer to avoid overwriting previously recorded data..3..2.1 Recording a Message Example */ // ---------------------------------------------------------------------------// Start recording the message from the calling party. Play a beep to tell the // calling party to start talking. // ---------------------------------------------------------------------------PK_BOOL recordfile ( IN PK_INT groupid, IN PK_INT channelid, IN PK_CHAR *filename ) { PK_STATUS status; PK_CHAR errortext[pkx_error_max_name_length]; 7
Media Processing.3 Basic Functions TPikaHandle channelhandle = g_system.group[groupid].channel[channelid].handle; PKX_TTermCond termcond; memset(&termcond, 0, sizeof(pkx_ttermcond)); termcond.silencetimeout = IVR_SAMPLE_RECORD_SILENCE_TIMEOUT; termcond.digitmask = PKX_MEDIA_DTMF_DIGIT_POUND; status = PKX_CHANNEL_RecordFile(channelHandle, filename, &termcond, PKX_AUDIO_ENCODING_MU_LAW PKX_AUDIO_SAMPLING_RATE_8KHZ PKX_AUDIO_BEEP_BEFORE_RECORDING); if (status!= PK_SUCCESS) { printf("pkx_channel_recordfile(0x%08x) failed, status = [%s0x%04x] %sn", (PK_UINT)channelHandle, (status < 0? "-" : ""), -status, PKX_ERROR_GetText(status, errortext, sizeof(errortext))); return PK_FALSE; printf("channel 0x%08x: Recording...n", (PK_UINT)channelHandle); return PK_TRUE; /*.3..2.2 Record Termination Conditions Example */ case PKX_EVENT_CHANNEL_TERM_DIGIT_MASK: case PKX_EVENT_CHANNEL_TERM_SILENCE_TIMEOUT: printf("channel 0x%08x: <-- %sn", (PK_UINT)event->handle, PKX_EVENT_GetText(event->id, eventtext, sizeof(eventtext))); // Retrieve the indexes into the global data structure where the // channel information is stored. if (FindChannel(PK_HANDLE_NONE, event->handle, &groupid, &channelid)) { // This termination condition should only occur when recording a message // with option '0' on the IVR menu. if (g_system.group[groupid].channel[channelid].option == IVR_SAMPLE_OPTION_0) { cleanupcall(groupid, channelid); break; /* 76
.3 Basic Functions Media Processing.3..2.3 Append Recorded Data to a Buffer Example */ case PKX_EVENT_CHANNEL_DATAREADY_RECORD: //Record data is ready to be collected printf("channel 0x%08x: <-- %sn", (PK_UINT)event.handle, PKX_EVENT_GetText(event.id, eventtext, sizeof(eventtext))); if (FindChannel(PK_HANDLE_NONE, event.handle, &groupid, &channelid)) { // Create a buffer to store the recorded data in PKX_TAudioData audiodetails; memset(&audiodetails, 0, sizeof(pkx_taudiodata)); audiodetails.location.buffer = g_system.group[groupid].call[channelid].namebuffer; if (audiodetails.location.buffer == NULL) { // initial allocation audiodetails.location.buffer = (PK_CHAR *)malloc((pk_size_t)event.p0); else { // reallocation audiodetails.location.buffer = (PK_CHAR *)realloc(audiodetails.location.buffer, g_system.group[groupid].call[channelid].namebuffersize + (PK_SIZE_T)event.p0); audiodetails.length = (PK_SIZE_T)event.p0; status = PKX_CHANNEL_RecordGetData(event.handle, &audiodetails); if (status!= PK_SUCCESS) { printf("pkx_channel_recordgetdata(record 0x%08x) failed," " status = [%s0x%04x] %sn", (PK_UINT)g_System.conference.recordHandle, (status < 0? "-" : ""), -status, PKX_ERROR_GetText(status, errortext, sizeof(errortext))); // Free the audio buffer delete [] audiodetails.location.buffer; break; // Store the buffer on the channel g_system.group[groupid].call[channelid].namebuffer = audiodetails.location.buffer; g_system.group[groupid].call[channelid].namebuffersize += audiodetails.length; break; /* 77
Media Processing.3 Basic Functions.3..3 Collecting DTMF Digits From a Channel The user application uses PKX_CHANNEL_CollectDigits to apply termination conditions to the collection of DTMF digits on a channel. The user application can use the PKX_CHANNEL_GetNumberOfDigits function to determine the number of digits in the received digit buffer for a specified channel. The PKX_CHANNEL_GetDigits function copies the specified number (or fewer, if there are insufficient digits in the channel digit buffer) of ASCII representations of the digits from the channel digit buffer into a local buffer supplied by the user application. Digits copied into a local buffer are removed from the channel digit buffer. The digits in the local buffer are terminated with a null (\0) character. The user application must ensure the local buffer is large enough to receive all the requested digits plus the null terminator. The user application can use the strlen function on the local buffer to determine the actual number of digits returned. The following table lists the ASCII representations that correspond to the DTMF tones generated when the keys are pressed on a phone: Phone Key 0 1 2 3 4 6 7 8 9 * # A B C D DTMF ASCII Representation 0 1 2 3 4 6 7 8 9 * # A B C D NOTE: The A, B, C, and D keys are rarely found on a phone. A channel digit buffer can store up to 127 digits. When 127 digits have been collected, without any of the digits having been retrieved by a PKX_CHANNEL_GetDigits function call, additional digits generated on the channel are not placed in the buffer. A PKX_EVENT_CHANNEL_DIGIT_BUFFER_FULL event is generated for every DTMF digit received that is not put in the buffer because the buffer is full: p0 of this event is set to 127, and p1 of this event specifies the DTMF digit received. Subsequent calls to the PKX_CHANNEL_GetDigits function frees space in the channel digit buffer, and digits received after the PKX_CHANNEL_GetDigits function call are collected up to the limit of the channel digit buffer. The PKX_CHANNEL_ClearDigits function deletes any digits stored in the channel digit buffer. The PKX_CHANNEL_Stop function is used to stop the termination conditions applied to the collection of DTMF digits on a channel. When DTMF digits are being collected on a channel and the PKX_CHANNEL_Stop function is 78
.3 Basic Functions Media Processing executed on that channel, a PKX_EVENT_CHANNEL_STOPPED_COLLECT_DIGITS event is generated. The p0 field of this event specifies the number of digits in the channel digit buffer when the PKX_CHANNEL_Stop was executed. Whenever a DTMF digit is detected on a channel (whether PKX_CHANNEL_CollectDigits has been called or not), a PKX_EVENT_CHANNEL_DTMF event is generated, indicating the DTMF digit has been received over the channel. The ASCII representation of the DTMF digit is specified in the p0 field of the event. The following diagram shows the events generated and the state of the internal digit buffer as DTMF digits are received. In the diagram, a PKX_EVENT_CHANNEL_DTMF event is generated for each digit received. The 79
Media Processing.3 Basic Functions PKX_CHANNEL_CollectDigits function (with a termination condition of maxdigits=3) is executed after one digit has been received. After the third digit is received, a PKX_EVENT_CHANNEL_TERM_MAX_DIGITS event is generated. The PKX_CHANNEL_CollectDigits function (with a termination condition of maxdigits=3) is executed again, after four digits have been received. Since there are four digits in the buffer, a PKX_EVENT_CHANNEL_TERM_MAX_DIGITS event is generated immediately. The PKX_CHANNEL_GetDigits function is called with four specified as the number of digits to transfer. Four digits are removed from the internal digit buffer and copied into the local buffer. The PKX_CHANNEL_CollectDigits function (with a termination condition of maxdigits=) is executed after the four digits have been removed from the buffer. The PKX_CHANNEL_Stop function is executed before the ninth digit is received. A PKX_EVENT_CHANNEL_STOPPED_COLLECT_DIGITS event is generated. This means that PKX_EVENT_CHANNEL_TERM_MAX_DIGITS is NOT generated after the ninth digit is received. The digits remaining in the channel internal digit buffer may still be retrieved using the PKX_CHANNEL_GetDigits function. NOTE: If DTMF detection has been disabled using the PKX_CHANNEL_SetConfig API function, digit collection will not be possible, however, no error will be generated. This applies only when using the AoH low-level product. Example There are three examples: the first example is the function selectoption, and the second and third examples are taken from from the handleivrevents function. All examples can be found in irv.ccp source file of the Interactive Voice Response sample application. The first example demonstrates the setting of termination conditions on the collection of digits on a channel. Two termination conditions are specified, a digit being received, or no tone being received for a timeout period. The second example demonstrates getting one digit from the channel digit buffer. Depending on the digit received, the application plays a canned message or plays a prompt to the caller that instructs them to record a message. The third example demonstrates the action taken if the timeout termination condition is met. In this example, the call is dropped..3..3.1 Collecting Digits Example */ // ---------------------------------------------------------------------------// Wait for the calling party to press a digit. Terminate as soon as that digit // is pressed or the timeout period occurs. // ---------------------------------------------------------------------------PK_BOOL selectoption 80
.3 Basic Functions Media Processing ( IN IN PK_INT groupid, PK_INT channelid ) { PK_STATUS status; PK_CHAR errortext[pkx_error_max_name_length]; TPikaHandle channelhandle = g_system.group[groupid].channel[channelid].handle; PKX_TTermCond termcond; memset(&termcond, 0, sizeof(pkx_ttermcond)); termcond.timeout = IVR_SAMPLE_MENU_REPEAT_PERIOD; termcond.maxdigits = 1; status = PKX_CHANNEL_CollectDigits(channelHandle, &termcond); if (status!= PK_SUCCESS) { printf("pkx_channel_collectdigits(0x%08x) failed," " status = [%s0x%04x] %sn", (PK_UINT)channelHandle, (status < 0? "-" : ""), -status, PKX_ERROR_GetText(status, errortext, sizeof(errortext))); return PK_FALSE; printf("channel 0x%08x: Collecting digits...n", (PK_UINT)channelHandle); return PK_TRUE; /*.3..3.2 Getting Digits Example */ case PKX_EVENT_CHANNEL_TERM_MAX_DIGITS: printf("channel 0x%08x: <-- %sn", (PK_UINT)event->handle, PKX_EVENT_GetText(event->id, eventtext, sizeof(eventtext))); // Retrieve the indexes into the global data structure where the // channel information is stored. if (FindChannel(PK_HANDLE_NONE, event->handle, &groupid, &channelid)) { PK_CHAR digitbuffer[2]; // Retrieve the digit that was entered. status = PKX_CHANNEL_GetDigits(event->handle, digitbuffer, 1); if (status!= PK_SUCCESS) { printf("pkx_channel_getdigits(0x%08x) failed, status = [%s0x%04x] %sn", (PK_UINT)event->handle, (status < 0? "-" : ""), -status, 81
Media Processing.3 Basic Functions PKX_ERROR_GetText(status, errortext, sizeof(errortext))); terminatecall = PK_TRUE; break; printf("channel 0x%08x: <-- DTMF %cn", (PK_UINT)event->handle, digitbuffer[0]); // Handle the option selected switch (digitbuffer[0]) { case '1': // The calling party wishes to hear the canned response. g_system.group[groupid].channel[channelid].option = IVR_SAMPLE_OPTION_1; terminatecall =!playfile(groupid, channelid, IVR_SAMPLE_AUDIO_CANNED_FILE); break; case '0': // The calling party wishes to leave a message. g_system.group[groupid].channel[channelid].option = IVR_SAMPLE_OPTION_0; terminatecall =!playfile(groupid, channelid, IVR_SAMPLE_AUDIO_LEAVEMSG_FILE); break; default: // An invalid option has been pressed. Inform the calling party of the // error and replay the main menu. g_system.group[groupid].channel[channelid].option = IVR_SAMPLE_OPTION_INVALID; terminatecall =!playfile(groupid, channelid, IVR_SAMPLE_AUDIO_ERROR_FILE); // Drop the call if an error has occured with any of the menu options. if (terminatecall) cleanupcall(groupid, channelid); break; /*.3..3.3 Collecting Digits Termination Conditions Example */ case PKX_EVENT_CHANNEL_TERM_TIMEOUT: printf("channel 0x%08x: <-- %sn", (PK_UINT)event->handle, PKX_EVENT_GetText(event->id, eventtext, sizeof(eventtext))); // Retrieve the indexes into the global data structure where the // channel information is stored. if (FindChannel(PK_HANDLE_NONE, event->handle, &groupid, &channelid)) { // Replay the IVR menu 82
.3 Basic Functions Media Processing if (!ivrmenu(groupid, channelid)) cleanupcall(groupid, channelid); break; /*.3..4 Sending DTMF Digits to a Channel The user application uses the PKX_CHANNEL_PlayDigits function to send DTMF digits to a channel. The user application passes a null terminated string of the ASCII representations of DTMF keys to this function. The ASCII representations of the DTMF keys supported are: 0 to 9; a to d; A to D; P; T; W;,; &; #; and *. If any other characters are contained in the string, the PKX_CHANNEL_PlayDigits function returns a PKX_ERROR_CHANNEL_INVALID_PLAY_DIGIT_SPECIFIED error status. The DTMF tones are played as a continuous stream. The tone on and off durations are defined in the root configuration file. See Tone Generation for more information on the specification of tone on and off durations. When the string of DTMF digits has been transmitted, a PKX_EVENT_CHANNEL_DONE_TONE_GENERATION event is generated. The generation of a string of DTMF digits can be terminated using the PKX_CHANNEL_Stop function. The generation of DTMF tones stops, with any unplayed tones discarded. A PKX_EVENT_CHANNEL_STOPPED_TONE_GENERATION is generated. The p0 field of this event specifies the last tone played..3.. Generating Tones on a Channel The tone groups GP can generate are listed in the [tone_generation] section of the root configuration file. To generate a tone group on a channel, the user application uses the PKX_CHANNEL_PlayTone function. The parameters passed to this function are: The channel handle. The index to the entries of the [tone_generation] section of the GP root configuration file. The termination conditions to stop the tone playing. See Media Processing Termination Conditions (pg. 89) for more information on the termination conditions that may be used for this function. 83
Media Processing.3 Basic Functions NOTE: A tone group is a collection of single-frequency tones. For example: a DTMF tone is a tone group made up of two single-frequency tones. GP function calls always deal with the tone group. The tone group is played for the total of the on and off duration specified in the tone definition unless a termination condition is met or the PKX_CHANNEL_Stop function is executed on that channel. When the tone group has been completely played (both on and off periods), a PKX_EVENT_CHANNEL_DONE_TONE_GENERATION event is generated. When the tone generation is stopped by a termination condition, a PKX_EVENT_CHANNEL_TERM_xxx (where xxx specifies the termination condition that was met) event is generated. When the tone generation is stopped by the PKX_CHANNEL_Stop function, a PKX_EVENT_CHANNEL_STOPPED_TONE_GENERATION event is generated. When no termination conditions are specified, the tone group plays for the duration specified in the configuration file (for example toneg3 "dial" plays for five seconds). When termination conditions are specified, the tone group repeats automatically until one of the termination conditions are met. To play a continuous tone group, use the timeout termination condition and set it for the desired time in milliseconds. Only one tone group can be played at a time. If a second call to the PKX_CHANNEL_PlayTone function is made while a tone group is being played, a PKX_ERROR_CHANNEL_MEDIA_IN_USE status is returned. The tone patterns generated by GP are listed in the [tone_patterns] section of the root configuration file. A tone pattern can be generated on a channel using the PKX_CHANNEL_PlayTonePattern function. The parameters passed to this function are: The channel handle. The index into the entries of the [tone_patterns] section of the root configuration file. The termination conditions to stop the tone playing. See Media Processing Termination Conditions (pg. 89) for more information on the termination conditions that may be used for this function. When no termination conditions are specified, the tone pattern plays for the duration specified in the configuration file (for example, tone_pattern0 "tp_ringback" plays for the duration of toneg36, two seconds on, and toneg37, four seconds off, for a total of six seconds). When termination conditions are specified, the tone pattern repeats automatically until one of the termination conditions is met. To play a continuous tone pattern, use the timeout termination condition and set it for the desired time in milliseconds. The PKX_CHANNEL_Stop function stops the playing of a tone or tone pattern. 84
.3 Basic Functions Media Processing When the tone pattern has been completely played, a PKX_EVENT_CHANNEL_DONE_TONE_GENERATION event is generated. When the tone generation is stopped by a termination condition, a PKX_EVENT_CHANNEL_TERM_xxx (where xxx specifies the termination condition that was met) event is generated. When the tone pattern generation is stopped by the PKX_CHANNEL_Stop function, the generation of the tone pattern stops, with any unplayed tones discarded. A PKX_EVENT_CHANNEL_STOPPED_TONE_GENERATION event is generated. The p0 field of this event specifies the last tone played. The repeat key in the tone pattern configuration section indicates the number of tone groups, starting at the last tone group, to be replayed during subsequent repetitions. This allows a tone pattern to be defined that begins with a special sequence of tone groups, followed by a regular pattern of tone groups or a continuous tone group. An example of this is the stutter dialtone. This tone is made up of three or more bursts (or beeps) of 100 ms on / 100 ms off followed by continuous on. The following example is a tone pattern configuration section where the first three cadence entries are the beeps, and the last cadence entry is the standard dialtone. The dialtone portion must be the repeated portion. To achieve this, the repeat key is set to 1 indicating only the last cadence entry is to be repeated. [stutter_dialtone] repeat=1 cadences=2 cadence0=toneg31 cadence1=toneg31 cadence2=toneg31 cadence3=toneg3.3..6 Detecting Tones on a Channel The tone groups that can be detected on a channel are listed in the [tone_detection] section of the root configuration file. To detect a tone group on a channel, the user application uses the PKX_CHANNEL_EnableToneDetection function. The parameters passed to this function are: The channel handle. The index to the tone group entries in the [tone_detection] section of the root configuration file. NOTE: If tone detection has been disabled using the PKX_CHANNEL_SetConfig API function, no tones will be collected until it is enabled. This applies only when using the AoH low-level product. When GP detects a tone group on the channel, a PKX_EVENT_CHANNEL_TONE_ON event is generated. The parameter fields of this event contain the following information: 8
Media Processing.3 Basic Functions Parameter Description Field p0 The index of the tone group that was detected. p1 Time, in milliseconds, since the last tone stopped being transmitted. Maximum duration is 32767 milliseconds with an accuracy of +/-6 milliseconds. p2 Not used. When GP detects a tone group is no longer being transmitted on the channel, a PKX_EVENT_CHANNEL_TONE_OFF event is generated. The parameter fields of this event contain the following information: Parameter Description Field p0 The index of the tone group that has stopped being transmitted. p1 Time, in milliseconds, since the tone group was detected. Maximum duration is 32767 milliseconds with an accuracy of +/-6 milliseconds. p2 Not used. To terminate the detection of a tone group on a channel, the user application uses the PKX_CHANNEL_DisableToneDetection function. The parameters passed to this function are: The channel handle. The index to the tone group entries in the [tone_detection] section of the root configuration file. Multiple tone groups can be enabled for detection at the same time on a single channel..3..7 Detecting Speech on a Channel To receive notifications of the detection or absence of speech on a channel, the user application calls the function PKX_CHANNEL_EnableSpeechDetection. When speech detection on the channel is enabled and speech is detected, a PKX_EVENT_CHANNEL_SPEECH_ON event is generated, and, when the absence of speech is detected, a PKX_EVENT_CHANNEL_SPEECH_OFF event is generated. The PKX_CHANNEL_DisableSpeechDetection function is called to turn off speech detection on a channel. The following diagram demonstrates when the 86
.3 Basic Functions Media Processing PKX_EVENT_CHANNEL_SPEECH_ON and PKX_EVENT_CHANNEL_SPEECH_OFF events are generated..3..8 Audio Flags An audio flag parameter is passed to the GP play and record functions. The audio flag specifies the encoding format, sampling rate, whether to play an initial beep tone prior to recording, and whether the sample is encoded with a WAVE header. The following table indicates which values can be set for each function: GP API Function Encoding Sampling Initial Beep Format Rate WAVE Header PKX_CHANNEL_PlayFile Required Required Ignored Allowed PKX_CHANNEL_PlayAddData Required Required Ignored Allowed PKX_CHANNEL_RecordFile Required Required Allowed Allowed PKX_CHANNEL_Record Required Required Allowed Ignored Required means a value must be specified for the function. Allowed means a value may be specified for that function. Ignored means the value is ignored for the function. Only one encoding format and one sampling rate may be used at a time. The encoding format, sampling rate, initial beep, and WAVE header values are ORed together. All the audio data buffers added for one play function must use the same encoding format and sampling rate. If audio data is added for a play function from files with the WAVE flag set, the audio format is extracted from the WAVE file header. All the encoding formats and sampling rates must be the 87
Media Processing.3 Basic Functions same in all the WAVE file headers for one play function. A PKX_ERROR_CHANNEL_INCONSISTENT_AUDIO_FORMAT error is returned when a data block is queued for a play request, where the queued block specifies a different audio format or sampling rate than a previously queued data block. This error is also returned when the PKX_AUDIO_WAVE_HEADER flag is specified for a data buffer. The encoding format values are: Encoding Format Description PKX_AUDIO_ENCODING_LINEAR_8BIT Linear 8-bit ITU PCM encoding (supported in AoB). PKX_AUDIO_ENCODING_LINEAR_16BIT Linear 16-bit ITU PCM encoding. PKX_AUDIO_ENCODING_MU_LAW North American mu-law ITU PCM encoding. PKX_AUDIO_ENCODING_A_LAW European a-law ITU PCM encoding. PKX_AUDIO_ENCODING_ADPCM_4BIT_PIKA Adaptive 4-bit PCM encoding. PKX_AUDIO_ENCODING_ADPCM_4BIT_DIALOGIC Dialogic OKI adaptive 4-bit PCM encoding. PKX_AUDIO_ENCODING_ADPCM_3BIT Adaptive 3-bit PCM encoding (supported in AoB). This format is not supported in files with WAVE headers. The PIKA and Dialogic ADPCM formats are identical, except the upper and lower nibbles of each byte are reversed. Linear encoding should be used when the data provided for playback is uncompressed linear PCM. The sampling rates are: Sampling Rates Description PKX_AUDIO_SAMPLING_RATE_4KHZ 4 khz sampling rate (supported in AoB) PKX_AUDIO_SAMPLING_RATE_6KHZ 6 khz sampling rate PKX_AUDIO_SAMPLING_RATE_8KHZ 8 khz sampling rate PKX_AUDIO_SAMPLING_RATE_11KHZ 11 khz sampling rate (supported in AoB) A sampling rate of 6 khz reduces the disk requirements for the stored audio, with a small reduction in the quality of the signal. 88
.3 Basic Functions Media Processing The PKX_AUDIO_BEEP_BEFORE_RECORDING flag tells the recording functions to play an initial beep tone prior to recording. The PKX_AUDIO_WAVE_HEADER flag tells the play and record functions the audio encoded is specified (or must be written to the file for record) in the WAVE file header. NOTE: This flag can only be used with the PKX_CHANNEL_PlayAddData function when the PKX_TAudioData field specifies a file location. Data buffer locations must not contain a WAVE header. Example Examples of setting audio flags are found in the Playing a Message Example (pg. 69) and the Recording a Message Example (pg. 7)..3..9 Media Processing Termination Conditions A number of functions specify termination conditions. The media function continues until any of the termination conditions specified are met. When a termination condition is met, an event is generated and the media processing that specified the termination condition ends. The p0 field of the event specifies function type that terminated. The following table lists the termination conditions, the event generated when the termination condition is met, and the value specified in the p1 field of the event. Termination Condition Description Event Generated digitmask Terminate the media function when any of the DTMF digits specified in the mask are received. PKX_EVENT_CHANNEL_TERM_ The DTMF digit DIGIT_MASK received maxdigits Terminate the media function when the specified number of digits has been received. PKX_EVENT_CHANNEL_TERM_ Number of digits MAX_DIGITS received timeout Terminate the media function when the specified period of time, in milliseconds, has passed. PKX_EVENT_CHANNEL_TERM_ Timeout period TIMEOUT Event p1 Value 89
Media Processing.3 Basic Functions initialsilencetimeout Terminate the media function when the PKX_EVENT_CHANNEL_TERM_ Initial specified period of initial silence (no digits INITSILENCE_TIMEOUT silence for digit collection or voice for recording), timeout in milliseconds, has passed. period silencetimeout Terminate the media function when the specified period of silence after receiving voice, in milliseconds, has passed. PKX_EVENT_CHANNEL_TERM_ Silence timeout SILENCE_TIMEOUT period nonsilencetimeout Terminate the media function when the specified period of non-silence (DTMF digit), in milliseconds, has been received. PKX_EVENT_CHANNEL_TERM_ Non-silence timeout NONSILENCE_TIMEOUT period interdigittimeout Terminate the media function when the specified amount of time after receiving a digit, in milliseconds, has passed. PKX_EVENT_CHANNEL_TERM_ Inter-digit timeout INTERDIGIT_TIMEOUT period Note: For the digitmask and maxdigits termination conditions, digits in the channel digit buffer are considered when determining if the termination condition has been met. See Collecting DTMF Digits (pg. 78) for more information on these termination conditions. For maxdigits, the value returned in p1 matches the value specified in the termination conditions of the media processing call. The timeout values returned in p1 also match the value specified in the termination conditions of the media processing call. The following table lists the values assigned to the p0 field of a termination condition met event: Event p0 Field Value Description Applicable Functions PKX_MEDIA_COLLECT_DIGITS The channel was collecting digits. PKX_CHANNEL_CollectDigits PKX_MEDIA_PLAY_AUDIO PKX_CHANNEL_Play The channel was playing audio. PKX_CHANNEL_PlayFile PKX_MEDIA_RECORD_AUDIO The channel was recording audio. PKX_CHANNEL_Record PKX_CHANNEL_RecordFile PKX_MEDIA_PLAY_TONE The channel was playing a tone. PKX_CHANNEL_PlayTone PKX_CHANNEL_PlayTonePattern The following table lists the media functions that specify termination conditions, and the termination conditions allowed 90
.3 Basic Functions Media Processing for each function: GP API Function Digit Mask Maximum Timeout Initial Silence Non- InterNumber Silence silence digit of Digits Timeout PKX_CHANNEL_CollectDigits Allowed Allowed Allowed PKX_CHANNEL_Play Allowed Allowed Allowed Allowed PKX_CHANNEL_PlayFile Allowed Allowed Allowed Allowed PKX_CHANNEL_PlayTone Allowed Allowed Allowed Allowed PKX_CHANNEL_PlayTonePattern Allowed Allowed Allowed Allowed PKX_CHANNEL_Record Allowed Allowed Allowed Allowed Allowed Allowed PKX_CHANNEL_RecordFile Allowed Allowed Allowed Allowed Allowed Allowed Allowed Allowed Allowed The following table lists the values that can be ORed together to create a digit mask and the corresponding DTMF keys: Mask Constant DTMF Key PKX_MEDIA_DTMF_DIGIT_1 1 PKX_MEDIA_DTMF_DIGIT_2 2 PKX_MEDIA_DTMF_DIGIT_3 3 PKX_MEDIA_DTMF_DIGIT_4 4 PKX_MEDIA_DTMF_DIGIT_ PKX_MEDIA_DTMF_DIGIT_6 6 PKX_MEDIA_DTMF_DIGIT_7 7 PKX_MEDIA_DTMF_DIGIT_8 8 PKX_MEDIA_DTMF_DIGIT_9 9 PKX_MEDIA_DTMF_DIGIT_0 0 PKX_MEDIA_DTMF_DIGIT_STAR * PKX_MEDIA_DTMF_DIGIT_POUND # PKX_MEDIA_DTMF_DIGIT_A A PKX_MEDIA_DTMF_DIGIT_B B 91
Conferencing PKX_MEDIA_DTMF_DIGIT_C C PKX_MEDIA_DTMF_DIGIT_D D.3 Basic Functions NOTE: Any termination condition involving DTMF digits will never be met if DTMF detection has been disabled using the PKX_CHANNEL_SetConfig API function. This applies only when using the AoH low-level product. Example Examples of setting termination conditions are found in the Recording A Message Example (pg. 7) and Collecting Digits Example (pg. 80). Examples of the events generated by the the termination conditions are found in the Record Termination Condition Example (pg. 76), Getting Digits Example (pg. 81), and Collecting Digits Termination Condition Example (pg. 82)..3.6 Conferencing A conference object is required when more than two channels must be joined together. The PKX_CONF_Create function creates a new conference object of the type specified. The conference types available are: Conference Type Description Low-level Support PKX_CONF_TYPE_SUMMATION The voices of all participants are added together and sent to each participant (minus that participant's own voice). AoH and AoB PKX_CONF_TYPE_SAMPLING AoB The loudest talker is delivered to each participant (the loudest talker hears the next loudest talker). When the conference object is created, conference members can be managed using the functions listed in the following table. These functions are asynchronous and return immediately. Low-level functions process the adding, changing, or removing of a conference member. When the action is complete, the low-level function generates an event. Failure of a conference function generates a PKX_EVENT_CONF_TASK_FAILED event. The p1 field of the event provides the PK_STATUS error code specifying the reason the function failed. 92
.3 Basic Functions Conferencing Function Description Event Generated PKX_CONF_AddMember Adds a channel to a conference. The channel conference configuration is specified as a parameter of type PKX_TConfMemberConfig to this function. PKX_EVENT_CONF_ MEMBER_ADDED PKX_CONF_ChangeMember Changes a channel conference configuration by passing in a new PKX_TConfMemberConfig structure. PKX_EVENT_CONF_ PKX_CONF_RemoveMember Removes a channel from a conference. PKX_EVENT_CONF_ MEMBER_MODIFIED MEMBER_REMOVED Configurable conference member parameters are: Conference Description Member Configuration Parameter type Type of member connection to make. PKX_CONF_MEMBER_TYPE_FULL - Full conference member with talking and listening privileges. PKX_CONF_MEMBER_TYPE_MONITOR - Listen-only member. inputgain Gain (in db) to apply to the voice from the member to the conference. Minimum - PKX_CONF_MEMBER_GAIN_MIN -120.0 Default - PKX_CONF_MEMBER_GAIN_DEFAULT 0.0 Maximum - PKX_CONF_MEMBER_GAIN_MAX 24.0 outputgain Gain (in db) to apply to the output of the conference to the member. Minimum - PKX_CONF_MEMBER_GAIN_MIN -120.0 Default - PKX_CONF_MEMBER_GAIN_DEFAULT 0.0 Maximum - PKX_CONF_MEMBER_GAIN_MAX 24.0 When a conference is created, it is unknown which low-level product library (AoH or AoB) is implementing the conference. The product configuration file that defines the first channel added to a conference determines the low-level product library used. After the low-level product for a conference has been determined, only channels controlled by that low-level product can be added to the conference. If the user application attempts to add a channel controlled by one low-level product library to a conference controlled by another low-level product library, the PKX_CONF_AddMember function returns a PKX_ERROR_CONF_INVALID_MEMBER status. 93
Conferencing.3 Basic Functions For example: a conference is created using the PKX_CONF_Create function. The first channel added to the conference is defined in the AoB product configuration file. The conference is implemented by the AoB product library. A second AoB-defined channel is added to the conference. This function succeeds and a PKX_EVENT_CONF_MEMBER_ADDED event is generated. Another channel is added to the conference but this time the channel is defined in the AoH product configuration file. The PKX_CONF_AddMember function returns with a status of PKX_ERROR_CONF_INVALID_MEMBER. No event is generated in response to the PKX_CONF_AddMember function call. Echo Cancellation When using the AoH low-level product, echo cancellation is automatically applied when a digital TDM channel is added to the conference. When using the AoB low-level product, echo cancellation is automatically applied when an RTP channel is added to the conference. When echo cancellation is enabled, there is a potential delay due to the distance between the echo canceller and the echo source, or tail. Delays can be fixed by setting a value for this tail for the TDM channel. See the parameter taillength under ISDN Resources in the PIKA GrandPrix Configuration Guide for more information on the value range and default. Example There are three examples; they are taken from the EventProcessing function in meetme.ccp source file of the Conferencing sample application. The first example demonstrates creating the conference. The second example demonstrates adding a member to a conference. The third example demonstrates removing a member from a conference..3.6.1 Create Conference Example */ // Create conference if it has not been created yet! if (g_system.conference.handle == PK_HANDLE_NONE) { g_system.conference.config.type = PKX_CONF_TYPE_SUMMATION; status = PKX_CONF_Create(&g_System.conference.config, &g_system.conference.handle); if (status!= PK_SUCCESS) { printf("pkx_conf_create() failed, status = [%s0x%04x] %sn", (status < 0? "-" : ""), -status, PKX_ERROR_GetText(status, errortext, sizeof(errortext))); cleanupcall(groupid, channelid); break; 94
.3 Basic Functions Conferencing /*.3.6.2 Add Member Example */ PK_STATUS status; PK_CHAR errortext[pkx_error_max_name_length]; PKX_TConfMemberConfig memberconfig; memset(&memberconfig, 0, sizeof(pkx_tconfmemberconfig)); memberconfig.type = g_system.group[groupid].channel[channelid].confmembertype; // Add member status = PKX_CONF_AddMember(g_System.conference.handle, g_system.group[groupid].channel[channelid].handle, &memberconfig); if (status!= PK_SUCCESS) { printf("pkx_conf_addmember(member 0x%08x) failed," " status = [%s0x%04x] %sn", (PK_UINT)g_System.group[groupId].channel[channelId].handle, (status < 0? "-" : ""), -status, PKX_ERROR_GetText(status, errortext, sizeof(errortext))); return PK_FALSE; return PK_TRUE; /*.3.6.3 Remove Member Example */ // Remove channel from conference if ((g_system.conference.handle!= PK_HANDLE_NONE) && (event.id == PKX_EVENT_CALL_DISCONNECTED)) { status = PKX_CONF_RemoveMember(g_System.conference.handle, (TPikaHandle)event.p0); if (status!= PK_SUCCESS) { printf("pkx_conf_removemember(0x%08x) failed," " status = [%s0x%04x] %sn", (PK_UINT)event.p0, (status < 0? "-" : ""), -status, PKX_ERROR_GetText(status, errortext, sizeof(errortext))); /* 9
Conferencing.3 Basic Functions.3.6.4 Virtual Channels in Conferences Virtual channels support the same media processing capabilities as physical channels, except they cannot make or accept calls. Virtual channels can be used in a conference for such applications as: playing the same announcement to all conference members recording audio from all conference members playing and recognizing tones from all conference members Virtual channels are created using the PKX_CHANNEL_Create function and destroyed using PKX_CHANNEL_Destroy function. Virtual channels must be removed frm a conference before they are destroyed. When the PKX_CHANNEL_Create function is used, it returns the virtual channel handle, unlike other channel types that use the PKX_CHANNEL_GetHandle function to return the channel handle. PKX_GROUP_GetConfig returns the number of currently created virtual channels. As shown in the following figure, the information flow between a physical channel and a virtual channel is opposite to the information flow between a physical channel and a conference member. If a recording is being played from a virtual channel to the conference, the information flows from the virtual channel to the physical channel to the conference members. If a recording is being made of the conference, the information flows from the conference members to the physical channel to the virtual channel. Example There are two examples; they are taken from the meetme.ccp source file of the Conferencing sample application. The first example demonstrates creating a virtual channel. The second example demonstrates destroying a virtual channel. 96
.3 Basic Functions Phones.3.6.4.1 Create Virtual Channel Example */ if (g_system.group[i].config.type == PKX_GROUP_TYPE_VIRTUAL) { PK_INT nextvirtchannel = g_system.group[i].config.numberofchannels; // Create a new virtual channel, place it at after the last existing // virtual channel status = PKX_CHANNEL_Create(g_System.group[i].handle, &g_system.group[i].channel[nextvirtchannel].handle); if (status!= PK_SUCCESS) { printf("pkx_channel_create(0x%08x) failed, status = [%s0x%04x] %sn", (PK_UINT)g_System.group[i].handle, (status < 0? "-" : ""), -status, PKX_ERROR_GetText(status, errortext, sizeof(errortext))); return PK_FALSE; g_system.group[i].config.numberofchannels++; g_system.group[i].channel[nextvirtchannel].state = PKX_CHANNEL_STATE_IN_USE; *handle = g_system.group[i].channel[nextvirtchannel].handle; return PK_TRUE; /*.3.6.4.2 Destroy Virtual Channel Example */ if (g_system.group[i].config.type == PKX_GROUP_TYPE_VIRTUAL) { for (j = 0; j < g_system.group[i].config.numberofchannels; j++) { status = PKX_CHANNEL_Destroy(g_System.group[i].channel[j].handle); if (status!= PK_SUCCESS) { printf("pkx_channel_destroy(0x%08x) failed, status = [%s0x%04x] %sn", (PK_UINT)g_System.group[i].handle, (status < 0? "-" : ""), -status, PKX_ERROR_GetText(status, errortext, sizeof(errortext))); return PK_FALSE; /*.3.7 Phones A phone channel does not have the same capabilities as other channels. The only functions a user application can 97
Phones.3 Basic Functions perform on a phone channel are: turn ringing on and off with the PKX_CHANNEL_RingingStart and PKX_CHANNEL_RingingStop functions. send caller identification information (as part of the PKX_CHANNEL_RingingStart function). detect hook state changes on the phone. Changes in hook state generate the following events: Phone Channel Event Description PKX_EVENT_CHANNEL_PHONE_HOOKFLASH Indicates the remote phone has just performed a hookflash. PKX_EVENT_CHANNEL_PHONE_OFFHOOK Indicates the remote phone has just gone offhook. PKX_EVENT_CHANNEL_PHONE_ONHOOK Indicates the remote phone has just gone onhook. See the Phone Resources section of the Configuration Guide for phone configuration parameters. Ringing a Channel To generate a ringing pattern on a channel, the user application uses the PKX_CHANNEL_RingingStart function. The parameters passed to this function are: The channel handle. The index into the entries of the [ring_pattern] section of the GP configuration file. This pattern is used to generate the ring pattern transmitted on a channel. The timeout period. Ringing continues until the far end answers or the timeout period expires. Caller information. The caller information to be displayed to the called party. The PKX_CHANNEL_RingingStart function also sends protocol-specific messages to the far-end device to indicate the called party should be alerted. If the call is not answered by the phone in the timeout period specified in the function call, the ringing is stopped and a PKX_EVENT_CHANNEL_DONE_RINGING event is raised. The p0 field of this event specifies the cause and is set to PKX_CALL_DROP_CAUSE_NOANSWER. If the phone is already offhook, the ringing is stopped and a PKX_EVENT_CHANNEL_DONE_RINGING event is raised. The p0 field of this event specifies the cause and is set to PKX_CALL_DROP_CAUSE_BUSY. 98
.3 Basic Functions Phones If the phone goes offhook while ringing, ringing is automatically stopped and no PKX_EVENT_CHANNEL_DONE_RINGING event is raised. Only the PKX_EVENT_CHANNEL_PHONE_OFFHOOK event is raised. The user application uses the PKX_CHANNEL_RingingStop to stop the ringing pattern from being sent to a channel. 99
6 6 Building a PIKA GrandPrix SDK Application To develop an application based on GP: Header files must be included in the application code to allow the code to compile. The GP library (Windows - libpikagpapi.lib, Linux - libpikagpapi.so) must be linked with the application code to create an executable. On Linux systems, the GP libraries must be built and installed. On Windows systems, pre-built libraries are installed with the GP component. GP is a multi-threaded product. Applications using GP must enable the multi-thread flag for Windows software projects. To test an application based on GP: The AoH, the AoB, or both components must be installed on the testing platform. When the PIKA cards are used, the cards must be installed on the testing platform. A license.keys file, licensing the appropriate resources, must be generated and copied to the testing platform. See the License Activation section of the PIKA AoH or AoB Getting Started Guide available at www.pikatechnologies.com for more information on generating the license.keys file. 6 Optionally, when the PIKA cards are used, pika.cfg files may be created to map card serial numbers to board identifiers. Optionally, environment variables may be set to specify directories, different from the defaults, for the location of configuration files and log files. Header Files - header files provide definitions of the functions and constants used by applications. Windows - On Windows development platforms, the header files can be found in the following folders: <PIKA GrandPrix SDK installation directory>\inc The default is: C:\Program Files\PIKA\GrandPrix\inc Linux - On Linux development platforms, the header file (pikagpapi.h) can be found in the following directory: /usr/include/pika Libraries - Libraries are linked statically or dynamically with the developer's code to create the user application. Windows - On Windows development platforms, the following libraries are provided: pikagpapi.lib - the static library used to link the user application The folder C:\WINDOWS\system32 contains dynamically loaded libraries used when executing the user application: libpikagpgwy.dll (for AllOnHost support) 100
6 libpikagpmm.dll (for AllOnBoard support) pikagpapi.dll The directory <PIKA GrandPrix SDK installation directory>\grandprix\debug contains debug versions of these libraries: libpikagpgwy.dll (for AllOnHost support) libpikagpmm.dll (for AllOnBoard support) pikagpapi.dll Linux - Binaries for the library files are not provided on Linux development platforms. The developer is responsible for building the libraries using the source code provided. To build the libraries: 1. Ensure the appropriate compiler, linker, and make executables can be found in the PATH environment variable. 2. Change directories by typing - cd /usr/share/pika/grandprix/source. 3. Execute the command: make [NOBUILD={aob aoh all] This command makes the required libraries for GP and the component(s) under the source directory: libpikagpapi.a and libpikagpapi.so.1.2.0 libpikagpgwy/libpikagpgwy.a and libpikagpgwy/libpikagpgwy.so.1.2.0 (for AllOnHost support) libpikagpmm/libpikagpmm.a and libpikagpmm/libpikagpmm.so.1.2.0 (for AllOnBoard support) The component (AllOnHost or AllOnBoard) must be installed on the development platform to make the library for that component. 4. Execute the command: make install [NOBUILD={aob aoh all] This command copies the libraries created by the previous command to the /usr/lib directory and creates the following symbolic links in that directory to these files: libpikagpapi.so->libpikagpapi.so.1.2.0 libpikagpgwy.so->libpikagpgwy.so.1.2.0 (for AllOnHost support) libpikagpmm.so->libpikagpmm.so.1.2.0 (for AllOnBoard support). The make commands check for the existence of the pikahmpapi.h and pikaapi.h files in the /usr/include directory to determine if AllOnHost and AllOnBoard respectively are to be built. The NOBUILD={ aoh aob all on the make or make install commands tell the make NOT to build AllOnHost or AllOnBoard (or both) libraries. Configuration Files - The following configuration files contain information that does not normally need to be changed. The default root configuration file contains includes for the following: 101 6
6 Root Configuration Include File Contains inccpa.cfg call progress parameters, see Call Progress in the PIKA GrandPrix Configuration Guide. inctonepatterns.cfg tone patterns and corresponding tone pattern generation parameters, see Tone Pattern Generation in the PIKA GrandPrix Configuration Guide. inctonegen.cfg tone generation and corresponding tone generation parameters, see Tone Generation in the PIKA GrandPrix Configuration Guide. inctonedet.cfg tone detection, see Tone Detection in the PIKA GrandPrix Configuration Guide. incringpatterns.cfg ring patterns and the corresponding ring pattern parameters, see Ring Patterns in the PIKA GrandPrix Configuration Guide. Environment Variables - The following environment variables can be optionally set when executing user applications on the PIKA GrandPrix SDK platform. Environment Variable Description PKX_BASE_DIR Specifies the directory where GP is installed. 6 Default Used If No Value Is Assigned to the Environment Variable Windows - C:\Program Files\PIKA\GrandPrix ( the C:\Program Files directory name is dependent on the OS language) Linux - /usr/share/pika/grandprix PKX_LOGS_DIR Specifies the base directory under which the log files are written. A separate sub-directory is created for each run of the user application. Windows - %PKX_BASE_DIR%\logs\ PKX_CONF_DIR Specifies the directory where the configuration files are located. Windows - %PKX_BASE_DIR%\conf Linux - /var/log/pika Linux - /etc/pika Linux only - Directory permissions GP is normally installed by the root user. This means the default log and configuration directories are owned by the root user. When user applications are run by a user other than root, the applications do not have permission to write in the log or configuration directories. To solve this problem, either: as the root user, change the permissions on these directories with the following commands: 102
6 chmod 777 <PKX_LOGS_DIR> chmod 777 <PKX_CONF_DIR> modify the values of the environment variables to point to directories in which the user running the application has write privileges. It is expected that applications running in production mode have root privileges or the application processes are the owners of the necessary directories. Application Tools - The following tools are provided with GP: GPTest: An application used to test and demonstrate GP functionality by allowing the user to perform functions from the command line, such as making a call, detecting DTMF tones, and creating switch connections. GPConfig: An application used to configure GP when using GP with AoH. GPDemo: An application used to allow the user to quickly execute a demonstration of the SIP capabilities of GP. Source Files - The source files required to make the GP libraries and the GPTest, GPConfig and GPDemo applications are provided in GP. Windows - The source code for GP libraries is provided in the <PIKA GrandPrix SDK installation directory>\source directory. The source code for the applications is provided in the <PIKA GrandPrix SDK installation directory>\source\applications\<application name> directory. Visual Studio 6 and Visual Studio 200 Professional 6 project files are included in the GP installation. The workspace files are located in the root source folder. Binaries are located in the source\debug and source\release folders. These workspaces are provided to allow the developer to modify and rebuild the libraries, and to build the gptest application. Linux - The source code for GP libraries is provided in the /usr/share/pika/grandprix/source directory.the source code for the applications is provided in the /usr/share/pika/grandprix/source/applications/<application name> directory. Makefiles are provided to create and recreate the libraries and applications. NOTE: Always copy the source to a private location before modifying it. Otherwise subsequent installations of GP overwrites any changes you have made. Compiling CAS XML Protocol Files - When using CAS interfaces, protocol files must be created to define the details of the protocol. See the PIKA GrandPrix Configuration Guide for more information on defining CAS protocol files. Before these protocol files can be used they must be compiled. There is a utility included in the PIKA AoB SDK installation directory (bin\smc.exe) that must be executed on the protocol files (in the montecarlo/conf/protocols folder) prior to using them. 103
7 7 Distributing a PIKA GrandPrix SDK Application The same user application can be deployed under either the Windows or Linux operating systems (OSs). The differences between the two OSs are: the applications must be compiled and linked under the appropriate OS. different library files must be redistributed. NOTE: Only one user application can be supported by GP on each deployment platform. To distribute a GP user application to a deployment platform: 1. Install the lower-level (AoH and/or AoB) redistribution files as described in the product Programmer's Guide. 2. Install any required boards. 3. Install the lower-level (AoH and/or AoB) drivers as described in the product Programmer's Guide. 4. Install the GP libraries. Windows - The following libraries must be copied to C:\Windows\System32 folder on the deployment platform: libpikagpapi.dll libpikagpgwy.dll (when AoH is used) libpikagpmm.dll (when AoB is used) 7 Linux - The following libraries must be copied to the deployment platform when dynamically linked libraries are used by the user application: libpikagpapi.so.1.2.0 libpikagpgwy.so.1.2.0 (when AoH is used) libpikagpmm.so.1.2.0 (when AoB is used). Install the configuration files. Copy the configuration files to the directory specified by the PKX_CONF_DIR environment variable. 6. Install the user application, as required. 7. If CAS is used, install the compiles CAS XML protocol files. 8. Generate and install the license keys as described in the product Getting Started Guide. 9. Set the environment variables (optional). If the configuration files or log files are going to be placed in locations other than the default location, the appropriate environment variable must be set to the new location. NOTE: Some systems require the current user to log out before new environment variables are available. 104
7 10. Reboot the deployment platform. 7 10
8.1 Configuring a Channel 8 Advanced Topics The following advanced topics are described: Configuring a Channel (pg. 106) Modifying the PIKA GrandPrix SDK Source Code (pg. 107) Bypassing the PIKA GrandPrix SDK to Make Low-level Function Calls (pg. 113) 8.1 Configuring a Channel Configuring a channel is optional and the default settings should be appropriate for most user applications. However, GP provides the ability to configure individual channels for specialized user applications. The PKX_CHANNEL_SetConfig function can be used to control how the recording and detection functions will operate on a channel. User applications should initialize the PKX_TChannelSettings structure by calling PKX_CHANNEL_GetConfig and passing in the channelsettings parameter. This guarantees that all fields (including fields added in later releases of this software) are set to proper default values. The user application may change the channel settings at any time unless the applicable media processing function is active on the channel. These configuration settings apply only to resources hosted by the AoH low-level product. Record Buffer Sizing The default size of the buffers used to retrieve recorded audio data is large (16 Kb), which may introduce a degree of 8 latency that is not acceptable to some user applications. If a user application requires the audio data in a more timely fashion, the channel may be configured to use smaller audio buffers. The application may change the size of the buffer used to collect recorded data by setting the buffersize field of the PKX_TChannelSettings parameter passed in to the PKX_CHANNEL_SetConfig function. This function may be issued at any time before recording is started. The minimum size of the buffer is specified in the product configuration file using the recordbuffersize parameter. If PKX_CHANNEL_SetConfig is called while recording is active on the channel, the error code PKX_ERROR_CHANNEL_RECORDING_ACTIVE will be returned. 106
8.2 Modifying PIKA GrandPrix SDK Source Detection Settings By default, GP controls the activation and deactivation of DTMF and tone detection. However, certain types of user applications may want to turn off tone or DTMF detection on a given channel to reduce CPU usage. For example, a SIP application which handles only INFO messages could turn off DTMF detection because digits are received out of band. Media termination conditions requiring tone and DTMF detection will be prevented if detection of tones and/or DTMF is disabled. For example, if detection of a DTMF digit is a termination condition for recording, DTMF detection must be enabled. 8.2 Modifying PIKA GrandPrix SDK Source Code PIKA provides the source code for GP. This allows you to modify GP to provide new features specific to a user application. The read-only source should be copied from its installation directory to a development directory and its permissions changed before it is modified. This prevents your modifications from being lost when GP is reloaded or upgraded. To take advantage of features in new releases of GP, modifications made by the developer to older versions of the source code must be merged with the new release. For information about building GP after modification, refer to sections Building the GrandPrix Libraries for Windows and Building the GrandPrix Libraries for Linux in the Getting Started Guide. Before modifying the GP source code, you must understand how the different threads that make up GP communicate. The main thread communicates with the product threads by creating events and injecting these events into the event queue of the appropriate product. The product threads retrieve these events, process them, and communicate the results to the main thread by creating result events and injecting them into the event queue. Lastly, the user application retrieves the result events from the queue to determine the result of the original function call. The following diagram demonstrates how the threads communicate. Functions in the green rectangle are AoB product thread functions. Functions in the yellow rectangle are AoH product thread functions. Functions in grey and red are executed in the user application thread. 107 8
8.2 Modifying PIKA GrandPrix SDK Source Example As an example of how to modify GP source code, a new function PKX_CONF_RemoveAllMembers is added to the interface. 8 This example demonstrates: adding a function to GP adding new methods to the conference object creating a new message to be sent to the product interfaces modifying both product threads to handle the new event type The following files need to be modified to implement this new function: Main thread functions: 108
8.2 Modifying PIKA GrandPrix SDK Source gp_conf.cpp cconference.h cconference.cpp include/pikaapi.h common/gpmsgs.h libpikagpgwy/cgatewayinterface.h libpikagpgwy/cgatewayinterface.cpp AoH thread functions: libpikagpmm/cmminterface.h libpikagpmm/cmminterface.cpp libpikagpgwy/cgatewaysystem.cpp AoH thread functions: libpikagpgwy/cgatewaysystem.cpp libpikagpmm/cmmsystem.cpp libpikagpmm/cmmsystem.cpp For windows only, the.def file needs to specify the new function calls to have them exported from the.dll. include/pikaapi.h - Define the new GP function. /* * Function: PKX_CONF_RemoveAllMembers * * Summary: * Removes all members from a conference. The user application receives a * PKX_EVENT_CONFERENCE_MEMBER_REMOVED for each member removed from the * conference. * * Parameters: * confhandle: * The handle to the conference retrieved through the * PKX_CONF_Create function. * * Return Values: * PKX_ERROR_OBJECT_INVALID_HANDLE: * The confhandle parameter does not refer to a valid * conference * PK_SUCCESS: * The function succeeded. * */ PK_STATUS PK_API PKX_CONF_RemoveAllMembers 8 109
8.2 Modifying PIKA GrandPrix SDK Source ( IN TPikaHandle confhandle, ); gp_conf.cpp - Implement the new function. This function calls the removeallmembers method of the conference object. // -----------------------------------------------------------------PK_STATUS PK_API PKX_CONF_RemoveAllMembers ( IN TPikaHandle confhandle, ) { PK_STATUS status = PK_SUCCESS; CLogging::Instance()->logApi(PKX_LOG_TYPE_IN_API, PKX_LOG_API_CALL, "PKX_CONF_RemoveAllMembers(IN confhandle %lu)", confhandle); CConference *conf; CHECK_DEVICE(CConference, confhandle, conf); if ((status = conf->removeallmembers())!= PK_SUCCESS) ISSUE_RESULT(status); ISSUE_RESULT(PK_SUCCESS); cconference.h - Define the new methods that are required. class CConfewrence() {... public:... PK_STATUS removeallmembers(); PK_STATUS deleteallmembers();... //CConference 8 cconference.cpp - Implement the methods in the conference object to provide the new functionality. // -----------------------------------------------------------------PK_STATUS CConference::removeAllMembers() { if (getobjectstate()!= PKX_OBJECT_STATE_RUNNING) return PKX_ERROR_SYSTEM_IS_NOT_RUNNING; return deleteallmembers(channel); // -----------------------------------------------------------------110
8.2 Modifying PIKA GrandPrix SDK Source PK_STATUS CConference::deleteAllMembers() { // Retrieve product interface object CProductInterface *productinterface = CProductMgr::Instance()->get(m_ProductId); if (productinterface == NULL) return PKX_ERROR_CONFIG_PRODUCT_NOT_LOADED; return productinterface->conferenceremoveallmembers(gethandle()); common/gpmsgs.h - Define a new event id used to send the new functionality from the main thread to the AoH and AoB product threads. #define INTERNAL_CONFERENCE_COMMAND_REMOVE_ALL_MEMBERS_EVENT PKX_PRODUCT_EVENT_MAKE_CODE(0x007) libpikagpgwy/cgatewayinterface.h - Define the new method required in the interface to the AoH product library virtual PK_STATUS conferenceremoveallmembers(tpikahandle conferencereference); libpikagpgwy/cgatewayinterface.cpp - Implement the new method required in the interface to the AoH product library. This method sends a new type of event (INTERNAL_CONFERENCE_COMMAND_REMOVE_ALL_MEMBERS_EVENT) to the AoH product thread. PK_STATUS CGatewayInterface::conferenceRemoveAllMembers(TPikaHandle conferencereference) { PKH_TPikaEvent event; ::memset(&event, 0, sizeof(pkh_tpikaevent)); event.id = INTERNAL_CONFERENCE_COMMAND_REMOVE_ALL_MEMBERS_EVENT; event.handle = PK_HANDLE_NONE; event.userdata = (PK_VOID *)PK_HANDLE_NONE; event.p0 = (PK_UINTPTR)conferenceReference; event.p1 = 0; event.p2 = 0; return CGatewaySystem::Instance()->injectEvent(&event); 8 libpikagpmm/cmminterface.h - Define the new method required in the interface to the AoB product library. virtual PK_STATUS conferenceremoveallmembers(tpikahandle conferencereference); libpikagpmm/cmminterface.cpp - Implement the new method required in the interface to the AoB product library. This method sends a new type of event (INTERNAL_CONFERENCE_COMMAND_REMOVE_ALL_MEMBERS_EVENT) to the AoB product thread. // -----------------------------------------------------------------PK_STATUS CMMInterface::conferenceRemoveMember(TPikaHandle conferencereference) 111
8.2 Modifying PIKA GrandPrix SDK Source { TPikaEvent event; ::memset(&event, 0, sizeof(tpikaevent)); event.id = INTERNAL_CONFERENCE_COMMAND_REMOVE_ALL_MEMBERS_EVENT; event.handle = PK_HANDLE_NONE; event.userdata = (PK_VOID *)PK_HANDLE_NONE; // Message is for system object event.p0 = (PK_VOID *)conferencereference; event.p1 = 0; event.p2 = 0; return CMMSystem::Instance()->injectEvent(&event); libpikagpgwy/cgatewaysystem.cpp - Add the case for handling of the new event type to the AoH thread event processing function. case PKX_CONFERENCE_CHANGE_MEMBER_EVENT: case PKX_CONFERENCE_REMOVE_MEMBER_EVENT: case PKX_CONFERENCE_REMOVE_ALL_MEMBERS_EVENT: case PKX_CONFERENCE_ADD_MEMBER_EVENT: { // Get conference if ((conference = getconference((tpikahandle)event->p0))!= NULL) { conference->onevent(event); else log(pkx_log_type_normal, PKX_LOG_ALL_ERROR, "CGatewaySystem::onEvent() - Invalid conference reference received: %d (p0 0x%08x, p1 0x%08x, p2 0x%08x)", event->id, event->p0, event->p1, event->p2); break; libpikagpgwy/cgatewaysystem.cpp - Eliminate each active member in the conference. The elimination of the member causes a PKX_EVENT_CONF_MEMBER_REMOVED to be sent to the user application. Add the following case immediately after the PKX_CONF_REMOVE_MEMBER_EVENT case in the 8 CConference::onEvent method: case PKX_CONFERENCE_REMOVE_ALL_MEMBERS_EVENT: { CConferenceMember *member = NULL; while ((member = (CConferenceMember *)m_activemembers.pop())!= NULL) { if ((status = eliminatemember(member))!= PK_SUCCESS) { log(pkx_log_type_normal, PKX_LOG_ALL_WARNING, "CConference::close() - Failed to destroy member of conference: %lu", m_externalref); break; 112
8.3 Bypassing the PIKA GrandPrix SDK to libpikagpmm/cmmsystem.cpp - Add the case for handling of the new event type to the AoB thread event processing function. case case case case // if PKX_CONFERENCE_CHANGE_MEMBER_EVENT: PKX_CONFERENCE_REMOVE_MEMBER_EVENT: PKX_CONFERENCE_REMOVE_ALL_MEMBERS_EVENT: PKX_CONFERENCE_ADD_MEMBER_EVENT: { Get conference ((conference = getconference((tpikahandle)event->p0))!= NULL) conference->onevent(event); else log(pkx_log_type_normal, PKX_LOG_ALL_ERROR, "CMMSystem::onEvent() - Invalid conference reference received: %d (p0 0x%08x, p1 0x%08x, p2 0x%08x)", event->id, event->p0, event->p1, event->p2); break; libpikagpmm/cmmsystem.cpp - Eliminate each active member in the conference. The elimination of the member causes a PKX_EVENT_CONF_MEMBER_REMOVED to be sent to the user application. Add the following case immediately after the PKX_CONF_REMOVE_MEMBER_EVENT case in the CConference::onEvent method case PKX_CONFERENCE_REMOVE_ALL_MEMBERS_EVENT: { CConferenceMember *member = NULL; while ((member = (CConferenceMember *)m_activemembers.pop())!= NULL) { if ((status = eliminatemember(member))!= PK_SUCCESS) { log(pkx_log_type_normal, PKX_LOG_ALL_WARNING, "CConference::close() - Failed to destroy member of conference: %lu", m_externalref); break; 8 8.3 Bypassing the PIKA GrandPrix SDK to Make Low-level Function Calls Some features of AoB and AoH are not available through GP (for example AoB FAX). To allow GP-based user applications to access AoB and AoH features, GP provides bypass functions to access low-level channel and conference resources. 113
8.3 Bypassing the PIKA GrandPrix SDK to The following types of bypass functions are provided: Bypass Function Description PKX_CHANNEL_EnableBypass Informs the high-level API the user application will be performing low-level functions on the channel resources. PKX_CHANNEL_GetBypassInfo Retrieves the low-level switching and resource handle information for the specified channel in a PKX_TChannelBypassInfo structure. AoB information retrieved: channel.switchdevice - Channel switch device identifier. channel.switchstream - Channel input/output switch stream number. channel.switchtimeslot - Channel input/output switch timeslot number. dspresourcehandle - Associated DSP resource handle (cast as TResourceHandle). AoH information retrieved: inputmediastreamhandle - Input media stream handle. outputmediastreamhandle - Output media stream handle. PKX_CHANNEL_DisableBypass Informs the high-level API the user application has finished performing low-level functions on the channel resources. PKX_CONF_EnableBypass Informs the high-level API the user application will be performing low-level functions on the conference resources. PKX_CONF_GetBypassInfo Retrieves the low-level resource handle information for the specified conference in a PKX_TConfBypassInfo structure. AoB information retrieved: confhandle - Conference group handle. AoH information retrieved: 8 confhandle - Conference group handle. PKX_CONF_DisableBypass Informs the high-level API the user application has finished performing low-level functions on the conference resources. The following restrictions apply to GP, AoH, and AoB function calls, with respect to the bypass enable and disable function calls: GP user applications can get the AoH and AoB resource information at any time. GP user applications must only use these resource handles between enable bypass and disable bypass function calls. 114
8.3 Bypassing the PIKA GrandPrix SDK to GP user applications must not use the bypassed channel or conference in any PKX_CHANNEL_xxx or PKX_CONF_xxx function call between enable bypass and disable bypass function calls. The xxx_getbypassinfo functions returns a structure (either PKX_TChannelBypassInfo or PKX_TConfBypassInfo) that contains: a field of type PKX_TProductLibrary. One of the following values is returned in this field: PKX_PRODUCT_LIBRARY_AOB - AoB product library. PKX_PRODUCT_LIBRARY_AOH - AoH product library. a union of the AoB and AoH resource information. PKX_TProductLibrary is an enumeration which lists the low-level product libraries supported. These values can be used to determine which fields in the PKX_TChannelBypassInfo and PKX_TConfBypassInfo structures to use when using the Bypass feature. The following diagram shows where the bypass and lower-level function calls may be used: 8 11
Retrieve Channel Resource Handles Example 8.3 Bypassing the PIKA GrandPrix SDK to Example The sample application, Receiving a FAX, demonstrates how to use the bypass feature of GP. In the initialization function, the user application retrieves the lower-level channel resource handles for the AoB 8 channels. The function recvfax (pg. 117) processes the incoming FAX using AoB function calls. After the FAX has been received, the bypass is disabled in the cleanupfax (pg. 121) function. 116
8.3 Bypassing the PIKA GrandPrix SDK to recvfax Function 8.3.1 Retrieve Channel Resource Handles Example */ // Retrieve the configuration of the group. This configuration information // includes the number and type of channels contained in the group. status = PKX_GROUP_GetConfig(g_System.group[i].handle, &g_system.group[i].config); if (status!= PK_SUCCESS) { printf("pkx_group_getconfig('%s') failed, status = [%s0x%04x] %sn", g_system.config.groupname[i], (status < 0? "-" : ""), -status, PKX_ERROR_GetText(status, errortext, sizeof(errortext))); return PK_FALSE; /* 8.3.2 recvfax Function Body Source PK_BOOL recvfax ( IN PK_INT groupid, IN PK_INT channelid ) { PK_STATUS status; PK_CHAR errortext[pkx_error_max_name_length]; TPikaHandle channelhandle = g_system.group[groupid].channel[channelid].handle; PKX_TChannelBypassInfo *bypassinfo = &g_system.group[groupid].channel[channelid].bypassinfo; 8 printf("ready to receive FAX with the following data:\n"); switch (bypassinfo->type) { case PKX_PRODUCT_LIBRARY_AOB: printf(" switchdevice: %u\n", bypassinfo->product.aob.channel.switchdevice); printf(" switchstream: %u\n", bypassinfo->product.aob.channel.switchstream); printf(" switchtimeslot: %u\n", bypassinfo->product.aob.channel.switchtimeslot); printf(" dspresourcehandle: %lu\n", bypassinfo->product.aob.dspresourcehandle); break; 117
recvfax Function 8.3 Bypassing the PIKA GrandPrix SDK to case PKX_PRODUCT_LIBRARY_AOH: printf(" inputstream: %lu\n", bypassinfo->product.aoh.inputmediastreamhandle); printf(" outputstream: %lu\n", bypassinfo->product.aoh.outputmediastreamhandle); break; default:; // Enable the bypass feature allowing us to execute low-level // functions on the channel resources. if ((status = PKX_CHANNEL_EnableBypass(channelHandle))!= PK_SUCCESS) { printf("pkx_channel_enablebypass(0x%08x) failed, status = [%s0x%04x] %s\n", (PK_UINT)channelHandle, (status < 0? "-" : ""), -status, PKX_ERROR_GetText(status, errortext, sizeof(errortext))); return PK_FALSE; TDeviceHandle dsphandle = PK_HANDLE_NONE; TResourceHandle faxhandle = PK_HANDLE_NONE; TResourceDesc resourceinfo; // Seize a fax resource from the same board as the channel. It is possible to // use fax dsp resources on other boards if an H.100 cable is used to connect // the physical cards in the server. PK_INT numberofdsps = PK_DSP_NumberOfDevices( bypassinfo->product.aob.channel.switchdevice); for (PK_INT dspid = 0; dspid < numberofdsps; dspid++) { dsphandle = PK_DSP_GetDeviceHandle( bypassinfo->product.aob.channel.switchdevice, dspid); if (dsphandle!= PK_HANDLE_NONE) { faxhandle = PK_DSP_DEVICE_SeizePort(dspHandle, PK_FAX); if (faxhandle!= PK_HANDLE_NONE) break; 8 if (faxhandle == PK_HANDLE_NONE) { printf("no fax resources available!\n"); return PK_FALSE; // Store the fax handle to allow the resource to be released when the fax // is complete. g_system.group[groupid].channel[channelid].faxhandle = faxhandle; // Retrieve the resource descriptor information (switching information, etc.) status = PK_DSP_PORT_GetResourceDesc(faxHandle, &resourceinfo); 118
8.3 Bypassing the PIKA GrandPrix SDK to recvfax Function if (status!= PK_SUCCESS) { printf("pk_dsp_port_getresourcedesc(0x%08x) failed," " status = [%s0x%04x] %s\n", (PK_UINT)faxHandle, (status < 0? "-" : ""), -status, PKX_ERROR_GetText(status, errortext, sizeof(errortext))); return PK_FALSE; // Set the fax event handler on the fax dsp resource retrieved above. status = PK_DSP_PORT_SetEventHandler( faxhandle, (PK_VOID *)channelhandle, FaxEventHandler); if (status!= PK_SUCCESS) { printf("pk_dsp_port_seteventhandler(0x%08x) failed," " status = [%s0x%04x] %s\n", (PK_UINT)faxHandle, (status < 0? "-" : ""), -status, PKX_ERROR_GetText(status, errortext, sizeof(errortext))); return PK_FALSE; // Connect the channel to the fax dsp resource. The fax resource must be able // to send and receive information on the channel, therefore a full-duplex // switch connection is required. status = PK_CTBUS_MakeConnection( bypassinfo->product.aob.channel.switchdevice, bypassinfo->product.aob.channel.switchstream, bypassinfo->product.aob.channel.switchtimeslot, resourceinfo.inport.stream, resourceinfo.inport.timeslot); if (status!= PK_SUCCESS) { printf("pk_ctbus_makeconnection(0x%08x) failed, status = [%s0x%04x] %s\n", (PK_UINT)faxHandle, (status < 0? "-" : ""), -status, PKX_ERROR_GetText(status, errortext, sizeof(errortext))); return PK_FALSE; status = PK_CTBUS_MakeConnection( bypassinfo->product.aob.channel.switchdevice, resourceinfo.outport.stream, resourceinfo.outport.timeslot, bypassinfo->product.aob.channel.switchstream, bypassinfo->product.aob.channel.switchtimeslot); if (status!= PK_SUCCESS) { printf("pk_ctbus_makeconnection(0x%08x) failed, status = [%s0x%04x] %s\n", (PK_UINT)faxHandle, 119 8
FAX Received Example 8.3 Bypassing the PIKA GrandPrix SDK to (status < 0? "-" : ""), -status, PKX_ERROR_GetText(status, errortext, sizeof(errortext))); return PK_FALSE; // Specify the file and document parameters to use for the incoming fax. TFaxDocumentParameters faxdocparms; faxdocparms.size = sizeof(tfaxdocumentparameters); faxdocparms.resolution = PK_FAX_RESOLUTION_HIGH; faxdocparms.encoding = PK_FAX_ENCODING_MMR; faxdocparms.pagewidth = PK_FAX_WIDTH_A4; status = PK_FAX_AddDocument(faxHandle, PK_FAX_RX_DOCUMENT, "testfax.tif", &faxdocparms); if (status!= PK_SUCCESS) { printf("pk_fax_adddocument(0x%08x) failed, status = [%s0x%04x] %s\n", (PK_UINT)faxHandle, (status < 0? "-" : ""), -status, PKX_ERROR_GetText(status, errortext, sizeof(errortext))); return PK_FALSE; // Start the fax reception. if ((status = PK_FAX_RxStart(faxHandle, NULL))!= PK_SUCCESS) { printf("pk_fax_rxstart(0x%08x) failed, status = [%s0x%04x] %s\n", (PK_UINT)faxHandle, (status < 0? "-" : ""), -status, PKX_ERROR_GetText(status, errortext, sizeof(errortext))); return PK_FALSE; return PK_TRUE; File faxrecv.cpp 8 8.3.3 FAX Received Example */ case APP_CHANNEL_FAX_RECEIVED: case APP_CHANNEL_FAX_FAILED: { if (event.id == APP_CHANNEL_FAX_RECEIVED) printf("channel 0x%08x: <-- APP_CHANNEL_FAX_RECEIVEDn", (PK_UINT)event.handle); else printf("channel 0x%08x: <-- APP_CHANNEL_FAX_FAILEDn", (PK_UINT)event.handle); 120
8.3 Bypassing the PIKA GrandPrix SDK to cleanupfax Function // Retrieve the indexes into the global data structure where the // channel information is stored. if (FindChannel(PK_HANDLE_NONE, event.handle, &groupid, &channelid)) { // Cleanup the fax usage. cleanupfax(groupid, channelid); break; /* 8.3.4 cleanupfax Function Body Source PK_BOOL cleanupfax ( IN PK_INT groupid, IN PK_INT channelid ) { PK_STATUS status; PK_CHAR errortext[pkx_error_max_name_length]; TPikaHandle channelhandle = g_system.group[groupid].channel[channelid].handle; TPikaHandle callhandle = g_system.group[groupid].call[channelid].handle; TResourceHandle faxhandle = g_system.group[groupid].channel[channelid].faxhandle; // Clear the fax handle entry stored by the recvfax function. g_system.group[groupid].channel[channelid].faxhandle = PK_HANDLE_NONE; // Disable the bypass feature returning the low-level resources to // Grand Prix control. if ((status = PKX_CHANNEL_DisableBypass(channelHandle))!= PK_SUCCESS) { printf("pkx_channel_disablebypass(0x%08x) failed," " status = [%s0x%04x] %s\n", (PK_UINT)channelHandle, (status < 0? "-" : ""), -status, PKX_ERROR_GetText(status, errortext, sizeof(errortext))); return PK_FALSE; 8 // Release the fax resources. if (faxhandle!= PK_HANDLE_NONE) { if ((status = PK_DSP_PORT_Release(faxHandle))!= PK_SUCCESS) { printf("pk_dsp_port_release(0x%08x) failed, status = [%s0x%04x] %s\n", (PK_UINT)faxHandle, (status < 0? "-" : ""), -status, PKX_ERROR_GetText(status, errortext, sizeof(errortext))); 121
cleanupfax Function 8.3 Bypassing the PIKA GrandPrix SDK to return PK_FALSE; // Terminate the incoming call once the fax has been successfully // received. status = PKX_CALL_Drop(callHandle, PKX_CALL_DROP_CAUSE_NORMAL); if (status!= PK_SUCCESS) { printf("pkx_call_drop(0x%08x) failed, status = [%s0x%04x] %s\n", (PK_UINT)callHandle, (status < 0? "-" : ""), -status, PKX_ERROR_GetText(status, errortext, sizeof(errortext))); return PK_FALSE; return PK_TRUE; File faxrecv.cpp 8 122
9 9 Sample Applications Sample applications for GP are available at PIKA's website. Each of these samples are made up of three source files: A main file - The main file is unique to each sample application. pk_thread.cpp - Shared by all sample applications. Operating system (Windows or Linux) specific functions are used by the main line processing to: Create a new thread Wait for the other thread to terminate pk_thread.h - Shared by all sample applications. This file defines process priorities and pk_thread.cpp functions. For each sample application the following information is provided: The make file used to build the application (Linux). The source code for the application. Visual Studio project files (Windows). The configuration files required for the application. readme.txt desscribing the sample 9 123
10 10 Glossary 10 124 Term Definition ADPCM Adaptive Differential Pulse Code Modulation A speech coding method that uses fewer bits than the traditional PCM. ADT Advanced Tone Detection the ability to detect tones and tones groups to determine what has picked up a call. a-law The PCM coding and companding standard used by European digital communications systems to modify the dynamic range of an analog signal for digitizing. AoB AllOnBoard PIKA s DSP media processing solution. AoH AllOnHost PIKA s host-based signal processing solution. API Application Programmer Interface software that allows an application program to carry out low-level functions. ASR Automatic Speech Recognition A user application that recognizes speech. These types of user applications interact with a caller, responding to spoken commands or information. BSD Licence Berkeley Software Distribution License An open source software licence defined by the Open Source Initiative. CAS Channel Associated Signaling Sometimes referred to as Robbed-Bit Signaling, CAS is a form of communication signaling that uses routing information to direct the payload of voice or data to its destination. This routing information is encoded and transmitted along the same link as the payload itself. This results in lower available bandwidth for the payload, normally reducing a 64 kbps timeslot to 4 kbps. Channels Are 64 kbps timeslots in an E1 or T1 signal. codec Coder/Decoder Converts analog signals to digital signals. CPU Central Processing Unit The processor in a computer. CTI Computer Telephony Integration db Decibel A logarithmic unit used to describe a ratio. DSP Digital Signal Processing Refers to the manipulation of analog signals, such as sound, that have been converted into a digital form. Also refers to special type of coprocessor designed for performing the mathematics involved in digital signal processing. DTMF Dual-Tone Multi-Frequency The system used by touch-tone telephones to encode keys. DTMF assigns a specific frequency (consisting of two separate tones) to each key, so each key can be easily identified.
10 E1 The European format for digital transmission. E1 carries 32 channels of 64 kbps, with 2 channels reserved for signaling and control. G.711 An ITU-T standard for audio companding, primarily used to encode analog telephony signals into digital signals. Defines a-law and mu-law companding. G.729 An audio data compression algorithm for voice that compresses voice audio to 8 kbps. Music or tones, such as DTMF or fax tones, cannot be transported reliably with this codec. GP GrandPrix The name of PIKA's high-level API providing an abstraction of call signalling (analog, digital, and IP) and call control for SIP (AoB and AoH), ISDN (AoB and AoH), CAS (AoB), and Analog with Caller-ID (AoB). HMP Host-based Media Processing Software that performs media processing tasks on general-purpose host hardware. HSP Host Signal Processing The use of general-purpose host hardware to perform signal processing functions, alleviating the need for special DSP hardware. Hz Hertz The unit of frequency. IP Internet Protocol The networking protocol used on the Internet. ISDN Integrated Services Digital Network A type of circuit-switched telephone network system, designed to allow digital transmission of voice and data over ordinary telephone copper wires, ISDN is a set of protocols for establishing and breaking circuit-switched connections, and for advanced call features for the user. ISO International Standards Organization International Organization for Standardization. ITU-T International Telecommunication Union - Telecommunications An international organization established to standardize and regulate international telecommunications. IVR Interactive Voice Response A automated telephony application that uses recorded messages and DTMF key tones to interact with a caller. LBO Line Build Out A power level that is set based on the distance from the board to the T1/E1 switch. If the board is close by, the board requires less power and the line build out value is lower; if the card is far away, the card requires more power and the line build out value is higher. The T1 service provider determines this setting. LGPL Lesser General Public License A license allowing for unrestricted redistribution of software. LSB Least Significant Bit MAC address Media Access Control address a unique 48-bit serial number. MF/R1 An ITU-T standard for call progress signaling tones. MSB Most Significant Bit 10 12
mu-law A standard analog signal companding algorithm used in digital communications systems of the North American and Japanese digital hierarchies to modify the dynamic range of an audio analog signal prior to digitizing. NAT Network Address Translation Rewrites the source and/or destination addresses of IP packets as they pass through a router or firewall. Most systems use NAT to enable multiple hosts on a private network to access the Internet using a single public IP address. NIC Network Interface Card A piece of computer hardware allowing computers to communicate over a network. Every network card has a unique 48-bit serial number called a Media Access Control (MAC) address. OS Operating System Software that controls the operation of a computer. PDF Portable Document Format A proprietary file format developed by Adobe Systems for representing two-dimensional documents in a device-independent and resolution-independent format. PCM Pulse Code Modulation A method of encoding an audio signal in a digital format. POTS Plain Ordinary Telephone Service The service available from analog telephones prior to the introduction of digital telephone exchanges. PSTN Public Switched Telephone Network The network of the world's public, circuit-switched telephone networks. RPORT Specified in RFC 381, the rport feature allows a client to request the server send the response back to the source IP address and port from which the request originated. RTCP Real-time Transport Control Protocol Defined in RFC 30 to provide out-of-band control information for an RTP flow. RTP Real-time Transport Protocol Defined in RFC 1889 to provide end-to-end network transport functions suitable for applications transmitting real-time data, such as audio. SDK Software Development Kit A set of development tools that allows a software engineer to create applications for a certain software package, software framework, or hardware platform. SIP Session Initiated Protocol A protocol for initiating, modifying, and terminating an interactive user session that involves multimedia elements such as voice. Span Acts as the system interface to the TDM network. State Machine A finite state machine (FSM) or finite automaton is a model of behavior composed of states, transitions, and actions. T1 A standard in telecommunications in North America and Japan to transmit voice and data between devices. TDM Time Division Multiplexing A method for sending multiple digital signals along a single telecommunications transmission path. telco Telephone Company A supplier of telephone services and primary rate lines. 10 126 10
10 UA User Agent The client application used with a network protocol, such as SIP. UDP User Datagram Protocol Programs on networked computers can send short messages known as datagrams to one another. UDP does not provide the reliability and ordering guarantees. Datagrams may arrive out of order or go missing without notice. VoIP Voice over IP The routing of voice conversations over the Internet or any other IP-based network. V-Engine A daughter card with 6 DSPs that can be optionally installed on Daytona or PrimeNet MM Boards. WAVE Header The WAVE header provides the following information as a header for a.wav file: Offset-Length-Contents 0-4 bytes - "RIFF" 4-4 bytes - file length - 8 (i.e., the length of the file minus the length of the first two entries) 8-4 bytes - WAVE Header "WAVE" 12-4 bytes - Format header "fmt" 16-4 bytes - 0x00000010 The length of the fmt header data (16 bytes) 20-2 bytes - 0x0001 The format type: 1 means PCM 22-2 bytes - The number of channels: 1 for mono, 2 for stereo 24-4 bytes - Sampling rate (for example 8000) 28-4 bytes - Bytes per second // sample rate * block align 32-2 bytes - Block alignment 34-2 bytes - Bits per sample, either 8 or 16 36-4 bytes - Date header 'data' 40-4 bytes - Date length in bytes 44-Data length - Audio data XML extensible Markup Language a W3C-recommended general purpose markup language that supports a wide variety of applications. It is a simplified subset of Standard Generalized Markup Language (SGML). It is used to facilitate data sharing across different information systems. 10 127
11 Index A D Design Guidelines 13 Destroy Virtual Channel Example 97 Add Member Example 9 Advanced Topics 106 API Principles 11 Append Recorded Data to a Buffer Example 77 Detecting Speech on a Channel 86 Detecting Tones on a Channel 8 Distributing a PIKA GrandPrix SDK Application 104 Dropping a Call Example 60 Application Development 11 Application Logging 24 Assumed Knowledge 4 Audio Flags 87 B Basic Functions 1 Building a PIKA GrandPrix SDK Application 100 Bypassing the PIKA GrandPrix SDK to Make Low-level Function Calls 113 E Event Queue 21 F FAX Received Example 120 G Generating Tones on a Channel 83 Getting Digits Example 81 C Glossary 124 Call Analysis 36 GrandPrix Object Descriptions 7 Call Initiation Examples 43 GrandPrix SDK Architecture 6 Call Processing 28 GrandPrix SDK Object Relationships 9 Call Transfer 0 Called and Calling Number Formats 40 I cleanupfax 121 Incoming Call Example 47 Collecting Digits Example 80 Initiating a Call 32 Collecting Digits Termination Conditions Example 82 Initiating a Call Example 44 Collecting DTMF Digits From a Channel 78 Initiating a Call Setup Example 43 Conferencing 92 Initiating a Skype Call Example 63 Configuring a Channel 106 Introduction 3 Contacting PIKA Technologies 2 Copyright Information 1 J Create Conference Example 94 Joining Calls 49 Create Virtual Channel Example 97 a
L T Log File Management 2 Terminating a Call 7 11 Terminating a Call Example 9 M Media Processing 63 U Media Processing Termination Conditions 89 User Application Logging 27 Modifying PIKA GrandPrix SDK Source Code 107 V P Virtual Channels in Conferences 96 Phones 97 Play Buffers Example - Add data to Buffer 70 W Play Buffers Example - Play Buffers In Sequence 71 Wait On Event Example 24 Playing a Message Example 69 Playing a Stored Message 64 Purpose and Scope 4 R Receiving a Call 4 Record Termination Conditions Example 76 Recording a Message Example 7 Recording Audio Data From a Channel 71 recvfax 117 Related Documentation Remove Member Example 9 Retrieve Channel Resource Handles Example 117 S Sample Applications 123 Sending DTMF Digits to a Channel 83 Skype Calls 61 System Object States 9 System Start 1 System Start-up Example 18 b