/* 
 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 */
#ifndef __PJMEDIA_TONEGEN_PORT_H__
#define __PJMEDIA_TONEGEN_PORT_H__

/**
 * @file tonegen.h
 * @brief Tone (sine, MF, DTMF) generator media port.
 */
#include <pjmedia/port.h>


/**
 * @defgroup PJMEDIA_MF_DTMF_TONE_GENERATOR Multi-frequency tone generator
 * @ingroup PJMEDIA_PORT
 * @brief Multi-frequency tone generator
 * @{
 *
 * This page describes tone generator media port. A tone generator can be
 * used to generate a single frequency sine wave or dual frequency tones
 * such as DTMF.
 *
 * The tone generator media port provides two functions to generate tones.
 * The function #pjmedia_tonegen_play() can be used to generate arbitrary
 * single or dual frequency tone, and #pjmedia_tonegen_play_digits() is
 * used to play digits such as DTMF. Each tone specified in the playback
 * function has individual on and off signal duration that must be
 * specified by application.
 *
 * In order to play digits such as DTMF, the tone generator is equipped
 * with digit map, which contain information about the frequencies of
 * the digits. The default digit map is DTMF (0-9,a-d,*,#), but application
 * may specifiy different digit map to the tone generator by calling
 * #pjmedia_tonegen_set_digit_map() function.
 */

PJ_BEGIN_DECL


/**
 * This structure describes individual MF digits to be played
 * with #pjmedia_tonegen_play().
 */
typedef struct pjmedia_tone_desc
{
    short   freq1;          /**< First frequency.                           */
    short   freq2;          /**< Optional second frequency.                 */
    short   on_msec;        /**< Playback ON duration, in miliseconds.      */
    short   off_msec;       /**< Playback OFF duration, ini miliseconds.    */
    short   volume;         /**< Volume (1-32767), or 0 for default, which
                                 PJMEDIA_TONEGEN_VOLUME will be used.       */
    short   flags;          /**< Currently internal flags, must be 0        */
} pjmedia_tone_desc;



/**
 * This structure describes individual MF digits to be played
 * with #pjmedia_tonegen_play_digits().
 */
typedef struct pjmedia_tone_digit
{
    char    digit;          /**< The ASCI identification for the digit.     */
    short   on_msec;        /**< Playback ON duration, in miliseconds.      */
    short   off_msec;       /**< Playback OFF duration, ini miliseconds.    */
    short   volume;         /**< Volume (1-32767), or 0 for default, which
                                 PJMEDIA_TONEGEN_VOLUME will be used.       */
} pjmedia_tone_digit;


/**
 * This structure describes the digit map which is used by the tone generator
 * to produce tones from an ASCII digits.
 * Digit map used by a particular tone generator can be retrieved/set with
 * #pjmedia_tonegen_get_digit_map() and #pjmedia_tonegen_set_digit_map().
 */
typedef struct pjmedia_tone_digit_map
{
    unsigned count;         /**< Number of digits in the map.           */

    struct {
        char    digit;      /**< The ASCI identification for the digit. */
        short   freq1;      /**< First frequency.                       */
        short   freq2;      /**< Optional second frequency.             */
    } digits[16];           /**< Array of digits in the digit map.      */
} pjmedia_tone_digit_map;


/**
 * Tone generator options.
 */
enum
{
    /**
     * Play the tones in loop, restarting playing the first tone after
     * the last tone has been played.
     */
    PJMEDIA_TONEGEN_LOOP    = 1,

    /**
     * Disable mutex protection to the tone generator.
     */
    PJMEDIA_TONEGEN_NO_LOCK = 2
};


/**
 * Create an instance of tone generator with the specified parameters.
 * When the tone generator is first created, it will be loaded with the
 * default digit map.
 *
 * @param pool              Pool to allocate memory for the port structure.
 * @param clock_rate        Sampling rate.
 * @param channel_count     Number of channels. Currently only mono and stereo
 *                          are supported.
 * @param samples_per_frame Number of samples per frame.
 * @param bits_per_sample   Number of bits per sample. This version of PJMEDIA
 *                          only supports 16bit per sample.
 * @param options           Option flags. Application may specify 
 *                          PJMEDIA_TONEGEN_LOOP to play the tone in a loop.
 * @param p_port            Pointer to receive the port instance.
 *
 * @return                  PJ_SUCCESS on success, or the appropriate
 *                          error code.
 */
PJ_DECL(pj_status_t) pjmedia_tonegen_create(pj_pool_t *pool,
                                            unsigned clock_rate,
                                            unsigned channel_count,
                                            unsigned samples_per_frame,
                                            unsigned bits_per_sample,
                                            unsigned options,
                                            pjmedia_port **p_port);


/**
 * Create an instance of tone generator with the specified parameters.
 * When the tone generator is first created, it will be loaded with the
 * default digit map.
 *
 * @param pool              Pool to allocate memory for the port structure.
 * @param name              Optional name for the tone generator.
 * @param clock_rate        Sampling rate.
 * @param channel_count     Number of channels. Currently only mono and stereo
 *                          are supported.
 * @param samples_per_frame Number of samples per frame.
 * @param bits_per_sample   Number of bits per sample. This version of PJMEDIA
 *                          only supports 16bit per sample.
 * @param options           Option flags. Application may specify 
 *                          PJMEDIA_TONEGEN_LOOP to play the tone in a loop.
 * @param p_port            Pointer to receive the port instance.
 *
 * @return                  PJ_SUCCESS on success, or the appropriate
 *                          error code.
 */
PJ_DECL(pj_status_t) pjmedia_tonegen_create2(pj_pool_t *pool,
                                             const pj_str_t *name,
                                             unsigned clock_rate,
                                             unsigned channel_count,
                                             unsigned samples_per_frame,
                                             unsigned bits_per_sample,
                                             unsigned options,
                                             pjmedia_port **p_port);


/**
 * Check if the tone generator is still busy producing some tones.
 *
 * @param tonegen           The tone generator instance.
 *
 * @return                  Non-zero if busy.
 */
PJ_DECL(pj_bool_t) pjmedia_tonegen_is_busy(pjmedia_port *tonegen);


/**
 * Instruct the tone generator to stop current processing.
 *
 * @param tonegen           The tone generator instance.
 *
 * @return                  PJ_SUCCESS on success.
 */
PJ_DECL(pj_status_t) pjmedia_tonegen_stop(pjmedia_port *tonegen);


/**
 * Instruct the tone generator to stop looping of the current tone set.
 *
 * @param tonegen           The tone generator instance.
 *
 * @return                  PJ_SUCCESS on success.
 */
PJ_DECL(pj_status_t) pjmedia_tonegen_stop_loop(pjmedia_port *tonegen);


/**
 * Rewind the playback. This will start the playback to the first
 * tone in the playback list.
 *
 * @param tonegen           The tone generator instance.
 *
 * @return                  PJ_SUCCESS on success.
 */
PJ_DECL(pj_status_t) pjmedia_tonegen_rewind(pjmedia_port *tonegen);


/**
 * Instruct the tone generator to play single or dual frequency tones 
 * with the specified duration. The new tones will be appended to currently
 * playing tones, unless #pjmedia_tonegen_stop() is called before calling
 * this function. The playback will begin as soon as  the first get_frame()
 * is called to the generator.
 *
 * @param tonegen           The tone generator instance.
 * @param count             The number of tones in the array.
 * @param tones             Array of tones to be played.
 * @param options           Option flags. Application may specify 
 *                          PJMEDIA_TONEGEN_LOOP to play the tone in a loop.
 *
 * @return                  PJ_SUCCESS on success, or PJ_ETOOMANY if
 *                          there are too many digits in the queue.
 */
PJ_DECL(pj_status_t) pjmedia_tonegen_play(pjmedia_port *tonegen,
                                          unsigned count,
                                          const pjmedia_tone_desc tones[],
                                          unsigned options);

/**
 * Instruct the tone generator to play multiple MF digits with each of
 * the digits having individual ON/OFF duration. Each of the digit in the
 * digit array must have the corresponding descriptor in the digit map.
 * The new tones will be appended to currently playing tones, unless 
 * #pjmedia_tonegen_stop() is called before calling this function. 
 * The playback will begin as soon as the first get_frame() is called 
 * to the generator.
 *
 * @param tonegen           The tone generator instance.
 * @param count             Number of digits in the array.
 * @param digits            Array of MF digits.
 * @param options           Option flags. Application may specify 
 *                          PJMEDIA_TONEGEN_LOOP to play the tone in a loop.
 *
 * @return                  PJ_SUCCESS on success, or PJ_ETOOMANY if
 *                          there are too many digits in the queue, or
 *                          PJMEDIA_RTP_EINDTMF if invalid digit is
 *                          specified.
 */
PJ_DECL(pj_status_t) pjmedia_tonegen_play_digits(pjmedia_port *tonegen,
                                                 unsigned count,
                                                 const pjmedia_tone_digit digits[],
                                                 unsigned options);


/**
 * Get the digit-map currently used by this tone generator.
 *
 * @param tonegen           The tone generator instance.
 * @param m                 On output, it will be filled with the pointer to
 *                          the digitmap currently used by the tone generator.
 *
 * @return                  PJ_SUCCESS on success.
 */
PJ_DECL(pj_status_t) pjmedia_tonegen_get_digit_map(pjmedia_port *tonegen,
                                                   const pjmedia_tone_digit_map **m);


/**
 * Set digit map to be used by the tone generator.
 *
 * @param tonegen           The tone generator instance.
 * @param m                 Digitmap to be used by the tone generator.
 *
 * @return                  PJ_SUCCESS on success.
 */
PJ_DECL(pj_status_t) pjmedia_tonegen_set_digit_map(pjmedia_port *tonegen,
                                                   pjmedia_tone_digit_map *m);


PJ_END_DECL

/**
 * @}
 */


#endif  /* __PJMEDIA_TONEGEN_PORT_H__ */

