Index: pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/pjsua2.i
===================================================================
--- pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/pjsua2.i	(revision 4661)
+++ pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/pjsua2.i	(revision 4662)
@@ -40,5 +40,4 @@
 %feature("director") FindBuddyMatch;
 
-
 //
 // STL stuff.
@@ -46,5 +45,4 @@
 %include "std_string.i"
 %include "std_vector.i"
-
 
 %template(StringVector)			std::vector<std::string>;
@@ -74,5 +72,8 @@
 %template(SipMultipartPartVector)	std::vector<pj::SipMultipartPart>;
 %template(BuddyVector)			std::vector<pj::Buddy*>;
+%template(AudioMediaVector)		std::vector<pj::AudioMedia*>;
+%template(MediaFormatVector)		std::vector<pj::MediaFormat*>;
 
+%include "pjsua2/media.hpp"
 %include "pjsua2/endpoint.hpp"
 %include "pjsua2/presence.hpp"
Index: pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/symbols.i
===================================================================
--- pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/symbols.i	(revision 4661)
+++ pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/symbols.i	(revision 4662)
@@ -41,4 +41,12 @@
 enum pjmedia_vid_dev_std_index {PJMEDIA_VID_DEFAULT_CAPTURE_DEV = -1, PJMEDIA_VID_DEFAULT_RENDER_DEV = -2, PJMEDIA_VID_INVALID_DEV = -3};
 
+enum pjmedia_file_writer_option {PJMEDIA_FILE_WRITE_PCM = 0, PJMEDIA_FILE_WRITE_ALAW = 1, PJMEDIA_FILE_WRITE_ULAW = 2};
+
+enum pjmedia_file_player_option {PJMEDIA_FILE_NO_LOOP = 1};
+
+typedef enum pjmedia_type {PJMEDIA_TYPE_NONE, PJMEDIA_TYPE_AUDIO, PJMEDIA_TYPE_VIDEO, PJMEDIA_TYPE_APPLICATION, PJMEDIA_TYPE_UNKNOWN} pjmedia_type;
+
+typedef enum pjmedia_format_id {PJMEDIA_FORMAT_L16 = 0, PJMEDIA_FORMAT_PCM = PJMEDIA_FORMAT_L16, PJMEDIA_FORMAT_PCMA = ((('W' << 24) | ('A' << 16)) | ('L' << 8)) | 'A', PJMEDIA_FORMAT_ALAW = PJMEDIA_FORMAT_PCMA, PJMEDIA_FORMAT_PCMU = ((('W' << 24) | ('A' << 16)) | ('L' << 8)) | 'u', PJMEDIA_FORMAT_ULAW = PJMEDIA_FORMAT_PCMU, PJMEDIA_FORMAT_AMR = ((('R' << 24) | ('M' << 16)) | ('A' << 8)) | ' ', PJMEDIA_FORMAT_G729 = ((('9' << 24) | ('2' << 16)) | ('7' << 8)) | 'G', PJMEDIA_FORMAT_ILBC = ((('C' << 24) | ('B' << 16)) | ('L' << 8)) | 'I', PJMEDIA_FORMAT_RGB24 = ((('3' << 24) | ('B' << 16)) | ('G' << 8)) | 'R', PJMEDIA_FORMAT_RGBA = ((('A' << 24) | ('B' << 16)) | ('G' << 8)) | 'R', PJMEDIA_FORMAT_BGRA = ((('A' << 24) | ('R' << 16)) | ('G' << 8)) | 'B', PJMEDIA_FORMAT_RGB32 = PJMEDIA_FORMAT_RGBA, PJMEDIA_FORMAT_DIB = (((' ' << 24) | ('B' << 16)) | ('I' << 8)) | 'D', PJMEDIA_FORMAT_GBRP = ((('P' << 24) | ('R' << 16)) | ('B' << 8)) | 'G', PJMEDIA_FORMAT_AYUV = ((('V' << 24) | ('U' << 16)) | ('Y' << 8)) | 'A', PJMEDIA_FORMAT_YUY2 = ((('2' << 24) | ('Y' << 16)) | ('U' << 8)) | 'Y', PJMEDIA_FORMAT_UYVY = ((('Y' << 24) | ('V' << 16)) | ('Y' << 8)) | 'U', PJMEDIA_FORMAT_YVYU = ((('U' << 24) | ('Y' << 16)) | ('V' << 8)) | 'Y', PJMEDIA_FORMAT_I420 = ((('0' << 24) | ('2' << 16)) | ('4' << 8)) | 'I', PJMEDIA_FORMAT_IYUV = PJMEDIA_FORMAT_I420, PJMEDIA_FORMAT_YV12 = ((('2' << 24) | ('1' << 16)) | ('V' << 8)) | 'Y', PJMEDIA_FORMAT_I422 = ((('2' << 24) | ('2' << 16)) | ('4' << 8)) | 'I', PJMEDIA_FORMAT_I420JPEG = ((('0' << 24) | ('2' << 16)) | ('4' << 8)) | 'J', PJMEDIA_FORMAT_I422JPEG = ((('2' << 24) | ('2' << 16)) | ('4' << 8)) | 'J', PJMEDIA_FORMAT_H261 = ((('1' << 24) | ('6' << 16)) | ('2' << 8)) | 'H', PJMEDIA_FORMAT_H263 = ((('3' << 24) | ('6' << 16)) | ('2' << 8)) | 'H', PJMEDIA_FORMAT_H263P = ((('3' << 24) | ('6' << 16)) | ('2' << 8)) | 'P', PJMEDIA_FORMAT_H264 = ((('4' << 24) | ('6' << 16)) | ('2' << 8)) | 'H', PJMEDIA_FORMAT_MJPEG = ((('G' << 24) | ('P' << 16)) | ('J' << 8)) | 'M', PJMEDIA_FORMAT_MPEG1VIDEO = ((('V' << 24) | ('1' << 16)) | ('P' << 8)) | 'M', PJMEDIA_FORMAT_MPEG2VIDEO = ((('V' << 24) | ('2' << 16)) | ('P' << 8)) | 'M', PJMEDIA_FORMAT_MPEG4 = ((('4' << 24) | ('G' << 16)) | ('P' << 8)) | 'M'} pjmedia_format_id;
+
 typedef enum pjsip_cred_data_type {PJSIP_CRED_DATA_PLAIN_PASSWD = 0, PJSIP_CRED_DATA_DIGEST = 1, PJSIP_CRED_DATA_EXT_AKA = 16} pjsip_cred_data_type;
 
Index: pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/symbols.lst
===================================================================
--- pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/symbols.lst	(revision 4661)
+++ pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/symbols.lst	(revision 4662)
@@ -1,3 +1,3 @@
-pj/types.h			pj_status_t pj_constants_ pj_uint8_t pj_int32_t		
+pj/types.h			pj_status_t pj_constants_ pj_uint8_t pj_int32_t         
 pj/file_io.h			pj_file_access
 pj/log.h			pj_log_decoration
@@ -5,17 +5,20 @@
 pj/ssl_sock.h			pj_ssl_cipher
 
-pjnath/nat_detect.h		pj_stun_nat_type
-pjnath/turn_session.h		pj_turn_tp_type
+pjnath/nat_detect.h          	pj_stun_nat_type
+pjnath/turn_session.h          	pj_turn_tp_type
 
-pjmedia/transport_srtp.h	pjmedia_srtp_use
-pjmedia/vid_stream.h		pjmedia_vid_stream_rc_method
-pjmedia-videodev/videodev.h	pjmedia_vid_dev_index pjmedia_vid_dev_std_index
+pjmedia/transport_srtp.h     	pjmedia_srtp_use
+pjmedia/vid_stream.h          	pjmedia_vid_stream_rc_method
+pjmedia-videodev/videodev.h     pjmedia_vid_dev_index pjmedia_vid_dev_std_index
+pjmedia/wav_port.h              pjmedia_file_writer_option pjmedia_file_player_option
+pjmedia/types.h                 pjmedia_type
+pjmedia/format.h		pjmedia_format_id
 
-pjsip/sip_auth.h		pjsip_cred_data_type
-pjsip/sip_msg.h			pjsip_status_code
-pjsip/sip_transport.h		pjsip_transport_type_e pjsip_transport_flags_e pjsip_transport_state
-pjsip/sip_transport_tls.h	pjsip_ssl_method
+pjsip/sip_auth.h          	pjsip_cred_data_type
+pjsip/sip_msg.h               	pjsip_status_code
+pjsip/sip_transport.h          	pjsip_transport_type_e pjsip_transport_flags_e pjsip_transport_state
+pjsip/sip_transport_tls.h     	pjsip_ssl_method
 
-pjsip-simple/rpid.h		pjrpid_activity
+pjsip-simple/rpid.h          	pjrpid_activity
 pjsip-simple/evsub.h		pjsip_evsub_state
 
Index: pjproject/branches/projects/pjsua2/pjsip/build/Makefile
===================================================================
--- pjproject/branches/projects/pjsua2/pjsip/build/Makefile	(revision 4661)
+++ pjproject/branches/projects/pjsua2/pjsip/build/Makefile	(revision 4662)
@@ -91,5 +91,5 @@
 export PJSUA2_LIB_OBJS += $(OS_OBJS) $(M_OBJS) $(CC_OBJS) $(HOST_OBJS) \
 			   account.o endpoint.o json.o persistent.o types.o \
-			   siptypes.o presence.o
+			   siptypes.o presence.o media.o
 export PJSUA2_LIB_CFLAGS += $(_CFLAGS) $(PJ_VIDEO_CFLAGS)
 export PJSUA2_LIB_CXXFLAGS = $(PJSUA2_LIB_CFLAGS) 
Index: pjproject/branches/projects/pjsua2/pjsip/include/pjsua2.hpp
===================================================================
--- pjproject/branches/projects/pjsua2/pjsip/include/pjsua2.hpp	(revision 4661)
+++ pjproject/branches/projects/pjsua2/pjsip/include/pjsua2.hpp	(revision 4662)
@@ -23,4 +23,5 @@
 #include <pjsua2/account.hpp>
 #include <pjsua2/presence.hpp>
+#include <pjsua2/media.hpp>
 #include <pjsua2/json.hpp>
 
Index: pjproject/branches/projects/pjsua2/pjsip/include/pjsua2/endpoint.hpp
===================================================================
--- pjproject/branches/projects/pjsua2/pjsip/include/pjsua2/endpoint.hpp	(revision 4661)
+++ pjproject/branches/projects/pjsua2/pjsip/include/pjsua2/endpoint.hpp	(revision 4662)
@@ -25,4 +25,5 @@
  */
 #include <pjsua2/persistent.hpp>
+#include <pjsua2/media.hpp>
 #include <pjsua2/siptypes.hpp>
 
@@ -946,4 +947,52 @@
     void transportClose(TransportId id) throw(Error);
 
+    /*************************************************************************
+     * Media operations
+     */
+
+    /**
+     * Add media to the media list.
+     *
+     * @param media	media to be added.
+     */
+    void addMedia(AudioMedia &media);
+
+    /**
+     * Remove media from the media list.
+     *
+     * @param media	media to be removed.
+     */
+    void removeMedia(AudioMedia &media);
+
+    /**
+     * Check if media has been added to the media list.
+     *
+     * @param media	media to be check.
+     *
+     * @return 		True if media has been added, false otherwise.
+     */
+    bool mediaExists(const AudioMedia &media) const;
+
+    /**
+     * Get maximum number of media port.
+     *
+     * @return		Maximum number of media port in the conference bridge.
+     */
+    unsigned mediaMaxPorts() const;
+
+    /**
+     * Get current number of active media port in the bridge.
+     *
+     * @return		The number of active media port.
+     */
+    unsigned mediaActivePorts() const;
+
+    /**
+     * Enumerate all media port.
+     *
+     * @return		The list of media port.
+     */
+    const AudioMediaVector &mediaEnumPorts() const throw(Error);
+
 public:
     /*
@@ -1010,6 +1059,7 @@
 
 private:
-    static Endpoint	*instance_;	// static instance
-    LogWriter		*writer;	// Custom writer, if any
+    static Endpoint		*instance_;	// static instance
+    LogWriter			*writer;	// Custom writer, if any
+    AudioMediaVector 	 	 mediaList;
 
     /* Endpoint static callbacks */
@@ -1071,6 +1121,6 @@
     static void on_mwi_info(pjsua_acc_id acc_id,
                             pjsua_mwi_info *mwi_info);
+
     static void on_buddy_state(pjsua_buddy_id buddy_id);
-
 };
 
Index: pjproject/branches/projects/pjsua2/pjsip/include/pjsua2/media.hpp
===================================================================
--- pjproject/branches/projects/pjsua2/pjsip/include/pjsua2/media.hpp	(revision 4662)
+++ pjproject/branches/projects/pjsua2/pjsip/include/pjsua2/media.hpp	(revision 4662)
@@ -0,0 +1,376 @@
+/* $Id$ */
+/*
+ * Copyright (C) 2013 Teluu Inc. (http://www.teluu.com)
+ *
+ * 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 __PJSUA2_MEDIA_HPP__
+#define __PJSUA2_MEDIA_HPP__
+
+/**
+ * @file pjsua2/media.hpp
+ * @brief PJSUA2 media operations
+ */
+#include <pjsua-lib/pjsua.h>
+#include <pjsua2/types.hpp>
+
+/**
+ * @defgroup PJSUA2_MED Media
+ * @ingroup PJSUA2_Ref
+ * @{
+ */
+
+/** PJSUA2 API is inside pj namespace */
+namespace pj
+{
+using std::string;
+using std::vector;
+
+/**
+ * This structure contains all the information needed to completely describe
+ * a media.
+ */
+struct MediaFormat
+{
+    /**
+     * The format id that specifies the audio sample or video pixel format.
+     * Some well known formats ids are declared in pjmedia_format_id
+     * enumeration.
+     *
+     * @see pjmedia_format_id
+     */
+    pj_uint32_t		id;
+
+    /**
+     * The top-most type of the media, as an information.
+     */
+    pjmedia_type	type;
+};
+
+/**
+ * This structure describe detail information about an audio media.
+ */
+struct MediaFormatAudio : public MediaFormat
+{
+    unsigned	clockRate;	/**< Audio clock rate in samples or Hz. */
+    unsigned	channelCount;	/**< Number of channels.		*/
+    unsigned	frameTimeUsec;  /**< Frame interval, in microseconds.	*/
+    unsigned	bitsPerSample;	/**< Number of bits per sample.		*/
+    pj_uint32_t	avgBps;		/**< Average bitrate			*/
+    pj_uint32_t	maxBps;		/**< Maximum bitrate			*/
+};
+
+/**
+ * This structure describe detail information about an video media.
+ */
+struct MediaFormatVideo : public MediaFormat
+{
+    unsigned		width;	    /**< Video width. 	*/
+    unsigned		height;	    /**< Video height. 	*/
+    int			fpsNum;	    /**< Frames per second numerator.	*/
+    int			fpsDenum;   /**< Frames per second denumerator.	*/
+    pj_uint32_t		avgBps;	    /**< Average bitrate.		*/
+    pj_uint32_t		maxBps;	    /**< Maximum bitrate.		*/
+};
+
+/** Array of MediaFormat */
+typedef std::vector<MediaFormat*> MediaFormatVector;
+
+
+/**
+ * This structure descibes information about a particular media port that
+ * has been registered into the conference bridge. 
+ */
+struct ConfPortInfo
+{
+    /**
+     * Conference port number.
+     */
+    int			portId;
+
+    /**
+     * Port name.
+     */
+    string		name;
+
+    /**
+     * Media audio format information
+     */
+    MediaFormatAudio	format;
+
+    /**
+     * Array of listeners (in other words, ports where this port is
+     * transmitting to.
+     */
+    IntVector		listeners;
+
+public:
+    /**
+     * Construct from pjsua_conf_port_info.
+     */
+    void fromPj(const pjsua_conf_port_info &port_info);
+
+};
+
+typedef void* MediaPort;
+
+/**
+ * Media.
+ */
+class Media
+{
+public:
+    /**
+     * Virtual destructor.
+     */
+    virtual ~Media();
+
+protected:
+    /**
+     * Constructor.
+     */
+    Media();
+};
+
+/**
+ * Audio Media.
+ */
+class AudioMedia : public Media
+{
+public:
+    /**
+    * Get information about the specified conference port.
+    */
+    ConfPortInfo getPortInfo() const throw(Error);
+
+    /**
+     * Get port Id.
+     */
+    int getPortId() const;
+
+    /**
+     * Get information from specific port id.
+     */
+    static ConfPortInfo getPortInfoFromId(int port_id) throw(Error);
+
+    /**
+     * Establish unidirectional media flow to sink. This media port
+     * will act as a source, and it may transmit to multiple destinations/sink.
+     * And if multiple sources are transmitting to the same sink, the media
+     * will be mixed together. Source and sink may refer to the same Media,
+     * effectively looping the media.
+     *
+     * If bidirectional media flow is desired, application needs to call
+     * this method twice, with the second one called from the opposite source
+     * media.
+     *
+     * @param sink		The destination Media.
+     */
+    void startTransmit(const AudioMedia &sink) const throw(Error);
+
+    /**
+     *  Stop media flow to destination/sink port.
+     *
+     * @param sink		The destination media.
+     *
+     */
+    void stopTransmit(const AudioMedia &sink) const throw(Error);
+
+    /**
+     * Adjust the signal level to be transmitted from the bridge to this
+     * media port by making it louder or quieter.
+     *
+     * @param level		Signal level adjustment. Value 1.0 means no
+     *				level adjustment, while value 0 means to mute
+     *				the port.
+     */
+    void adjustRxLevel(float level) throw(Error);
+
+    /**
+     * Adjust the signal level to be received from this media port (to
+     * the bridge) by making it louder or quieter.
+     *
+     * @param level		Signal level adjustment. Value 1.0 means no
+     *				level adjustment, while value 0 means to mute
+     *				the port.
+     */
+    void adjustTxLevel(float level) throw(Error);
+
+    /**
+     * Get the last received signal level.
+     */
+    unsigned getRxLevel() const throw(Error);
+
+    /**
+     * Get the last transmitted signal level.
+     */
+    unsigned getTxLevel() const throw(Error);
+
+    /**
+     * Virtual Destructor
+     */
+    virtual ~AudioMedia();
+
+protected:
+    /**
+     * Conference port Id.
+     */
+    int			 id;
+
+protected:
+    /**
+     * Default Constructor.
+     */
+    AudioMedia();
+
+    /**
+     * This method needs to be called by descendants of this class to register
+     * the media port created to the conference bridge and Endpoint's
+     * media list.
+     *
+     * param port  the media port to be registered to the conference bridge.
+     *
+     */
+    void registerMediaPort(MediaPort port) throw(Error);
+
+    /**
+     * This method needs to be called by descendants of this class to remove
+     * the media port from the conference bridge and Endpoint's media list.
+     * Descendant should only call this method if it has registered the media
+     * with the previous call to #registerMediaPort().
+     */
+    void unregisterMediaPort();
+
+private:
+    pj_caching_pool 	 mediaCachingPool;
+    pj_pool_t 		*mediaPool;
+
+private:
+    unsigned getSignalLevel(bool is_rx = true) const throw(Error);
+};
+
+/** Array of Audio Media */
+typedef std::vector<AudioMedia*> AudioMediaVector;
+
+/**
+ * Audio Media Player.
+ */
+class AudioMediaPlayer : public AudioMedia
+{
+public:
+    /** 
+     * Constructor.
+     */
+    AudioMediaPlayer();
+
+    /**
+     * Create a file player,  and automatically add this 
+     * player to the conference bridge.
+     *
+     * @param file_name	 The filename to be played. Currently only
+     *			 WAV files are supported, and the WAV file MUST be
+     *			 formatted as 16bit PCM mono/single channel (any
+     *			 clock rate is supported).
+     * @param options	 Optional option flag. Application may specify
+     *			 PJMEDIA_FILE_NO_LOOP to prevent playback loop.
+     */
+    void createPlayer(const string &file_name,
+		      unsigned options=PJMEDIA_FILE_NO_LOOP) throw(Error);
+
+    /**
+     * Create a file playlist media port, and automatically add the port
+     * to the conference bridge.
+     *
+     * @param file_names  Array of file names to be added to the play list.
+     *			  Note that the files must have the same clock rate,
+     *			  number of channels, and number of bits per sample.
+     * @param label	  Optional label to be set for the media port.
+     * @param options	  Optional option flag. Application may specify
+     *			  PJMEDIA_FILE_NO_LOOP to prevent looping.
+     */
+    void createPlaylist(const StringVector &file_names,
+			const string &label="",
+			unsigned options=PJMEDIA_FILE_NO_LOOP) throw(Error);
+
+    /**
+     * Set playback position. This operation is not valid for playlist.
+     */
+    void setPos(pj_uint32_t samples) throw(Error);
+
+    /**
+     * Virtual destructor.
+     */
+    virtual ~AudioMediaPlayer();
+
+private:
+    /**
+     * Player Id.
+     */
+    int	playerId;
+
+};
+
+/**
+ * Audio Media Recorder.
+ */
+class AudioMediaRecorder : public AudioMedia
+{
+public:
+    /**
+     * Constructor.
+     */
+    AudioMediaRecorder();
+
+    /**
+     * Create a file recorder, and automatically connect this recorder to
+     * the conference bridge. The recorder currently supports recording WAV
+     * file. The type of the recorder to use is determined by the extension of
+     * the file (e.g. ".wav").
+     *
+     * @param file_name	 Output file name. The function will determine the
+     *			 default format to be used based on the file extension.
+     *			 Currently ".wav" is supported on all platforms.
+     * @param enc_type	 Optionally specify the type of encoder to be used to
+     *			 compress the media, if the file can support different
+     *			 encodings. This value must be zero for now.
+     * @param max_size	 Maximum file size. Specify zero or -1 to remove size
+     *			 limitation. This value must be zero or -1 for now.
+     * @param options	 Optional options.
+     */
+    void createRecorder(const string &file_name,
+			unsigned enc_type=0,
+			pj_ssize_t max_size=0,
+			unsigned options=PJMEDIA_FILE_WRITE_PCM) throw(Error);
+
+    /**
+     * Virtual destructor.
+     */
+    virtual ~AudioMediaRecorder();
+
+private:
+    /**
+     * Recorder Id.
+     */
+    int	recorderId;
+};
+
+} // namespace pj
+
+/**
+ * @}  // PJSUA2_MED
+ */
+
+#endif	/* __PJSUA2_MEDIA_HPP__ */
Index: pjproject/branches/projects/pjsua2/pjsip/src/pjsua2/endpoint.cpp
===================================================================
--- pjproject/branches/projects/pjsua2/pjsip/src/pjsua2/endpoint.cpp	(revision 4661)
+++ pjproject/branches/projects/pjsua2/pjsip/src/pjsua2/endpoint.cpp	(revision 4662)
@@ -20,4 +20,5 @@
 #include <pjsua2/account.hpp>
 #include <pjsua2/presence.hpp>
+#include <algorithm>
 #include "util.hpp"
 
@@ -366,4 +367,10 @@
     }
     delete writer;
+    
+    while(mediaList.size() > 0) {
+	AudioMedia *cur_media = mediaList[0];
+	delete cur_media;
+    }
+
     instance_ = NULL;
 }
@@ -971,2 +978,47 @@
 ///////////////////////////////////////////////////////////////////////////////
 
+/*
+ * Media API
+ */
+unsigned Endpoint::mediaMaxPorts() const
+{
+    return pjsua_conf_get_max_ports();
+}
+
+unsigned Endpoint::mediaActivePorts() const
+{
+    return pjsua_conf_get_active_ports();
+}
+
+const AudioMediaVector &Endpoint::mediaEnumPorts() const throw(Error)
+{
+    return mediaList;
+}
+
+void Endpoint::addMedia(AudioMedia &media)
+{
+    if (mediaExists(media))
+	return;
+
+    mediaList.push_back(&media);
+}
+
+void Endpoint::removeMedia(AudioMedia &media)
+{
+    AudioMediaVector::iterator it = std::find(mediaList.begin(),
+					      mediaList.end(),
+					      &media);
+
+    if (it != mediaList.end())
+	mediaList.erase(it);
+
+}
+
+bool Endpoint::mediaExists(const AudioMedia &media) const
+{
+    AudioMediaVector::const_iterator it = std::find(mediaList.begin(),
+						    mediaList.end(),
+						    &media);
+
+    return (it != mediaList.end());
+}
Index: pjproject/branches/projects/pjsua2/pjsip/src/pjsua2/media.cpp
===================================================================
--- pjproject/branches/projects/pjsua2/pjsip/src/pjsua2/media.cpp	(revision 4662)
+++ pjproject/branches/projects/pjsua2/pjsip/src/pjsua2/media.cpp	(revision 4662)
@@ -0,0 +1,283 @@
+/* $Id$ */
+/*
+ * Copyright (C) 2013 Teluu Inc. (http://www.teluu.com)
+ *
+ * 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 <pj/ctype.h>
+#include <pjsua2/media.hpp>
+#include <pjsua2/types.hpp>
+#include <pjsua2/endpoint.hpp>
+#include "util.hpp"
+
+using namespace pj;
+using namespace std;
+
+#define THIS_FILE		"media.cpp"
+#define MAX_FILE_NAMES 		64
+
+///////////////////////////////////////////////////////////////////////////////
+/* Audio Media operations. */
+void ConfPortInfo::fromPj(const pjsua_conf_port_info &port_info)
+{
+    portId = port_info.slot_id;
+    name = pj2Str(port_info.name);
+
+    format.id = PJMEDIA_FORMAT_PCM;
+    format.type = PJMEDIA_TYPE_AUDIO;
+    format.clockRate = port_info.clock_rate;
+    format.channelCount = port_info.channel_count;
+    format.bitsPerSample = port_info.bits_per_sample;
+    format.frameTimeUsec = (port_info.samples_per_frame *
+			   1000000) /
+			   (port_info.clock_rate *
+			   port_info.channel_count);
+
+    format.avgBps = format.maxBps = port_info.clock_rate *
+				    port_info.channel_count *
+				    port_info.bits_per_sample;
+
+    listeners.clear();
+    for (unsigned i=0; i<port_info.listener_cnt; ++i) {
+	listeners.push_back(port_info.listeners[i]);
+    }
+}
+///////////////////////////////////////////////////////////////////////////////
+Media::Media()
+{
+
+}
+
+Media::~Media()
+{
+
+}
+
+///////////////////////////////////////////////////////////////////////////////
+AudioMedia::AudioMedia() 
+: id(PJSUA_INVALID_ID), mediaPool(NULL)
+{
+
+}
+
+void AudioMedia::registerMediaPort(MediaPort port) throw(Error)
+{
+    /* Check if media already added to Conf bridge. */
+    pj_assert(!Endpoint::instance().mediaExists(*this));
+
+    if (port != NULL) {
+	pj_assert(id == PJSUA_INVALID_ID);
+
+	pj_caching_pool_init(&mediaCachingPool, NULL, 0);
+
+	mediaPool = pj_pool_create(&mediaCachingPool.factory,
+				   "media",
+				   512,
+				   512,
+				   NULL);
+
+	if (!mediaPool) {
+	    pj_caching_pool_destroy(&mediaCachingPool);
+	    PJSUA2_RAISE_ERROR(PJ_ENOMEM);
+	}
+
+	PJSUA2_CHECK_EXPR( pjsua_conf_add_port(mediaPool,
+					       (pjmedia_port *)port,
+					       &id) );
+    }
+
+    Endpoint::instance().addMedia(*this);
+}
+
+void AudioMedia::unregisterMediaPort()
+{
+    if (id != PJSUA_INVALID_ID)
+	pjsua_conf_remove_port(id);
+
+    if (mediaPool) {
+	pj_pool_release(mediaPool);
+	mediaPool = NULL;
+	pj_caching_pool_destroy(&mediaCachingPool);
+    }
+
+    id = PJSUA_INVALID_ID;
+
+    Endpoint::instance().removeMedia(*this);
+}
+
+AudioMedia::~AudioMedia() 
+{
+    unregisterMediaPort();
+}
+
+ConfPortInfo AudioMedia::getPortInfo() const throw(Error)
+{
+    return AudioMedia::getPortInfoFromId(id);
+}
+
+int AudioMedia::getPortId() const
+{
+    return id;
+}
+
+ConfPortInfo AudioMedia::getPortInfoFromId(int port_id) throw(Error)
+{
+    pjsua_conf_port_info pj_info;
+    ConfPortInfo pi;
+
+    PJSUA2_CHECK_EXPR( pjsua_conf_get_port_info(port_id, &pj_info) );
+    pi.fromPj(pj_info);
+    return pi;
+}
+
+void AudioMedia::startTransmit(const AudioMedia &sink) const throw(Error)
+{
+    PJSUA2_CHECK_EXPR( pjsua_conf_connect(id, sink.id) );
+}
+
+void AudioMedia::stopTransmit(const AudioMedia &sink) const throw(Error)
+{
+    PJSUA2_CHECK_EXPR( pjsua_conf_disconnect(id, sink.id) );
+}
+
+void AudioMedia::adjustRxLevel(float level) throw(Error)
+{
+    PJSUA2_CHECK_EXPR( pjsua_conf_adjust_rx_level(id, level) );
+}
+
+void AudioMedia::adjustTxLevel(float level) throw(Error)
+{
+    PJSUA2_CHECK_EXPR( pjsua_conf_adjust_tx_level(id, level) );
+}
+
+unsigned AudioMedia::getRxLevel() const throw(Error)
+{
+    return getSignalLevel(true);
+}
+
+unsigned AudioMedia::getTxLevel() const throw(Error)
+{
+    return getSignalLevel(false);
+}
+
+unsigned AudioMedia::getSignalLevel(bool is_rx) const throw(Error)
+{    
+    unsigned rx_level;
+    unsigned tx_level;
+    
+    PJSUA2_CHECK_EXPR( pjsua_conf_get_signal_level(id, &tx_level, &rx_level) );
+    return is_rx?rx_level:tx_level;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+AudioMediaPlayer::AudioMediaPlayer()
+: playerId(PJSUA_INVALID_ID)
+{
+
+}
+
+AudioMediaPlayer::~AudioMediaPlayer()
+{
+    if (playerId != PJSUA_INVALID_ID)
+	pjsua_player_destroy(playerId);
+}
+
+void AudioMediaPlayer::createPlayer(const string &file_name,
+				    unsigned options)
+				    throw(Error)
+{
+    pj_str_t pj_name = str2Pj(file_name);
+
+    PJSUA2_CHECK_EXPR( pjsua_player_create(&pj_name,
+					   options, 
+					   &playerId) );
+
+    /* Get media port id. */
+    id = pjsua_player_get_conf_port(playerId);
+
+    registerMediaPort(NULL);
+}
+
+void AudioMediaPlayer::createPlaylist(const StringVector &file_names,
+				      const string &label,
+				      unsigned options)
+				      throw(Error)
+{
+    pj_str_t pj_files[MAX_FILE_NAMES];
+    unsigned i, count = 0;
+    pj_str_t pj_lbl = str2Pj(label);
+
+    count = PJ_ARRAY_SIZE(pj_files);
+
+    for(i=0; i<file_names.size() && i<count;++i)
+    {
+	const string &file_name = file_names[i];
+	
+	pj_files[i] = str2Pj(file_name);
+    }
+
+    PJSUA2_CHECK_EXPR( pjsua_playlist_create(pj_files,
+					     i,
+					     &pj_lbl,
+					     options, 
+					     &playerId) );
+
+    /* Get media port id. */
+    id = pjsua_player_get_conf_port(playerId);
+
+    registerMediaPort(NULL);
+}
+
+void AudioMediaPlayer::setPos(pj_uint32_t samples) throw(Error)
+{
+    PJSUA2_CHECK_EXPR( pjsua_player_set_pos(playerId, samples) );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+AudioMediaRecorder::AudioMediaRecorder()
+: recorderId(PJSUA_INVALID_ID)
+{
+
+}
+
+AudioMediaRecorder::~AudioMediaRecorder()
+{
+    if (recorderId != PJSUA_INVALID_ID)
+	pjsua_recorder_destroy(recorderId);
+}
+
+void AudioMediaRecorder::createRecorder(const string &file_name,
+				        unsigned enc_type,
+				        pj_ssize_t max_size,
+				        unsigned options)
+				        throw(Error)
+{
+    pj_str_t pj_name = str2Pj(file_name);
+
+    PJSUA2_CHECK_EXPR( pjsua_recorder_create(&pj_name,
+					     enc_type,
+					     NULL,
+					     -1,
+					     options,
+					     &recorderId) );
+
+    /* Get media port id. */
+    id = pjsua_recorder_get_conf_port(recorderId);
+
+    registerMediaPort(NULL);
+}
+
