Index: /pjproject/trunk/pjmedia/build/pjmedia.dsp
===================================================================
--- /pjproject/trunk/pjmedia/build/pjmedia.dsp	(revision 320)
+++ /pjproject/trunk/pjmedia/build/pjmedia.dsp	(revision 321)
@@ -169,4 +169,8 @@
 # Begin Source File
 
+SOURCE=..\src\pjmedia\sound_port.c
+# End Source File
+# Begin Source File
+
 SOURCE=..\src\pjmedia\stream.c
 # End Source File
@@ -254,4 +258,8 @@
 
 SOURCE=..\include\pjmedia\sound.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\pjmedia\sound_port.h
 # End Source File
 # Begin Source File
Index: /pjproject/trunk/pjmedia/include/pjmedia/errno.h
===================================================================
--- /pjproject/trunk/pjmedia/include/pjmedia/errno.h	(revision 320)
+++ /pjproject/trunk/pjmedia/include/pjmedia/errno.h	(revision 321)
@@ -416,4 +416,9 @@
  */
 #define PJMEDIA_ENCBYTES	    (PJMEDIA_ERRNO_START+165)    /* 220165 */
+/**
+ * @hideinitializer
+ * Incompatible number of channels
+ */
+#define PJMEDIA_ENCCHANNEL	    (PJMEDIA_ERRNO_START+166)    /* 220166 */
 
 
Index: /pjproject/trunk/pjmedia/include/pjmedia/port.h
===================================================================
--- /pjproject/trunk/pjmedia/include/pjmedia/port.h	(revision 320)
+++ /pjproject/trunk/pjmedia/include/pjmedia/port.h	(revision 321)
@@ -79,4 +79,5 @@
     pj_str_t	    encoding_name;	/**< Encoding name.		    */
     unsigned	    sample_rate;	/**< Sampling rate.		    */
+    unsigned	    channel_count;	/**< Number of channels.	    */
     unsigned	    bits_per_sample;	/**< Bits/sample		    */
     unsigned	    samples_per_frame;	/**< No of samples per frame.	    */
Index: /pjproject/trunk/pjmedia/include/pjmedia/rtcp.h
===================================================================
--- /pjproject/trunk/pjmedia/include/pjmedia/rtcp.h	(revision 320)
+++ /pjproject/trunk/pjmedia/include/pjmedia/rtcp.h	(revision 321)
@@ -40,5 +40,5 @@
  * RTCP sender report.
  */
-struct pj_rtcp_sr
+struct pjmedia_rtcp_sr
 {
     pj_uint32_t	    ssrc;	    /**< SSRC identification.		*/
@@ -51,12 +51,12 @@
 
 /**
- * @see pj_rtcp_sr
- */
-typedef struct pj_rtcp_sr pj_rtcp_sr;
+ * @see pjmedia_rtcp_sr
+ */
+typedef struct pjmedia_rtcp_sr pjmedia_rtcp_sr;
 
 /**
  * RTCP receiver report.
  */
-struct pj_rtcp_rr
+struct pjmedia_rtcp_rr
 {
     pj_uint32_t	    ssrc;	    /**< SSRC identification.		*/
@@ -79,7 +79,7 @@
 
 /**
- * @see pj_rtcp_rr
- */
-typedef struct pj_rtcp_rr pj_rtcp_rr;
+ * @see pjmedia_rtcp_rr
+ */
+typedef struct pjmedia_rtcp_rr pjmedia_rtcp_rr;
 
 
@@ -87,5 +87,5 @@
  * RTCP common header.
  */
-struct pj_rtcp_common
+struct pjmedia_rtcp_common
 {
 #if defined(PJ_IS_BIG_ENDIAN) && PJ_IS_BIG_ENDIAN!=0
@@ -104,22 +104,22 @@
 
 /**
- * @see pj_rtcp_common
- */
-typedef struct pj_rtcp_common pj_rtcp_common;
+ * @see pjmedia_rtcp_common
+ */
+typedef struct pjmedia_rtcp_common pjmedia_rtcp_common;
 
 /**
  * RTCP packet.
  */
-struct pj_rtcp_pkt
-{
-    pj_rtcp_common  common;	/**< Common header.	    */
-    pj_rtcp_sr	    sr;		/**< Sender report.	    */
-    pj_rtcp_rr	    rr;		/**< variable-length list   */
-};
-
-/**
- * @see pj_rtcp_pkt
- */
-typedef struct pj_rtcp_pkt pj_rtcp_pkt;
+struct pjmedia_rtcp_pkt
+{
+    pjmedia_rtcp_common  common;	/**< Common header.	    */
+    pjmedia_rtcp_sr sr;		/**< Sender report.	    */
+    pjmedia_rtcp_rr rr;		/**< variable-length list   */
+};
+
+/**
+ * @see pjmedia_rtcp_pkt
+ */
+typedef struct pjmedia_rtcp_pkt pjmedia_rtcp_pkt;
 
 
@@ -127,5 +127,5 @@
  * NTP time representation.
  */
-struct pj_rtcp_ntp_rec
+struct pjmedia_rtcp_ntp_rec
 {
     pj_uint32_t	    hi;		/**< High order 32-bit part.	*/
@@ -134,7 +134,7 @@
 
 /**
- * @see pj_rtcp_ntp_rec
- */
-typedef struct pj_rtcp_ntp_rec pj_rtcp_ntp_rec;
+ * @see pjmedia_rtcp_ntp_rec
+ */
+typedef struct pjmedia_rtcp_ntp_rec pjmedia_rtcp_ntp_rec;
 
 
@@ -143,7 +143,7 @@
  * RTCP session.
  */
-struct pj_rtcp_session
-{
-    pj_rtcp_pkt	    rtcp_pkt;	    /**< Cached RTCP packet.		    */
+struct pjmedia_rtcp_session
+{
+    pjmedia_rtcp_pkt	    rtcp_pkt;	/**< Cached RTCP packet.	    */
     
     pjmedia_rtp_seq_session seq_ctrl;	/**< RTCP sequence number control.  */
@@ -155,14 +155,14 @@
     pj_uint32_t	    jitter;	    /**< Estimated jitter		    */
     
-    pj_rtcp_ntp_rec rtcp_lsr;	    /**< NTP ts in last SR received	    */
-    unsigned 	    rtcp_lsr_time;  /**< Time when last SR is received.	    */
-    pj_uint32_t	    peer_ssrc;	    /**< Peer SSRC			    */
+    pjmedia_rtcp_ntp_rec rtcp_lsr;	 /**< NTP ts in last SR received    */
+    unsigned 		 rtcp_lsr_time;  /**< Time when last SR is received.*/
+    pj_uint32_t		 peer_ssrc;	 /**< Peer SSRC			    */
     
 };
 
 /**
- * @see pj_rtcp_session
- */
-typedef struct pj_rtcp_session pj_rtcp_session;
+ * @see pjmedia_rtcp_session
+ */
+typedef struct pjmedia_rtcp_session pjmedia_rtcp_session;
 
 
@@ -173,5 +173,6 @@
  * @param ssrc	    The SSRC used in to identify the session.
  */
-PJ_DECL(void) pj_rtcp_init( pj_rtcp_session *session, pj_uint32_t ssrc );
+PJ_DECL(void) pjmedia_rtcp_init( pjmedia_rtcp_session *session, 
+				 pj_uint32_t ssrc );
 
 
@@ -181,5 +182,5 @@
  * @param session   The session.
  */
-PJ_DECL(void) pj_rtcp_fini( pj_rtcp_session *session);
+PJ_DECL(void) pjmedia_rtcp_fini( pjmedia_rtcp_session *session);
 
 
@@ -192,6 +193,7 @@
  * @param ts	    The RTP packet timestamp, in host byte order.
  */
-PJ_DECL(void) pj_rtcp_rx_rtp( pj_rtcp_session *session, pj_uint16_t seq, 
-			      pj_uint32_t ts );
+PJ_DECL(void) pjmedia_rtcp_rx_rtp( pjmedia_rtcp_session *session, 
+				   pj_uint16_t seq, 
+				   pj_uint32_t ts );
 
 
@@ -204,5 +206,6 @@
  *		    RTP header) in bytes.
  */
-PJ_DECL(void) pj_rtcp_tx_rtp( pj_rtcp_session *session, pj_uint16_t ptsize );
+PJ_DECL(void) pjmedia_rtcp_tx_rtp( pjmedia_rtcp_session *session, 
+				   pj_uint16_t ptsize );
 
 
@@ -216,7 +219,7 @@
  *		    the RTCP packet.
  */
-PJ_DECL(void) pj_rtcp_build_rtcp( pj_rtcp_session *session, 
-				  pj_rtcp_pkt **rtcp_pkt, 
-				  int *len );
+PJ_DECL(void) pjmedia_rtcp_build_rtcp( pjmedia_rtcp_session *session, 
+				       pjmedia_rtcp_pkt **rtcp_pkt, 
+				       int *len );
 
 
Index: /pjproject/trunk/pjmedia/include/pjmedia/sound.h
===================================================================
--- /pjproject/trunk/pjmedia/include/pjmedia/sound.h	(revision 320)
+++ /pjproject/trunk/pjmedia/include/pjmedia/sound.h	(revision 321)
@@ -37,10 +37,10 @@
 
 /** Opaque data type for audio stream. */
-typedef struct pj_snd_stream pj_snd_stream;
-
-/**
- * Device information structure returned by #pj_snd_get_dev_info.
- */
-typedef struct pj_snd_dev_info
+typedef struct pjmedia_snd_stream pjmedia_snd_stream;
+
+/**
+ * Device information structure returned by #pjmedia_snd_get_dev_info.
+ */
+typedef struct pjmedia_snd_dev_info
 {
     char	name[64];	        /**< Device name.		    */
@@ -48,5 +48,5 @@
     unsigned	output_count;	        /**< Max number of output channels. */
     unsigned	default_samples_per_sec;/**< Default sampling rate.	    */
-} pj_snd_dev_info;
+} pjmedia_snd_dev_info;
 
 /** 
@@ -63,5 +63,5 @@
  * @return		Non-zero to stop the stream.
  */
-typedef pj_status_t (*pj_snd_play_cb)(/* in */   void *user_data,
+typedef pj_status_t (*pjmedia_snd_play_cb)(/* in */   void *user_data,
 				      /* in */   pj_uint32_t timestamp,
 				      /* out */  void *output,
@@ -79,5 +79,5 @@
  * @return		Non-zero to stop the stream.
  */
-typedef pj_status_t (*pj_snd_rec_cb)(/* in */   void *user_data,
+typedef pj_status_t (*pjmedia_snd_rec_cb)(/* in */   void *user_data,
 				     /* in */   pj_uint32_t timestamp,
 				     /* in */   const void *input,
@@ -91,5 +91,5 @@
  * @return		Zero on success.
  */
-PJ_DECL(pj_status_t) pj_snd_init(pj_pool_factory *factory);
+PJ_DECL(pj_status_t) pjmedia_snd_init(pj_pool_factory *factory);
 
 
@@ -99,5 +99,5 @@
  * @return		Number of devices.
  */
-PJ_DECL(int) pj_snd_get_dev_count(void);
+PJ_DECL(int) pjmedia_snd_get_dev_count(void);
 
 
@@ -106,7 +106,7 @@
  *
  * @param index		The index of the device, which should be in the range
- *			from zero to #pj_snd_get_dev_count - 1.
- */
-PJ_DECL(const pj_snd_dev_info*) pj_snd_get_dev_info(unsigned index);
+ *			from zero to #pjmedia_snd_get_dev_count - 1.
+ */
+PJ_DECL(const pjmedia_snd_dev_info*) pjmedia_snd_get_dev_info(unsigned index);
 
 
@@ -114,40 +114,55 @@
  * Create a new audio stream for audio capture purpose.
  *
- * @param index		Device index, or -1 to let the library choose the first
- *			available device, or -2 to use NULL device.
- * @param param		Stream parameters.
- * @param rec_cb	Callback to handle captured audio samples.
- * @param user_data	User data to be associated with the stream.
- *
- * @return		Audio stream, or NULL if failed.
- */
-PJ_DECL(pj_status_t) pj_snd_open_recorder( int index,
+ * @param index		    Device index, or -1 to let the library choose the 
+ *			    first available device.
+ * @param clock_rate	    Sound device's clock rate to set.
+ * @param channel_count	    Set number of channels, 1 for mono, or 2 for
+ *			    stereo. The channel count determines the format
+ *			    of the frame.
+ * @param samples_per_frame Number of samples per frame.
+ * @param bits_per_sample   Set the number of bits per sample. The normal 
+ *			    value for this parameter is 16 bits per sample.
+ * @param rec_cb	    Callback to handle captured audio samples.
+ * @param user_data	    User data to be associated with the stream.
+ * @param p_snd_strm	    Pointer to receive the stream instance.
+ *
+ * @return		    PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_snd_open_recorder( int index,
 					   unsigned clock_rate,
 					   unsigned channel_count,
 					   unsigned samples_per_frame,
 					   unsigned bits_per_sample,
-					   pj_snd_rec_cb rec_cb,
+					   pjmedia_snd_rec_cb rec_cb,
 					   void *user_data,
-					   pj_snd_stream **p_snd_strm);
+					   pjmedia_snd_stream **p_snd_strm);
 
 /**
  * Create a new audio stream for playing audio samples.
  *
- * @param index		Device index, or -1 to let the library choose the first
- *			available device, or -2 to use NULL device.
- * @param param		Stream parameters.
- * @param play_cb	Callback to supply audio samples.
- * @param user_data	User data to be associated with the stream.
- *
- * @return		Audio stream, or NULL if failed.
- */
-PJ_DECL(pj_status_t) pj_snd_open_player( int index,
+ * @param index		    Device index, or -1 to let the library choose the 
+ *			    first available device.
+ * @param clock_rate	    Sound device's clock rate to set.
+ * @param channel_count	    Set number of channels, 1 for mono, or 2 for
+ *			    stereo. The channel count determines the format
+ *			    of the frame.
+ * @param samples_per_frame Number of samples per frame.
+ * @param bits_per_sample   Set the number of bits per sample. The normal 
+ *			    value for this parameter is 16 bits per sample.
+ * @param play_cb	    Callback to be called when the sound player needs
+ *			    more audio samples to play.
+ * @param user_data	    User data to be associated with the stream.
+ * @param p_snd_strm	    Pointer to receive the stream instance.
+ *
+ * @return		    PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_snd_open_player( int index,
 					 unsigned clock_rate,
 					 unsigned channel_count,
 					 unsigned samples_per_frame,
 					 unsigned bits_per_sample,
-					 pj_snd_play_cb play_cb,
+					 pjmedia_snd_play_cb play_cb,
 					 void *user_data,
-					 pj_snd_stream **p_snd_strm );
+					 pjmedia_snd_stream **p_snd_strm );
 
 /**
@@ -158,5 +173,5 @@
  * @return		Zero on success.
  */
-PJ_DECL(pj_status_t) pj_snd_stream_start(pj_snd_stream *stream);
+PJ_DECL(pj_status_t) pjmedia_snd_stream_start(pjmedia_snd_stream *stream);
 
 /**
@@ -167,5 +182,5 @@
  * @return		Zero on success.
  */
-PJ_DECL(pj_status_t) pj_snd_stream_stop(pj_snd_stream *stream);
+PJ_DECL(pj_status_t) pjmedia_snd_stream_stop(pjmedia_snd_stream *stream);
 
 /**
@@ -176,5 +191,5 @@
  * @return		Zero on success.
  */
-PJ_DECL(pj_status_t) pj_snd_stream_close(pj_snd_stream *stream);
+PJ_DECL(pj_status_t) pjmedia_snd_stream_close(pjmedia_snd_stream *stream);
 
 /**
@@ -183,5 +198,5 @@
  * @return		Zero on success.
  */
-PJ_DECL(pj_status_t) pj_snd_deinit(void);
+PJ_DECL(pj_status_t) pjmedia_snd_deinit(void);
 
 
Index: /pjproject/trunk/pjmedia/include/pjmedia/sound_port.h
===================================================================
--- /pjproject/trunk/pjmedia/include/pjmedia/sound_port.h	(revision 321)
+++ /pjproject/trunk/pjmedia/include/pjmedia/sound_port.h	(revision 321)
@@ -0,0 +1,165 @@
+/* $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_SOUND_PORT_H__
+#define __PJMEDIA_SOUND_PORT_H__
+
+/**
+ * @file sound_port.h
+ * @brief Media port connection abstraction to sound device.
+ */
+#include <pjmedia/sound.h>
+#include <pjmedia/port.h>
+
+PJ_BEGIN_DECL
+
+/**
+ * @defgroup PJMED_SND_PORT Media Port Connection Abstraction to Sound Device
+ * @ingroup PJMEDIA
+ * @{
+ */
+
+/**
+ * This opaque type describes sound device port connection.
+ * Sound device port is not a media port, but it is used to connect media
+ * port to the sound device.
+ */
+typedef struct pjmedia_snd_port pjmedia_snd_port;
+
+/**
+ * Create sound device port for capturing audio streams from the sound device
+ * with the specified parameters.
+ *
+ * @param pool		    Pool to allocate sound port structure.
+ * @param index		    Device index, or -1 to let the library choose the 
+ *			    first available device.
+ * @param clock_rate	    Sound device's clock rate to set.
+ * @param channel_count	    Set number of channels, 1 for mono, or 2 for
+ *			    stereo. The channel count determines the format
+ *			    of the frame.
+ * @param samples_per_frame Number of samples per frame.
+ * @param bits_per_sample   Set the number of bits per sample. The normal 
+ *			    value for this parameter is 16 bits per sample.
+ * @param options	    Options flag, currently must be zero.
+ * @param p_port	    Pointer to receive the sound device port instance.
+ *
+ * @return		    PJ_SUCCESS on success, or the appropriate error
+ *			    code.
+ */
+PJ_DECL(pj_status_t) pjmedia_snd_port_create_rec(pj_pool_t *pool,
+						 int index,
+						 unsigned clock_rate,
+						 unsigned channel_count,
+						 unsigned samples_per_frame,
+						 unsigned bits_per_sample,
+						 unsigned options,
+						 pjmedia_snd_port **p_port);
+					      
+/**
+ * Create sound device port for playing audio streams with the specified 
+ * parameters.
+ *
+ * @param pool		    Pool to allocate sound port structure.
+ * @param index		    Device index, or -1 to let the library choose the 
+ *			    first available device.
+ * @param clock_rate	    Sound device's clock rate to set.
+ * @param channel_count	    Set number of channels, 1 for mono, or 2 for
+ *			    stereo. The channel count determines the format
+ *			    of the frame.
+ * @param samples_per_frame Number of samples per frame.
+ * @param bits_per_sample   Set the number of bits per sample. The normal 
+ *			    value for this parameter is 16 bits per sample.
+ * @param options	    Options flag, currently must be zero.
+ * @param p_port	    Pointer to receive the sound device port instance.
+ *
+ * @return		    PJ_SUCCESS on success, or the appropriate error
+ *			    code.
+ */
+PJ_DECL(pj_status_t) pjmedia_snd_port_create_player(pj_pool_t *pool,
+						    int index,
+						    unsigned clock_rate,
+						    unsigned channel_count,
+						    unsigned samples_per_frame,
+						    unsigned bits_per_sample,
+						    unsigned options,
+						    pjmedia_snd_port **p_port);
+					      
+
+/**
+ * Destroy sound device port.
+ *
+ * @param snd_port	    The sound device port.
+ *
+ * @return		    PJ_SUCCESS on success, or the appropriate error
+ *			    code.
+ */
+PJ_DECL(pj_status_t) pjmedia_snd_port_destroy(pjmedia_snd_port *snd_port);
+
+
+/**
+ * Connect a port to the sound device port. If the sound device port is a
+ * sound recorder device, then this will start periodic function call to
+ * the port's put_frame() function. If the sound device is a sound player
+ * device, then this will start periodic function call to the port's
+ * get_frame() function.
+ *
+ * For this version of PJMEDIA, the media port MUST have the same audio
+ * settings as the sound device port, or otherwise the connection will
+ * fail. This means the port MUST have the same clock_rate, channel count,
+ * samples per frame, and bits per sample as the sound device port.
+ *
+ * @param snd_port	    The sound device port.
+ *
+ * @return		    PJ_SUCCESS on success, or the appropriate error
+ *			    code.
+ */
+PJ_DECL(pj_status_t) pjmedia_snd_port_connect(pjmedia_snd_port *snd_port,
+					      pjmedia_port *port);
+
+
+/**
+ * Retrieve the port instance currently attached to the sound port, if any.
+ *
+ * @param snd_port	    The sound device port.
+ *
+ * @return		    The port instance currently attached to the 
+ *			    sound device port, or NULL if there is no port
+ *			    currently attached to the sound device port.
+ */
+PJ_DECL(pjmedia_port*) pjmedia_snd_port_get_port(pjmedia_snd_port *snd_port);
+
+
+/**
+ * Disconnect currently attached port from the sound device port.
+ *
+ * @param snd_port	    The sound device port.
+ *
+ * @return		    PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_snd_port_disconnect(pjmedia_snd_port *snd_port);
+
+
+/**
+ * @}
+ */
+
+PJ_END_DECL
+
+
+#endif	/* __PJMEDIA_SOUND_PORT_H__ */
+
Index: /pjproject/trunk/pjmedia/src/pjmedia/conference.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia/conference.c	(revision 320)
+++ /pjproject/trunk/pjmedia/src/pjmedia/conference.c	(revision 321)
@@ -132,6 +132,6 @@
     unsigned		  port_cnt;	/**< Current number of ports.	    */
     unsigned		  connect_cnt;	/**< Total number of connections    */
-    pj_snd_stream	 *snd_rec;	/**< Sound recorder stream.	    */
-    pj_snd_stream	 *snd_player;	/**< Sound player stream.	    */
+    pjmedia_snd_stream	 *snd_rec;	/**< Sound recorder stream.	    */
+    pjmedia_snd_stream	 *snd_player;	/**< Sound player stream.	    */
     pj_mutex_t		 *mutex;	/**< Conference mutex.		    */
     struct conf_port	**ports;	/**< Array of ports.		    */
@@ -383,5 +383,5 @@
     /* Open recorder only if mic is not disabled. */
     if ((conf->options & PJMEDIA_CONF_NO_MIC) == 0) {
-	status = pj_snd_open_recorder(-1, conf->clock_rate, 1, 
+	status = pjmedia_snd_open_recorder(-1, conf->clock_rate, 1, 
 				      conf->samples_per_frame,
 				      conf->bits_per_sample,
@@ -394,5 +394,5 @@
 
     /* Open player */
-    status = pj_snd_open_player(-1, conf->clock_rate, 1,
+    status = pjmedia_snd_open_player(-1, conf->clock_rate, 1,
 			        conf->samples_per_frame,
 				conf->bits_per_sample, 
@@ -400,5 +400,5 @@
     if (status != PJ_SUCCESS) {
 	if (conf->snd_rec) {
-	    pj_snd_stream_close(conf->snd_rec);
+	    pjmedia_snd_stream_close(conf->snd_rec);
 	    conf->snd_rec = NULL;
 	}
@@ -416,9 +416,9 @@
 {
     if (conf->snd_rec) {
-	pj_snd_stream_close(conf->snd_rec);
+	pjmedia_snd_stream_close(conf->snd_rec);
 	conf->snd_rec = NULL;
     }
     if (conf->snd_player) {
-	pj_snd_stream_close(conf->snd_player);
+	pjmedia_snd_stream_close(conf->snd_player);
 	conf->snd_player = NULL;
     }
@@ -442,5 +442,5 @@
     /* Start recorder. */
     if (conf->snd_rec) {
-	status = pj_snd_stream_start(conf->snd_rec);
+	status = pjmedia_snd_stream_start(conf->snd_rec);
 	if (status != PJ_SUCCESS)
 	    goto on_error;
@@ -449,5 +449,5 @@
     /* Start player. */
     if (conf->snd_player) {
-	status = pj_snd_stream_start(conf->snd_player);
+	status = pjmedia_snd_stream_start(conf->snd_player);
 	if (status != PJ_SUCCESS)
 	    goto on_error;
Index: /pjproject/trunk/pjmedia/src/pjmedia/endpoint.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia/endpoint.c	(revision 320)
+++ /pjproject/trunk/pjmedia/src/pjmedia/endpoint.c	(revision 321)
@@ -107,10 +107,10 @@
 
     /* Sound */
-    pj_snd_init(pf);
+    pjmedia_snd_init(pf);
 
     /* Init codec manager. */
     status = pjmedia_codec_mgr_init(&endpt->codec_mgr);
     if (status != PJ_SUCCESS) {
-	pj_snd_deinit();
+	pjmedia_snd_deinit();
 	goto on_error;
     }
@@ -123,5 +123,5 @@
     status = g711_init_factory (factory, endpt->pool);
     if (status != PJ_SUCCESS) {
-	pj_snd_deinit();
+	pjmedia_snd_deinit();
 	goto on_error;
     }
@@ -129,5 +129,5 @@
     status = pjmedia_codec_mgr_register_factory (&endpt->codec_mgr, factory);
     if (status != PJ_SUCCESS)  {
-	pj_snd_deinit();
+	pjmedia_snd_deinit();
 	goto on_error;
     }
@@ -159,5 +159,5 @@
     endpt->pf = NULL;
 
-    pj_snd_deinit();
+    pjmedia_snd_deinit();
     pj_pool_release (endpt->pool);
 
Index: /pjproject/trunk/pjmedia/src/pjmedia/errno.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia/errno.c	(revision 320)
+++ /pjproject/trunk/pjmedia/src/pjmedia/errno.c	(revision 321)
@@ -114,4 +114,5 @@
     { PJMEDIA_ENCBITS,		    "Media ports have incompatible bits per sample" },
     { PJMEDIA_ENCBYTES,		    "Media ports have incompatible bytes per frame" },
+    { PJMEDIA_ENCCHANNEL,	    "Media ports have incompatible number of channels" },
 
     /* Media file errors: */
Index: /pjproject/trunk/pjmedia/src/pjmedia/nullsound.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia/nullsound.c	(revision 320)
+++ /pjproject/trunk/pjmedia/src/pjmedia/nullsound.c	(revision 321)
@@ -22,5 +22,5 @@
 #if defined(PJMEDIA_HAS_NULL_SOUND) && PJMEDIA_HAS_NULL_SOUND!=0
 
-static pj_snd_dev_info null_info = 
+static pjmedia_snd_dev_info null_info = 
 {
     "Null Device",
@@ -31,5 +31,5 @@
 
 
-PJ_DEF(pj_status_t) pj_snd_init(pj_pool_factory *factory)
+PJ_DEF(pj_status_t) pjmedia_snd_init(pj_pool_factory *factory)
 {
     PJ_UNUSED_ARG(factory);
@@ -37,10 +37,10 @@
 }
 
-PJ_DEF(int) pj_snd_get_dev_count(void)
+PJ_DEF(int) pjmedia_snd_get_dev_count(void)
 {
     return 1;
 }
 
-PJ_DEF(const pj_snd_dev_info*) pj_snd_get_dev_info(unsigned index)
+PJ_DEF(const pjmedia_snd_dev_info*) pjmedia_snd_get_dev_info(unsigned index)
 {
     PJ_ASSERT_RETURN(index==0, NULL);
@@ -48,12 +48,12 @@
 }
 
-PJ_DEF(pj_status_t) pj_snd_open_recorder( int index,
+PJ_DEF(pj_status_t) pjmedia_snd_open_recorder( int index,
 					  unsigned clock_rate,
 					  unsigned channel_count,
 					  unsigned samples_per_frame,
 					  unsigned bits_per_sample,
-					  pj_snd_rec_cb rec_cb,
+					  pjmedia_snd_rec_cb rec_cb,
 					  void *user_data,
-					  pj_snd_stream **p_snd_strm)
+					  pjmedia_snd_stream **p_snd_strm)
 {
     PJ_UNUSED_ARG(index);
@@ -70,12 +70,12 @@
 }
 
-PJ_DEF(pj_status_t) pj_snd_open_player( int index,
+PJ_DEF(pj_status_t) pjmedia_snd_open_player( int index,
 					unsigned clock_rate,
 					unsigned channel_count,
 					unsigned samples_per_frame,
 					unsigned bits_per_sample,
-					pj_snd_play_cb play_cb,
+					pjmedia_snd_play_cb play_cb,
 					void *user_data,
-					pj_snd_stream **p_snd_strm )
+					pjmedia_snd_stream **p_snd_strm )
 {
     PJ_UNUSED_ARG(index);
@@ -92,5 +92,5 @@
 }
 
-PJ_DEF(pj_status_t) pj_snd_stream_start(pj_snd_stream *stream)
+PJ_DEF(pj_status_t) pjmedia_snd_stream_start(pjmedia_snd_stream *stream)
 {
     PJ_UNUSED_ARG(stream);
@@ -98,5 +98,5 @@
 }
 
-PJ_DEF(pj_status_t) pj_snd_stream_stop(pj_snd_stream *stream)
+PJ_DEF(pj_status_t) pjmedia_snd_stream_stop(pjmedia_snd_stream *stream)
 {
     PJ_UNUSED_ARG(stream);
@@ -104,5 +104,5 @@
 }
 
-PJ_DEF(pj_status_t) pj_snd_stream_close(pj_snd_stream *stream)
+PJ_DEF(pj_status_t) pjmedia_snd_stream_close(pjmedia_snd_stream *stream)
 {
     PJ_UNUSED_ARG(stream);
@@ -110,5 +110,5 @@
 }
 
-PJ_DEF(pj_status_t) pj_snd_deinit(void)
+PJ_DEF(pj_status_t) pjmedia_snd_deinit(void)
 {
     return PJ_SUCCESS;
Index: /pjproject/trunk/pjmedia/src/pjmedia/pasound.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia/pasound.c	(revision 320)
+++ /pjproject/trunk/pjmedia/src/pjmedia/pasound.c	(revision 321)
@@ -33,5 +33,5 @@
 } snd_mgr;
 
-struct pj_snd_stream
+struct pjmedia_snd_stream
 {
     pj_pool_t	    *pool;
@@ -46,6 +46,6 @@
     pj_uint32_t	     overflow;
     void	    *user_data;
-    pj_snd_rec_cb    rec_cb;
-    pj_snd_play_cb   play_cb;
+    pjmedia_snd_rec_cb    rec_cb;
+    pjmedia_snd_play_cb   play_cb;
     pj_bool_t	     quit_flag;
     pj_bool_t	     thread_has_exited;
@@ -63,5 +63,5 @@
 			      void *userData )
 {
-    pj_snd_stream *stream = userData;
+    pjmedia_snd_stream *stream = userData;
     pj_status_t status;
 
@@ -103,5 +103,5 @@
 			     void *userData )
 {
-    pj_snd_stream *stream = userData;
+    pjmedia_snd_stream *stream = userData;
     pj_status_t status;
     unsigned size = frameCount * stream->bytes_per_sample;
@@ -141,5 +141,5 @@
  * Init sound library.
  */
-PJ_DEF(pj_status_t) pj_snd_init(pj_pool_factory *factory)
+PJ_DEF(pj_status_t) pjmedia_snd_init(pj_pool_factory *factory)
 {
     int err;
@@ -152,7 +152,7 @@
 			 Pa_GetHostApiCount()));
     PJ_LOG(4,(THIS_FILE, "Sound device count=%d",
-			 pj_snd_get_dev_count()));
-
-    return err;
+			 pjmedia_snd_get_dev_count()));
+
+    return err ? PJMEDIA_ERRNO_FROM_PORTAUDIO(err) : PJ_SUCCESS;
 }
 
@@ -161,5 +161,5 @@
  * Get device count.
  */
-PJ_DEF(int) pj_snd_get_dev_count(void)
+PJ_DEF(int) pjmedia_snd_get_dev_count(void)
 {
     return Pa_GetDeviceCount();
@@ -170,7 +170,7 @@
  * Get device info.
  */
-PJ_DEF(const pj_snd_dev_info*) pj_snd_get_dev_info(unsigned index)
-{
-    static pj_snd_dev_info info;
+PJ_DEF(const pjmedia_snd_dev_info*) pjmedia_snd_get_dev_info(unsigned index)
+{
+    static pjmedia_snd_dev_info info;
     const PaDeviceInfo *pa_info;
 
@@ -193,15 +193,15 @@
  * Open stream.
  */
-PJ_DEF(pj_status_t) pj_snd_open_recorder( int index,
+PJ_DEF(pj_status_t) pjmedia_snd_open_recorder( int index,
 					  unsigned clock_rate,
 					  unsigned channel_count,
 					  unsigned samples_per_frame,
 					  unsigned bits_per_sample,
-					  pj_snd_rec_cb rec_cb,
+					  pjmedia_snd_rec_cb rec_cb,
 					  void *user_data,
-					  pj_snd_stream **p_snd_strm)
+					  pjmedia_snd_stream **p_snd_strm)
 {
     pj_pool_t *pool;
-    pj_snd_stream *stream;
+    pjmedia_snd_stream *stream;
     PaStreamParameters inputParam;
     int sampleFormat;
@@ -278,15 +278,15 @@
 
 
-PJ_DEF(pj_status_t) pj_snd_open_player( int index,
+PJ_DEF(pj_status_t) pjmedia_snd_open_player( int index,
 					unsigned clock_rate,
 					unsigned channel_count,
 					unsigned samples_per_frame,
 					unsigned bits_per_sample,
-					pj_snd_play_cb play_cb,
+					pjmedia_snd_play_cb play_cb,
 					void *user_data,
-					pj_snd_stream **p_snd_strm)
+					pjmedia_snd_stream **p_snd_strm)
 {
     pj_pool_t *pool;
-    pj_snd_stream *stream;
+    pjmedia_snd_stream *stream;
     PaStreamParameters outputParam;
     int sampleFormat;
@@ -367,15 +367,15 @@
  * Start stream.
  */
-PJ_DEF(pj_status_t) pj_snd_stream_start(pj_snd_stream *stream)
-{
-    pj_status_t status;
+PJ_DEF(pj_status_t) pjmedia_snd_stream_start(pjmedia_snd_stream *stream)
+{
+    pj_status_t err;
 
     PJ_LOG(5,(THIS_FILE, "Starting %s stream..", stream->name.ptr));
 
-    status = Pa_StartStream(stream->stream);
-
-    PJ_LOG(5,(THIS_FILE, "Done, status=%d", status));
-
-    return status;
+    err = Pa_StartStream(stream->stream);
+
+    PJ_LOG(5,(THIS_FILE, "Done, status=%d", err));
+
+    return err ? PJMEDIA_ERRNO_FROM_PORTAUDIO(err) : PJ_SUCCESS;
 }
 
@@ -383,5 +383,5 @@
  * Stop stream.
  */
-PJ_DEF(pj_status_t) pj_snd_stream_stop(pj_snd_stream *stream)
+PJ_DEF(pj_status_t) pjmedia_snd_stream_stop(pjmedia_snd_stream *stream)
 {
     int i, err;
@@ -399,5 +399,5 @@
     PJ_LOG(5,(THIS_FILE, "Done, status=%d", err));
 
-    return err;
+    return err ? PJMEDIA_ERRNO_FROM_PORTAUDIO(err) : PJ_SUCCESS;
 }
 
@@ -405,5 +405,5 @@
  * Destroy stream.
  */
-PJ_DEF(pj_status_t) pj_snd_stream_close(pj_snd_stream *stream)
+PJ_DEF(pj_status_t) pjmedia_snd_stream_close(pjmedia_snd_stream *stream)
 {
     int i, err;
@@ -424,5 +424,6 @@
     err = Pa_CloseStream(stream->stream);
     pj_pool_release(stream->pool);
-    return err;
+
+    return err ? PJMEDIA_ERRNO_FROM_PORTAUDIO(err) : PJ_SUCCESS;
 }
 
@@ -430,9 +431,13 @@
  * Deinitialize sound library.
  */
-PJ_DEF(pj_status_t) pj_snd_deinit(void)
-{
+PJ_DEF(pj_status_t) pjmedia_snd_deinit(void)
+{
+    int err;
+
     PJ_LOG(4,(THIS_FILE, "PortAudio sound library shutting down.."));
 
-    return Pa_Terminate();
+    err = Pa_Terminate();
+
+    return err ? PJMEDIA_ERRNO_FROM_PORTAUDIO(err) : PJ_SUCCESS;
 }
 
Index: /pjproject/trunk/pjmedia/src/pjmedia/rtcp.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia/rtcp.c	(revision 320)
+++ /pjproject/trunk/pjmedia/src/pjmedia/rtcp.c	(revision 321)
@@ -32,5 +32,5 @@
  * Get NTP time.
  */
-static void rtcp_get_ntp_time(struct pj_rtcp_ntp_rec *ntp)
+static void rtcp_get_ntp_time(struct pjmedia_rtcp_ntp_rec *ntp)
 {
     pj_time_val tv;
@@ -45,9 +45,10 @@
 
 
-PJ_DEF(void) pj_rtcp_init(pj_rtcp_session *s, pj_uint32_t ssrc)
-{
-    pj_rtcp_pkt *rtcp_pkt = &s->rtcp_pkt;
-    
-    pj_memset(rtcp_pkt, 0, sizeof(pj_rtcp_pkt));
+PJ_DEF(void) pjmedia_rtcp_init(pjmedia_rtcp_session *s, 
+			       pj_uint32_t ssrc)
+{
+    pjmedia_rtcp_pkt *rtcp_pkt = &s->rtcp_pkt;
+    
+    pj_memset(rtcp_pkt, 0, sizeof(pjmedia_rtcp_pkt));
     
     /* Init time */
@@ -67,5 +68,5 @@
 }
 
-PJ_DEF(void) pj_rtcp_fini(pj_rtcp_session *session)
+PJ_DEF(void) pjmedia_rtcp_fini(pjmedia_rtcp_session *session)
 {
     /* Nothing to do. */
@@ -73,5 +74,5 @@
 }
 
-static void rtcp_init_seq(pj_rtcp_session *s, pj_uint16_t  seq)
+static void rtcp_init_seq(pjmedia_rtcp_session *s, pj_uint16_t  seq)
 {
     s->received = 0;
@@ -84,5 +85,7 @@
 }
 
-PJ_DEF(void) pj_rtcp_rx_rtp(pj_rtcp_session *s, pj_uint16_t seq, pj_uint32_t rtp_ts)
+PJ_DEF(void) pjmedia_rtcp_rx_rtp(pjmedia_rtcp_session *s, 
+				 pj_uint16_t seq, 
+				 pj_uint32_t rtp_ts)
 {   
     pj_uint32_t arrival;
@@ -130,17 +133,19 @@
 }
 
-PJ_DEF(void) pj_rtcp_tx_rtp(pj_rtcp_session *s, pj_uint16_t  bytes_payload_size)
-{
-    pj_rtcp_pkt *rtcp_pkt = &s->rtcp_pkt;
+PJ_DEF(void) pjmedia_rtcp_tx_rtp(pjmedia_rtcp_session *s, 
+				 pj_uint16_t  bytes_payload_size)
+{
+    pjmedia_rtcp_pkt *rtcp_pkt = &s->rtcp_pkt;
     rtcp_pkt->sr.sender_pcount = pj_htonl( pj_ntohl(rtcp_pkt->sr.sender_pcount) + 1);
     rtcp_pkt->sr.sender_bcount = pj_htonl( pj_ntohl(rtcp_pkt->sr.sender_bcount) + bytes_payload_size );
 }
 
-static void rtcp_build_rtcp(pj_rtcp_session *s, pj_uint32_t receiver_ssrc)
+static void rtcp_build_rtcp(pjmedia_rtcp_session *s, 
+			    pj_uint32_t receiver_ssrc)
 {   
     pj_uint32_t expected;
     pj_uint32_t u32;
     pj_uint32_t expected_interval, received_interval, lost_interval;
-    pj_rtcp_pkt *rtcp_pkt = &s->rtcp_pkt;
+    pjmedia_rtcp_pkt *rtcp_pkt = &s->rtcp_pkt;
     
     /* SSRC and last_seq */
@@ -176,8 +181,10 @@
 }
 
-PJ_DEF(void) pj_rtcp_build_rtcp(pj_rtcp_session *session, pj_rtcp_pkt **ret_p_pkt, int *len)
-{
-    pj_rtcp_pkt *rtcp_pkt = &session->rtcp_pkt;
-    pj_rtcp_ntp_rec ntp;
+PJ_DEF(void) pjmedia_rtcp_build_rtcp(pjmedia_rtcp_session *session, 
+				     pjmedia_rtcp_pkt **ret_p_pkt, 
+				     int *len)
+{
+    pjmedia_rtcp_pkt *rtcp_pkt = &session->rtcp_pkt;
+    pjmedia_rtcp_ntp_rec ntp;
     pj_time_val now;
     
@@ -214,5 +221,5 @@
     /* Return pointer. */
     *ret_p_pkt = rtcp_pkt;
-    *len = sizeof(pj_rtcp_pkt);
-}
-
+    *len = sizeof(pjmedia_rtcp_pkt);
+}
+
Index: /pjproject/trunk/pjmedia/src/pjmedia/sound_port.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia/sound_port.c	(revision 321)
+++ /pjproject/trunk/pjmedia/src/pjmedia/sound_port.c	(revision 321)
@@ -0,0 +1,317 @@
+/* $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 
+ */
+#include <pjmedia/sound_port.h>
+#include <pjmedia/errno.h>
+#include <pj/assert.h>
+#include <pj/string.h>	    /* pj_memset() */
+
+struct pjmedia_snd_port
+{
+    int			 snd_index;
+    pjmedia_snd_stream	*snd_stream;
+    pjmedia_dir		 dir;
+    pjmedia_port	*port;
+
+    unsigned		 clock_rate;
+    unsigned		 channel_count;
+    unsigned		 samples_per_frame;
+    unsigned		 bits_per_sample;
+};
+
+/*
+ * The callback called by sound player when it needs more samples to be
+ * played.
+ */
+static pj_status_t play_cb(/* in */   void *user_data,
+			   /* in */   pj_uint32_t timestamp,
+			   /* out */  void *output,
+			   /* out */  unsigned size)
+{
+    pjmedia_snd_port *snd_port = user_data;
+    pjmedia_port *port;
+    pjmedia_frame frame;
+    pj_status_t status;
+
+    /* We're risking accessing the port without holding any mutex.
+     * It's possible that port is disconnected then destroyed while
+     * we're trying to access it.
+     * But in the name of performance, we'll try this approach until
+     * someone complains when it crashes.
+     */
+    port = snd_port->port;
+    if (port == NULL)
+	goto no_frame;
+
+    frame.buf = output;
+    frame.size = size;
+    frame.timestamp.u32.lo = timestamp;
+
+    status = pjmedia_port_get_frame(port, &frame);
+    if (status != PJ_SUCCESS)
+	goto no_frame;
+
+    if (frame.type != PJMEDIA_FRAME_TYPE_AUDIO)
+	goto no_frame;
+
+    return PJ_SUCCESS;
+
+no_frame:
+    pj_memset(output, 0, size);
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * The callback called by sound recorder when it has finished capturing a
+ * frame.
+ */
+static pj_status_t rec_cb(/* in */   void *user_data,
+			  /* in */   pj_uint32_t timestamp,
+			  /* in */   const void *input,
+			  /* in*/    unsigned size)
+{
+    pjmedia_snd_port *snd_port = user_data;
+    pjmedia_port *port;
+    pjmedia_frame frame;
+
+    /* We're risking accessing the port without holding any mutex.
+     * It's possible that port is disconnected then destroyed while
+     * we're trying to access it.
+     * But in the name of performance, we'll try this approach until
+     * someone complains when it crashes.
+     */
+    port = snd_port->port;
+    if (port == NULL)
+	return PJ_SUCCESS;
+
+    frame.buf = (void*)input;
+    frame.size = size;
+    frame.type = PJMEDIA_FRAME_TYPE_AUDIO;
+    frame.timestamp.u32.lo = timestamp;
+
+    pjmedia_port_put_frame(port, &frame);
+
+    return PJ_SUCCESS;
+}
+
+/*
+ * Start the sound stream.
+ * This may be called even when the sound stream has already been started.
+ */
+static pj_status_t start_sound_device( pjmedia_snd_port *snd_port )
+{
+    pj_status_t status;
+
+    /* Check if sound has been started. */
+    if (snd_port->snd_stream != NULL)
+	return PJ_SUCCESS;
+
+    /* Open sound stream. */
+    if (snd_port->dir == PJMEDIA_DIR_ENCODING) {
+	status = pjmedia_snd_open_recorder( snd_port->snd_index, 
+					    snd_port->clock_rate,
+					    snd_port->channel_count,
+					    snd_port->samples_per_frame,
+					    snd_port->bits_per_sample,
+					    &rec_cb,
+					    snd_port,
+					    &snd_port->snd_stream);
+    } else {
+	status = pjmedia_snd_open_player( snd_port->snd_index, 
+					  snd_port->clock_rate,
+					  snd_port->channel_count,
+					  snd_port->samples_per_frame,
+					  snd_port->bits_per_sample,
+					  &play_cb,
+					  snd_port,
+					  &snd_port->snd_stream);
+    }
+
+    if (status != PJ_SUCCESS)
+	return status;
+
+    /* Start sound stream. */
+    status = pjmedia_snd_stream_start(snd_port->snd_stream);
+    if (status != PJ_SUCCESS) {
+	pjmedia_snd_stream_close(snd_port->snd_stream);
+	snd_port->snd_stream = NULL;
+	return status;
+    }
+
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * Stop the sound device.
+ * This may be called even when there's no sound device in the port.
+ */
+static pj_status_t stop_sound_device( pjmedia_snd_port *snd_port )
+{
+    /* Check if we have sound stream device. */
+    if (snd_port->snd_stream) {
+	pjmedia_snd_stream_stop(snd_port->snd_stream);
+	pjmedia_snd_stream_close(snd_port->snd_stream);
+	snd_port->snd_stream = NULL;
+    }
+
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * Create sound recorder port.
+ */
+PJ_DEF(pj_status_t) pjmedia_snd_port_create_rec( pj_pool_t *pool,
+						 int index,
+						 unsigned clock_rate,
+						 unsigned channel_count,
+						 unsigned samples_per_frame,
+						 unsigned bits_per_sample,
+						 unsigned options,
+						 pjmedia_snd_port **p_port)
+{
+    pjmedia_snd_port *snd_port;
+
+    PJ_ASSERT_RETURN(pool && p_port, PJ_EINVAL);
+    PJ_ASSERT_RETURN(options == 0, PJ_EINVAL);
+
+    snd_port = pj_pool_zalloc(pool, sizeof(pjmedia_snd_port));
+    PJ_ASSERT_RETURN(snd_port, PJ_ENOMEM);
+
+    snd_port->snd_index = index;
+    snd_port->dir = PJMEDIA_DIR_ENCODING;
+    snd_port->clock_rate = clock_rate;
+    snd_port->channel_count = channel_count;
+    snd_port->samples_per_frame = samples_per_frame;
+    snd_port->bits_per_sample = bits_per_sample;
+
+    *p_port = snd_port;
+
+    /* Start sound device immediately.
+     * If there's no port connected, the sound callback will return
+     * empty signal.
+     */
+    return start_sound_device( snd_port );
+}
+
+
+/*
+ * Create sound player port.
+ */
+PJ_DEF(pj_status_t) pjmedia_snd_port_create_player( pj_pool_t *pool,
+						    int index,
+						    unsigned clock_rate,
+						    unsigned channel_count,
+						    unsigned samples_per_frame,
+						    unsigned bits_per_sample,
+						    unsigned options,
+						    pjmedia_snd_port **p_port)
+{
+    pjmedia_snd_port *snd_port;
+
+    PJ_ASSERT_RETURN(pool && p_port, PJ_EINVAL);
+    PJ_ASSERT_RETURN(options == 0, PJ_EINVAL);
+
+    snd_port = pj_pool_zalloc(pool, sizeof(pjmedia_snd_port));
+    PJ_ASSERT_RETURN(snd_port, PJ_ENOMEM);
+
+    snd_port->snd_index = index;
+    snd_port->dir = PJMEDIA_DIR_DECODING;
+    snd_port->clock_rate = clock_rate;
+    snd_port->channel_count = channel_count;
+    snd_port->samples_per_frame = samples_per_frame;
+    snd_port->bits_per_sample = bits_per_sample;
+
+    *p_port = snd_port;
+
+    /* Start sound device immediately.
+     * If there's no port connected, the sound callback will return
+     * empty signal.
+     */
+    return start_sound_device( snd_port );
+}
+
+
+/*
+ * Destroy port (also destroys the sound device).
+ */
+PJ_DEF(pj_status_t) pjmedia_snd_port_destroy(pjmedia_snd_port *snd_port)
+{
+    PJ_ASSERT_RETURN(snd_port, PJ_EINVAL);
+
+    return stop_sound_device(snd_port);
+}
+
+
+/*
+ * Connect a port.
+ */
+PJ_DEF(pj_status_t) pjmedia_snd_port_connect( pjmedia_snd_port *snd_port,
+					      pjmedia_port *port)
+{
+    pjmedia_port_info *pinfo;
+
+    PJ_ASSERT_RETURN(snd_port && port, PJ_EINVAL);
+
+    /* Check that port has the same configuration as the sound device
+     * port.
+     */
+    pinfo = &port->info;
+    if (pinfo->sample_rate != snd_port->clock_rate)
+	return PJMEDIA_ENCCLOCKRATE;
+
+    if (pinfo->samples_per_frame != snd_port->samples_per_frame)
+	return PJMEDIA_ENCSAMPLESPFRAME;
+
+    if (pinfo->channel_count != snd_port->channel_count)
+	return PJMEDIA_ENCCHANNEL;
+
+    if (pinfo->bits_per_sample != snd_port->bits_per_sample)
+	return PJMEDIA_ENCBITS;
+
+    /* Port is okay. */
+    snd_port->port = port;
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * Get the connected port.
+ */
+PJ_DEF(pjmedia_port*) pjmedia_snd_port_get_port(pjmedia_snd_port *snd_port)
+{
+    PJ_ASSERT_RETURN(snd_port, NULL);
+    return snd_port->port;
+}
+
+
+/*
+ * Disconnect port.
+ */
+PJ_DEF(pj_status_t) pjmedia_snd_port_disconnect(pjmedia_snd_port *snd_port)
+{
+    PJ_ASSERT_RETURN(snd_port, PJ_EINVAL);
+
+    snd_port->port = NULL;
+
+    return PJ_SUCCESS;
+}
+
+
Index: /pjproject/trunk/pjmedia/src/pjmedia/stream.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia/stream.c	(revision 320)
+++ /pjproject/trunk/pjmedia/src/pjmedia/stream.c	(revision 321)
@@ -100,5 +100,5 @@
     unsigned		     rem_src_cnt;   /**< if different, # of pkt rcv */
 
-    pj_rtcp_session	     rtcp;	    /**< RTCP for incoming RTP.	    */
+    pjmedia_rtcp_session     rtcp;	    /**< RTCP for incoming RTP.	    */
 
     pj_bool_t		     quit_flag;	    /**< To signal thread exit.	    */
@@ -521,5 +521,5 @@
 	    continue;
 	}
-	pj_rtcp_rx_rtp(&stream->rtcp, pj_ntohs(hdr->seq), pj_ntohl(hdr->ts));
+	pjmedia_rtcp_rx_rtp(&stream->rtcp, pj_ntohs(hdr->seq), pj_ntohl(hdr->ts));
 
 	/* Update stat */
@@ -721,5 +721,5 @@
     /* Init RTCP session: */
 
-    pj_rtcp_init(&stream->rtcp, info->ssrc);
+    pjmedia_rtcp_init(&stream->rtcp, info->ssrc);
 
 
@@ -790,6 +790,6 @@
     if (stream->enc && stream->enc->snd_stream) {
 
-	pj_snd_stream_stop(stream->enc->snd_stream);
-	pj_snd_stream_close(stream->enc->snd_stream);
+	pjmedia_snd_stream_stop(stream->enc->snd_stream);
+	pjmedia_snd_stream_close(stream->enc->snd_stream);
 	stream->enc->snd_stream = NULL;
 
@@ -802,6 +802,6 @@
     if (stream->dec && stream->dec->snd_stream) {
 
-	pj_snd_stream_stop(stream->dec->snd_stream);
-	pj_snd_stream_close(stream->dec->snd_stream);
+	pjmedia_snd_stream_stop(stream->dec->snd_stream);
+	pjmedia_snd_stream_close(stream->dec->snd_stream);
 	stream->dec->snd_stream = NULL;
 
@@ -858,5 +858,5 @@
     if (stream->enc && (stream->dir & PJMEDIA_DIR_ENCODING)) {
 	stream->enc->paused = 0;
-	//pj_snd_stream_start(stream->enc->snd_stream);
+	//pjmedia_snd_stream_start(stream->enc->snd_stream);
 	PJ_LOG(4,(THIS_FILE, "Encoder stream started"));
     } else {
@@ -866,5 +866,5 @@
     if (stream->dec && (stream->dir & PJMEDIA_DIR_DECODING)) {
 	stream->dec->paused = 0;
-	//pj_snd_stream_start(stream->dec->snd_stream);
+	//pjmedia_snd_stream_start(stream->dec->snd_stream);
 	PJ_LOG(4,(THIS_FILE, "Decoder stream started"));
     } else {
Index: /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c	(revision 320)
+++ /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c	(revision 321)
@@ -1085,9 +1085,4 @@
 
 
-    /* Destroy sound framework: 
-     * (this should be done in pjmedia_shutdown())
-     */
-    pj_snd_deinit();
-
     /* Shutdown all codecs: */
     for (i = pjsua.codec_cnt-1; i >= 0; --i) {
