/* 
 * 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_SESSION_H__
#define __PJMEDIA_SESSION_H__


/**
 * @file session.h
 * @brief Media Session.
 */

#include <pjmedia/endpoint.h>
#include <pjmedia/stream.h>
#include <pjmedia/sdp.h>

PJ_BEGIN_DECL 

/**
 * @defgroup PJMEDIA_SESSION Media Sessions
 * @brief Management of media sessions
 * @{
 *
 * A media session represents multimedia communication between two
 * parties. A media session represents the multimedia session that
 * is described by SDP session descriptor. A media session consists 
 * of one or more media streams (pjmedia_stream), where each stream 
 * represents one media line (m= line) in SDP.
 *
 * This module provides functions to create and manage multimedia
 * sessions.
 *
 * Application creates the media session by calling #pjmedia_session_create(),
 * normally after it has completed negotiating both SDP offer and answer.
 * The session creation function creates the media session (including
 * media streams) based on the content of local and remote SDP.
 */


/**
 * Session info, retrieved from a session by calling
 * #pjmedia_session_get_info().
 */
struct pjmedia_session_info
{
    /** Number of streams. */
    unsigned            stream_cnt;

    /** Individual stream info. */
    pjmedia_stream_info stream_info[PJMEDIA_MAX_SDP_MEDIA];
};


/** 
 * Opaque declaration of media session. 
 */
typedef struct pjmedia_session pjmedia_session;


/**
 * @see pjmedia_session_info.
 */
typedef struct pjmedia_session_info pjmedia_session_info;


/**
 * This function will initialize the session info based on information
 * in both SDP session descriptors. The remaining information will be
 * taken from default codec parameters. If socket info array is specified,
 * the socket will be copied to the session info as well.
 *
 * @param pool          Pool to allocate memory.
 * @param endpt         Pjmedia endpoint.
 * @param max_streams   Maximum number of stream infos to be created.
 * @param si            Session info structure to be initialized.
 * @param local         Local SDP session descriptor.
 * @param remote        Remote SDP session descriptor.
 *
 * @return              PJ_SUCCESS if stream info is successfully initialized.
 */
PJ_DECL(pj_status_t)
pjmedia_session_info_from_sdp( pj_pool_t *pool,
                               pjmedia_endpt *endpt,
                               unsigned max_streams,
                               pjmedia_session_info *si,
                               const pjmedia_sdp_session *local,
                               const pjmedia_sdp_session *remote);


/**
 * This function will initialize the stream info based on information
 * in both SDP session descriptors for the specified stream index. 
 * The remaining information will be taken from default codec parameters. 
 * If socket info array is specified, the socket will be copied to the 
 * session info as well.
 *
 * @param si            Stream info structure to be initialized.
 * @param pool          Pool to allocate memory.
 * @param endpt         PJMEDIA endpoint instance.
 * @param local         Local SDP session descriptor.
 * @param remote        Remote SDP session descriptor.
 * @param stream_idx    Media stream index in the session descriptor.
 *
 * @return              PJ_SUCCESS if stream info is successfully initialized.
 */
PJ_DECL(pj_status_t)
pjmedia_stream_info_from_sdp( pjmedia_stream_info *si,
                              pj_pool_t *pool,
                              pjmedia_endpt *endpt,
                              const pjmedia_sdp_session *local,
                              const pjmedia_sdp_session *remote,
                              unsigned stream_idx);

/**
 * Create media session based on the local and remote SDP. After the session
 * has been created, application normally would want to get the media port 
 * interface of each streams, by calling #pjmedia_session_get_port(). The 
 * media port interface exports put_frame() and get_frame() function, used
 * to transmit and receive media frames from the stream.
 *
 * Without application calling put_frame() and get_frame(), there will be 
 * no media frames transmitted or received by the session.
 * 
 * @param endpt         The PJMEDIA endpoint instance.
 * @param si            Session info containing stream count and array of
 *                      stream info. The stream count indicates how many
 *                      streams to be created in the session.
 * @param transports    Array of media stream transports, with 
 *                      sufficient number of elements (one for each stream).
 * @param user_data     Arbitrary user data to be kept in the session.
 * @param p_session     Pointer to receive the media session.
 *
 * @return              PJ_SUCCESS if media session can be created 
 *                      successfully.
 */
PJ_DECL(pj_status_t) 
pjmedia_session_create( pjmedia_endpt *endpt, 
                        const pjmedia_session_info *si,
                        pjmedia_transport *transports[],
                        void *user_data,
                        pjmedia_session **p_session );


/**
 * Get media session info of the session.
 *
 * @param session       The session which info is being queried.
 * @param info          Pointer to receive session info.
 *
 * @return              PJ_SUCCESS on success.
 */
PJ_DECL(pj_status_t) pjmedia_session_get_info( pjmedia_session *session,
                                               pjmedia_session_info *info );

/**
 * Get user data of the session.
 *
 * @param session       The session being queried.
 *
 * @return              User data of the session.
 */
PJ_DECL(void*) pjmedia_session_get_user_data( pjmedia_session *session);


/**
 * Activate all streams in media session for the specified direction.
 * Application only needs to call this function if it previously paused
 * the session.
 *
 * @param session       The media session.
 * @param dir           The direction to activate.
 *
 * @return              PJ_SUCCESS if success.
 */
PJ_DECL(pj_status_t) pjmedia_session_resume(pjmedia_session *session,
                                            pjmedia_dir dir);


/**
 * Suspend receipt and transmission of all streams in media session
 * for the specified direction.
 *
 * @param session       The media session.
 * @param dir           The media direction to suspend.
 *
 * @return              PJ_SUCCESS if success.
 */
PJ_DECL(pj_status_t) pjmedia_session_pause(pjmedia_session *session,
                                           pjmedia_dir dir);

/**
 * Suspend receipt and transmission of individual stream in media session
 * for the specified direction.
 *
 * @param session       The media session.
 * @param index         The stream index.
 * @param dir           The media direction to pause.
 *
 * @return              PJ_SUCCESS on success.
 */
PJ_DECL(pj_status_t) pjmedia_session_pause_stream( pjmedia_session *session,
                                                   unsigned index,
                                                   pjmedia_dir dir);

/**
 * Activate individual stream in media session for the specified direction.
 *
 * @param session       The media session.
 * @param index         The stream index.
 * @param dir           The media direction to activate.
 *
 * @return              PJ_SUCCESS on success.
 */
PJ_DECL(pj_status_t) pjmedia_session_resume_stream(pjmedia_session *session,
                                                   unsigned index,
                                                   pjmedia_dir dir);

/**
 * Send RTCP SDES for the session.
 *
 * @param session       The media session.
 *
 * @return              PJ_SUCCESS on success.
 */
PJ_DECL(pj_status_t) 
pjmedia_session_send_rtcp_sdes( const pjmedia_session *session );

/**
 * Send RTCP BYE for the session.
 *
 * @param session       The media session.
 *
 * @return              PJ_SUCCESS on success.
 */
PJ_DECL(pj_status_t) 
pjmedia_session_send_rtcp_bye( const pjmedia_session *session );

/**
 * Enumerate media streams in the session.
 *
 * @param session       The media session.
 * @param count         On input, specifies the number of elements in
 *                      the array. On output, the number will be filled
 *                      with number of streams in the session.
 * @param strm_info     Array of stream info.
 *
 * @return              PJ_SUCCESS on success.
 */
PJ_DECL(pj_status_t) 
pjmedia_session_enum_streams( const pjmedia_session *session,
                              unsigned *count, 
                              pjmedia_stream_info strm_info[]);


/**
 * Get the media port interface of the specified stream. The media port
 * interface declares put_frame() and get_frame() function, which is the 
 * only  way for application to transmit and receive media frames from the
 * stream.
 *
 * @param session       The media session.
 * @param index         Stream index.
 * @param p_port        Pointer to receive the media port interface for
 *                      the specified stream.
 *
 * @return              PJ_SUCCESS on success.
 */
PJ_DECL(pj_status_t) pjmedia_session_get_port( pjmedia_session *session,
                                               unsigned index,
                                               pjmedia_port **p_port);


/**
 * Get session statistics. The stream statistic shows various
 * indicators such as packet count, packet lost, jitter, delay, etc.
 * See also #pjmedia_session_get_stream_stat_jbuf()
 *
 * @param session       The media session.
 * @param index         Stream index.
 * @param stat          Stream statistic.
 *
 * @return              PJ_SUCCESS on success.
 */
PJ_DECL(pj_status_t) pjmedia_session_get_stream_stat(pjmedia_session *session,
                                                     unsigned index,
                                                     pjmedia_rtcp_stat *stat);


/**
 * Reset session statistics.
 *
 * @param session       The media session.
 * @param index         Stream index.
 *
 * @return              PJ_SUCCESS on success.
 */
PJ_DECL(pj_status_t) pjmedia_session_reset_stream_stat(pjmedia_session *session,
                                                       unsigned index);


#if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0)
/**
 * Get extended session statistics. The extended statistic shows reports
 * from RTCP XR, such as per interval statistics summary (packet count, 
 * packet lost, jitter, etc), VoIP metrics (delay, quality, etc)
 *
 * @param session       The media session.
 * @param index         Stream index.
 * @param stat_xr       Stream extended statistics.
 *
 * @return              PJ_SUCCESS on success.
 */
PJ_DECL(pj_status_t) pjmedia_session_get_stream_stat_xr(
                                             pjmedia_session *session,
                                             unsigned index,
                                             pjmedia_rtcp_xr_stat *stat_xr);
#endif


/**
 * Get current jitter buffer state for the specified stream.
 * See also #pjmedia_session_get_stream_stat()
 *
 * @param session       The media session.
 * @param index         Stream index.
 * @param state         Jitter buffer state.
 *
 * @return              PJ_SUCCESS on success.
 */
PJ_DECL(pj_status_t) pjmedia_session_get_stream_stat_jbuf(
                                            pjmedia_session *session,
                                            unsigned index,
                                            pjmedia_jb_state *state);

/**
 * Dial DTMF digit to the stream, using RFC 2833 mechanism.
 *
 * @param session       The media session.
 * @param index         The stream index.
 * @param ascii_digits  String of ASCII digits (i.e. 0-9*##A-B).
 *
 * @return              PJ_SUCCESS on success.
 */
PJ_DECL(pj_status_t) pjmedia_session_dial_dtmf( pjmedia_session *session,
                                                unsigned index,
                                                const pj_str_t *ascii_digits );


/**
 * Check if the specified stream has received DTMF digits.
 *
 * @param session       The media session.
 * @param index         The stream index.
 *
 * @return              Non-zero (PJ_TRUE) if the stream has DTMF digits.
 */
PJ_DECL(pj_status_t) pjmedia_session_check_dtmf( pjmedia_session *session,
                                                 unsigned index);


/**
 * Retrieve DTMF digits from the specified stream.
 *
 * @param session       The media session.
 * @param index         The stream index.
 * @param ascii_digits  Buffer to receive the digits. The length of this
 *                      buffer is indicated in the "size" argument.
 * @param size          On input, contains the maximum digits to be copied
 *                      to the buffer.
 *                      On output, it contains the actual digits that has
 *                      been copied to the buffer.
 *
 * @return              PJ_SUCCESS on success.
 */
PJ_DECL(pj_status_t) pjmedia_session_get_dtmf( pjmedia_session *session,
                                               unsigned index,
                                               char *ascii_digits,
                                               unsigned *size );

/**
 * Set callback to be called upon receiving DTMF digits. If callback is
 * registered, the stream will not buffer incoming DTMF but rather call
 * the callback as soon as DTMF digit is received completely.
 *
 * @param session       The media session.
 * @param index         The stream index.
 * @param cb            Callback to be called upon receiving DTMF digits.
 *                      The DTMF digits will be given to the callback as
 *                      ASCII digits.
 * @param user_data     User data to be returned back when the callback
 *                      is called.
 *
 * @return              PJ_SUCCESS on success.
 */
PJ_DECL(pj_status_t)
pjmedia_session_set_dtmf_callback(pjmedia_session *session,
                                  unsigned index,
                                  void (*cb)(pjmedia_stream*, 
                                             void *user_data, 
                                             int digit), 
                                  void *user_data);

/**
 * Destroy media session.
 *
 * @param session       The media session.
 *
 * @return              PJ_SUCCESS if success.
 */
PJ_DECL(pj_status_t) pjmedia_session_destroy(pjmedia_session *session);



/**
 * @}
 */

PJ_END_DECL

#endif  /* __PJMEDIA_SESSION_H__ */
