Initial conference implementation

git-svn-id: https://svn.pjsip.org/repos/pjproject/trunk@205 74dad513-b988-da41-8d7b-12977e46ad98
diff --git a/pjmedia/include/pjmedia.h b/pjmedia/include/pjmedia.h
index 31f06be..66ba4e0 100644
--- a/pjmedia/include/pjmedia.h
+++ b/pjmedia/include/pjmedia.h
@@ -25,16 +25,18 @@
  */
 
 #include <pjmedia/types.h>
-#include <pjmedia/errno.h>
 #include <pjmedia/codec.h>
-#include <pjmedia/jbuf.h>
+#include <pjmedia/conference.h>
 #include <pjmedia/endpoint.h>
+#include <pjmedia/errno.h>
+#include <pjmedia/jbuf.h>
+#include <pjmedia/port.h>
 #include <pjmedia/rtcp.h>
 #include <pjmedia/rtp.h>
-#include <pjmedia/session.h>
-#include <pjmedia/sound.h>
 #include <pjmedia/sdp.h>
 #include <pjmedia/sdp_neg.h>
+#include <pjmedia/session.h>
+#include <pjmedia/sound.h>
 
 #endif	/* __PJMEDIA_H__ */
 
diff --git a/pjmedia/include/pjmedia/audio_conf.h b/pjmedia/include/pjmedia/audio_conf.h
deleted file mode 100644
index 0131ac4..0000000
--- a/pjmedia/include/pjmedia/audio_conf.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/* $Id$ */
-/* 
- * Copyright (C) 2003-2006 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_CONF_H__
-#define __PJMEDIA_CONF_H__
-
-
-/**
- * @file conf.h
- * @brief Conference bridge.
- */
-#include <pjmedia/types.h>
-
-/**
- * Opaque type for conference bridge.
- */
-typedef struct pjmedia_conf pjmedia_conf;
-
-
-/**
- * Create conference bridge.
- */
-PJ_DECL(pj_status_t) pjmedia_conf_create( pj_pool_t *pool,
-					  unsigned max_ports,
-					  pjmedia_conf **p_conf );
-
-
-/**
- * Add stream port to the conference bridge.
- */
-PJ_DECL(pj_status_t) pjmedia_conf_add_port( pjmedia_conf *conf,
-					    pj_pool_t *pool,
-					    pjmedia_stream_port *strm_port,
-					    const pj_str_t *port_name,
-					    unsigned *p_port );
-
-
-/**
- * Mute or unmute port.
- */
-PJ_DECL(pj_status_t) pjmedia_conf_set_mute( pjmedia_conf *conf,
-					    unsigned port,
-					    pj_bool_t mute );
-
-
-/**
- * Set the specified port to be member of conference bridge.
- */
-PJ_DECL(pj_status_t) pjmedia_conf_set_membership( pjmedia_conf *conf,
-						  unsigned port,
-						  pj_bool_t enabled );
-
-
-/**
- * Remove the specified port.
- */
-PJ_DECL(pj_status_t) pjmedia_conf_remove_port( pjmedia_conf *conf,
-					       unsigned port );
-
-
-
-#endif	/* __PJMEDIA_CONF_H__ */
-
diff --git a/pjmedia/include/pjmedia/codec.h b/pjmedia/include/pjmedia/codec.h
index 1da3273..c308c57 100644
--- a/pjmedia/include/pjmedia/codec.h
+++ b/pjmedia/include/pjmedia/codec.h
@@ -119,26 +119,6 @@
 };
 
 
-/** 
- * Types of media frame. 
- */
-enum pjmedia_frame_type
-{
-    PJMEDIA_FRAME_TYPE_SILENCE_AUDIO,	/**< Silence audio frame.	*/
-    PJMEDIA_FRAME_TYPE_AUDIO,		/**< Normal audio frame.	*/
-
-};
-
-/** 
- * This structure describes a media frame. 
- */
-struct pjmedia_frame
-{
-    pjmedia_frame_type	 type;	/**< Frame type.		    */
-    void		*buf;	/**< Pointer to buffer.		    */
-    pj_size_t		 size;	/**< Frame size in bytes.	    */
-};
-
 /**
  * This structure describes codec operations. Each codec MUST implement
  * all of these functions.
diff --git a/pjmedia/include/pjmedia/conference.h b/pjmedia/include/pjmedia/conference.h
new file mode 100644
index 0000000..ffa4437
--- /dev/null
+++ b/pjmedia/include/pjmedia/conference.h
@@ -0,0 +1,163 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2003-2006 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_CONF_H__
+#define __PJMEDIA_CONF_H__
+
+
+/**
+ * @file conference.h
+ * @brief Conference bridge.
+ */
+#include <pjmedia/port.h>
+
+
+PJ_BEGIN_DECL
+
+
+/**
+ * Opaque type for conference bridge.
+ */
+typedef struct pjmedia_conf pjmedia_conf;
+
+/**
+ * Conference port info.
+ */
+typedef struct pjmedia_conf_port_info
+{
+    pj_str_t		name;
+    pjmedia_port_op	tx_setting;
+    pjmedia_port_op	rx_setting;
+    pj_bool_t	       *listener;
+} pjmedia_conf_port_info;
+
+
+/**
+ * Create conference bridge.
+ */
+PJ_DECL(pj_status_t) pjmedia_conf_create( pj_pool_t *pool,
+					  unsigned max_slots,
+					  unsigned sampling_rate,
+					  unsigned samples_per_frame,
+					  unsigned bits_per_sample,
+					  pjmedia_conf **p_conf );
+
+
+/**
+ * Destroy conference bridge.
+ */
+PJ_DECL(pj_status_t) pjmedia_conf_destroy( pjmedia_conf *conf );
+
+
+/**
+ * Add stream port to the conference bridge. By default, the new conference
+ * port will have both TX and RX enabled, but it is not connected to any
+ * other ports.
+ *
+ * Application SHOULD call #pjmedia_conf_connect_port() to enable audio
+ * transmission and receipt to/from this port.
+ *
+ * @param conf		The conference bridge.
+ * @param pool		Pool to allocate buffers for this port.
+ * @param strm_port	Stream port interface.
+ * @param name		Port name.
+ * @param p_slot	Pointer to receive the slot index of the port in
+ *			the conference bridge.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_conf_add_port( pjmedia_conf *conf,
+					    pj_pool_t *pool,
+					    pjmedia_port *strm_port,
+					    const pj_str_t *name,
+					    unsigned *p_slot );
+
+
+
+/**
+ * Change TX and RX settings for the port.
+ *
+ * @param conf		The conference bridge.
+ * @param slot		Port number/slot in the conference bridge.
+ * @param tx		Settings for the transmission TO this port.
+ * @param rx		Settings for the receipt FROM this port.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_conf_configure_port( pjmedia_conf *conf,
+						  unsigned slot,
+						  pjmedia_port_op tx,
+						  pjmedia_port_op rx);
+
+
+/**
+ * Enable unidirectional audio from the specified source slot to the
+ * specified sink slot.
+ *
+ * @param conf		The conference bridge.
+ * @param src_slot	Source slot.
+ * @param sink_slot	Sink slot.
+ *
+ * @return		PJ_SUCCES on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_conf_connect_port( pjmedia_conf *conf,
+						unsigned src_slot,
+						unsigned sink_slot );
+
+
+/**
+ * Disconnect unidirectional audio from the specified source to the specified
+ * sink slot.
+ *
+ * @param conf		The conference bridge.
+ * @param src_slot	Source slot.
+ * @param sink_slot	Sink slot.
+ *
+ * @reutrn		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_conf_disconnect_port( pjmedia_conf *conf,
+						   unsigned src_slot,
+						   unsigned sink_slot );
+
+
+/**
+ * Remove the specified port from the conference bridge.
+ *
+ * @param conf		The conference bridge.
+ * @param slot		The port index to be removed.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_conf_remove_port( pjmedia_conf *conf,
+					       unsigned slot );
+
+
+
+/**
+ * Get port info.
+ */
+PJ_DECL(pj_status_t) pjmedia_conf_get_port_info( pjmedia_conf *conf,
+						 unsigned slot,
+						 pjmedia_conf_port_info *info);
+
+
+PJ_END_DECL
+
+
+#endif	/* __PJMEDIA_CONF_H__ */
+
diff --git a/pjmedia/include/pjmedia/errno.h b/pjmedia/include/pjmedia/errno.h
index 5a90537..708f5e0 100644
--- a/pjmedia/include/pjmedia/errno.h
+++ b/pjmedia/include/pjmedia/errno.h
@@ -344,6 +344,16 @@
  * Bad RTP sequence number
  */
 #define PJMEDIA_RTP_EBADSEQ	    (PJMEDIA_ERRNO_START+132)    /* 220132 */
+/**
+ * @hideinitializer
+ * RTP media port destination is not configured
+ */
+#define PJMEDIA_RTP_EBADDEST	    (PJMEDIA_ERRNO_START+133)    /* 220133 */
+/**
+ * @hideinitializer
+ * RTP is not configured.
+ */
+#define PJMEDIA_RTP_ENOCONFIG	    (PJMEDIA_ERRNO_START+134)    /* 220134 */
 
 
 /************************************************************
@@ -351,6 +361,42 @@
  ***********************************************************/
 
 
+/************************************************************
+ * PORT ERRORS
+ ***********************************************************/
+/**
+ * @hideinitializer
+ * Generic incompatible port error.
+ */
+#define PJMEDIA_ENOTCOMPATIBLE	    (PJMEDIA_ERRNO_START+160)    /* 220160 */
+/**
+ * @hideinitializer
+ * Incompatible clock rate
+ */
+#define PJMEDIA_ENCCLOCKRATE	    (PJMEDIA_ERRNO_START+161)    /* 220161 */
+/**
+ * @hideinitializer
+ * Incompatible samples per frame
+ */
+#define PJMEDIA_ENCSAMPLESPFRAME    (PJMEDIA_ERRNO_START+162)    /* 220162 */
+/**
+ * @hideinitializer
+ * Incompatible media type
+ */
+#define PJMEDIA_ENCTYPE		    (PJMEDIA_ERRNO_START+163)    /* 220163 */
+/**
+ * @hideinitializer
+ * Incompatible bits per sample
+ */
+#define PJMEDIA_ENCBITS		    (PJMEDIA_ERRNO_START+164)    /* 220164 */
+/**
+ * @hideinitializer
+ * Incompatible bytes per frame
+ */
+#define PJMEDIA_ENCBYTES	    (PJMEDIA_ERRNO_START+165)    /* 220165 */
+
+
+
 PJ_END_DECL
 
 #endif	/* __PJMEDIA_ERRNO_H__ */
diff --git a/pjmedia/include/pjmedia/port.h b/pjmedia/include/pjmedia/port.h
new file mode 100644
index 0000000..5437061
--- /dev/null
+++ b/pjmedia/include/pjmedia/port.h
@@ -0,0 +1,210 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2003-2006 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_PORT_H__
+#define __PJMEDIA_PORT_H__
+
+/**
+ * @file port.h
+ * @brief Port interface declaration
+ */
+#include <pjmedia/types.h>
+#include <pj/os.h>
+
+
+PJ_BEGIN_DECL
+
+
+/**
+ * Port operation setting.
+ */
+enum pjmedia_port_op
+{
+    /** 
+     * No change to the port TX or RX settings.
+     */
+    PJMEDIA_PORT_NO_CHANGE,
+
+    /**
+     * TX or RX is disabled from the port. It means get_frame() or
+     * put_frame() WILL NOT be called for this port.
+     */
+    PJMEDIA_PORT_DISABLE,
+
+    /**
+     * TX or RX is muted, which means that get_frame() or put_frame()
+     * will still be called, but the audio frame is discarded.
+     */
+    PJMEDIA_PORT_MUTE,
+
+    /**
+     * Enable TX and RX to/from this port.
+     */
+    PJMEDIA_PORT_ENABLE,
+};
+
+
+/**
+ * @see pjmedia_port_op
+ */
+typedef enum pjmedia_port_op pjmedia_port_op;
+
+
+/**
+ * Port info.
+ */
+struct pjmedia_port_info
+{
+    pj_str_t	    name;		/**< Port name.			    */
+    pj_uint32_t	    signature;		/**< Port signature.		    */
+    pjmedia_type    type;		/**< Media type.		    */
+    pj_bool_t	    has_info;		/**< Has info?			    */
+    pj_bool_t	    need_info;		/**< Need info on connect?	    */
+    unsigned	    pt;			/**< Payload type (can be dynamic). */
+    pj_str_t	    encoding_name;	/**< Encoding name.		    */
+    unsigned	    sample_rate;	/**< Sampling rate.		    */
+    unsigned	    bits_per_sample;	/**< Bits/sample		    */
+    unsigned	    samples_per_frame;	/**< No of samples per frame.	    */
+    unsigned	    bytes_per_frame;	/**< No of samples per frame.	    */
+};
+
+/**
+ * @see pjmedia_port_info
+ */
+typedef struct pjmedia_port_info pjmedia_port_info;
+
+
+/** 
+ * Types of media frame. 
+ */
+enum pjmedia_frame_type
+{
+    PJMEDIA_FRAME_TYPE_NONE,	    /**< No frame.		*/
+    PJMEDIA_FRAME_TYPE_CNG,	    /**< Silence audio frame.	*/
+    PJMEDIA_FRAME_TYPE_AUDIO,	    /**< Normal audio frame.	*/
+
+};
+
+/** 
+ * This structure describes a media frame. 
+ */
+struct pjmedia_frame
+{
+    pjmedia_frame_type	 type;	    /**< Frame type.		    */
+    void		*buf;	    /**< Pointer to buffer.	    */
+    pj_size_t		 size;	    /**< Frame size in bytes.	    */
+    pj_timestamp	 timestamp; /**< Frame timestamp.	    */
+};
+
+/**
+ * For future graph.
+ */
+typedef struct pjmedia_graph pjmedia_graph;
+
+
+/**
+ * @see pjmedia_port
+ */
+typedef struct pjmedia_port pjmedia_port;
+
+/**
+ * Port interface.
+ */
+struct pjmedia_port
+{
+    pjmedia_port_info	 info;
+    pjmedia_graph	*graph;
+    pjmedia_port	*upstream_port;
+    pjmedia_port	*downstream_port;
+    void		*user_data;
+
+    /**
+     * Called when this port is connected to an upstream port.
+     */
+    pj_status_t (*on_upstream_connect)(pj_pool_t *pool,
+				       pjmedia_port *this_port,
+				       pjmedia_port *upstream);
+
+    /**
+     * Called when this port is connected to a downstream port.
+     */
+    pj_status_t (*on_downstream_connect)(pj_pool_t *pool,
+					 pjmedia_port *this_port,
+				         pjmedia_port *upstream);
+
+    /**
+     * Sink interface. 
+     * This should only be called by #pjmedia_port_put_frame().
+     */
+    pj_status_t (*put_frame)(pjmedia_port *this_port, 
+			     const pjmedia_frame *frame);
+
+    /**
+     * Source interface. 
+     * This should only be called by #pjmedia_port_get_frame().
+     */
+    pj_status_t (*get_frame)(pjmedia_port *this_port, 
+			     pjmedia_frame *frame);
+
+    /**
+     * Called to destroy this port.
+     */
+    pj_status_t (*on_destroy)(pjmedia_port *this_port);
+};
+
+
+
+/**
+ * Connect two ports.
+ */
+PJ_DECL(pj_status_t) pjmedia_port_connect( pj_pool_t *pool,
+					   pjmedia_port *upstream_port,
+					   pjmedia_port *downstream_port);
+
+/**
+ * Disconnect ports.
+ */
+PJ_DECL(pj_status_t) pjmedia_port_disconnect( pjmedia_port *upstream_port,
+					      pjmedia_port *downstream_port);
+
+
+/**
+ * Get a frame from the port (and subsequent downstream ports).
+ */
+PJ_DECL(pj_status_t) pjmedia_port_get_frame( pjmedia_port *port,
+					     pjmedia_frame *frame );
+
+/**
+ * Put a frame to the port (and subsequent downstream ports).
+ */
+PJ_DECL(pj_status_t) pjmedia_port_put_frame( pjmedia_port *port,
+					     const pjmedia_frame *frame );
+
+
+/**
+ * Destroy port (and subsequent downstream ports)
+ */
+PJ_DECL(pj_status_t) pjmedia_port_destroy( pjmedia_port *port );
+
+
+
+PJ_END_DECL
+
+
+#endif	/* __PJMEDIA_PORT_H__ */
+
diff --git a/pjmedia/include/pjmedia/rtp.h b/pjmedia/include/pjmedia/rtp.h
index 409ad0a..3afc130 100644
--- a/pjmedia/include/pjmedia/rtp.h
+++ b/pjmedia/include/pjmedia/rtp.h
@@ -69,6 +69,9 @@
  *
  */
 
+#ifdef _MSC_VER
+#   pragma warning(disable:4214)    // bit field types other than int
+#endif
 
 
 /**
diff --git a/pjmedia/include/pjmedia/rtp_port.h b/pjmedia/include/pjmedia/rtp_port.h
new file mode 100644
index 0000000..7bb93cb
--- /dev/null
+++ b/pjmedia/include/pjmedia/rtp_port.h
@@ -0,0 +1,53 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2003-2006 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_RTP_PORT_H__
+#define __PJMEDIA_RTP_PORT_H__
+
+
+/**
+ * @file rtp_port.h
+ * @brief RTP media port.
+ */
+#include <pjmedia/port.h>
+
+
+PJ_BEGIN_DECL
+
+
+/**
+ * Create RTP port.
+ */
+PJ_DECL(pj_status_t) pjmedia_rtp_port_create(pj_pool_t *pool,
+					     pjmedia_sock_info *sock_info,
+					     pjmedia_port **p_port);
+
+
+/**
+ * Set RTP destination info.
+ */
+PJ_DECL(pj_status_t) pjmedia_rtp_port_configure(pjmedia_port *rtp,
+						const pj_sockaddr_in *rem_rtp,
+						const pj_sockaddr_in *rem_rtcp);
+
+
+
+PJ_END_DECL
+
+
+#endif	/* __PJMEDIA_RTP_PORT_H__ */
diff --git a/pjmedia/include/pjmedia/session.h b/pjmedia/include/pjmedia/session.h
index 4d36762..78d699f 100644
--- a/pjmedia/include/pjmedia/session.h
+++ b/pjmedia/include/pjmedia/session.h
@@ -175,6 +175,14 @@
 
 
 /**
+ * Get the port interface for the specified stream.
+ */
+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.
  *
diff --git a/pjmedia/include/pjmedia/stream.h b/pjmedia/include/pjmedia/stream.h
index 57bbe63..52b8008 100644
--- a/pjmedia/include/pjmedia/stream.h
+++ b/pjmedia/include/pjmedia/stream.h
@@ -28,6 +28,7 @@
 #include <pjmedia/sound.h>
 #include <pjmedia/codec.h>
 #include <pjmedia/endpoint.h>
+#include <pjmedia/port.h>
 #include <pj/sock.h>
 
 PJ_BEGIN_DECL
@@ -97,22 +98,6 @@
 };
 
 
-/**
- * Stream ports.
- */
-struct pjmedia_stream_port
-{
-    /**
-     * Sink port.
-     */
-    pj_status_t (*put_frame)(const pj_int16_t *frame, pj_size_t frame_cnt);
-
-    /**
-     * Source port.
-     */
-    pj_status_t (*get_frame)(pj_int16_t *frame, pj_size_t frame_cnt);
-};
-
 
 /**
  * Create a media stream based on the specified stream parameter.
@@ -142,6 +127,18 @@
 PJ_DECL(pj_status_t) pjmedia_stream_destroy(pjmedia_stream *stream);
 
 /**
+ * Get the port interface of the stream.
+ *
+ * @param stream	The media stream.
+ * @param p_port	Pointer to receive the port interface.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_stream_get_port(pjmedia_stream *stream,
+					     pjmedia_port **p_port );
+
+
+/**
  * Start the media stream. This will start the appropriate channels
  * in the media stream, depending on the media direction that was set
  * when the stream was created.
diff --git a/pjmedia/include/pjmedia/types.h b/pjmedia/include/pjmedia/types.h
index 7f1a106..b0bda7e 100644
--- a/pjmedia/include/pjmedia/types.h
+++ b/pjmedia/include/pjmedia/types.h
@@ -151,11 +151,6 @@
 typedef struct pjmedia_stream_stat pjmedia_stream_stat;
 
 /**
- * @see pjmedia_stream_port
- */
-typedef struct pjmedia_stream_port pjmedia_stream_port;
-
-/**
  * Typedef for media stream.
  */
 typedef struct pjmedia_stream pjmedia_stream;