diff --git a/sflphone-common/configure.ac b/sflphone-common/configure.ac
index 1149007f870418208f8318826987ccf1b18f6b29..b1d3d4d7d982dc0f9333ed152e11b31e5150046e 100644
--- a/sflphone-common/configure.ac
+++ b/sflphone-common/configure.ac
@@ -407,7 +407,7 @@ AC_DEFUN([BB_ENABLE_DOXYGEN],
 
 	if test x$DOT = x; then
 	if test "x$enable_dot" = xyes; then
-AC_MSG_ERROR([could not find dot])
+	AC_MSG_ERROR([could not find dot])
 	fi
 	enable_dot=no
 	else
@@ -416,24 +416,22 @@ AC_MSG_ERROR([could not find dot])
 	AM_CONDITIONAL(ENABLE_DOXYGEN, test x$enable_doc = xtrue)
 	AC_SUBST(enable_dot)
 	AC_SUBST(enable_html_docs)
-AC_SUBST(enable_latex_docs)
+	AC_SUBST(enable_latex_docs)
 	])
-# Acutally perform the doxygen check
+	# Acutally perform the doxygen check
 	BB_ENABLE_DOXYGEN
 
 	dnl Datadir directory
 	sflphone_datadir=$datadir/sflphone
-AC_SUBST(sflphone_datadir)
+	AC_SUBST(sflphone_datadir)
 
 	dnl Dbus Service activation part
 	DBUS_SERVICES_DIR="$datadir/dbus-1/services"
-AC_SUBST(DBUS_SERVICES_DIR)
+	AC_SUBST(DBUS_SERVICES_DIR)
 	AC_DEFINE_UNQUOTED(DBUS_SERVICES_DIR, "$DBUS_SERVICES_DIR", [Where services dir for DBUS is])
 
 # Go!
 	AC_SUBST(SFLPHONE_CFLAGS)
-AC_SUBST(SFLPHONE_LIBS)
+	AC_SUBST(SFLPHONE_LIBS)
 	AC_OUTPUT
 	AC_MSG_NOTICE([[Configuration done! Please make sure that pjsip library (libs/pjproject) has already been compiled. Run `make' to build the software.]])
-
-
diff --git a/sflphone-common/globals.mak b/sflphone-common/globals.mak
index 23f700e61f5cad26b71d0550c4a5ce63c3955780..0c408d19286bdf59a1202bd2ccf87bb04ce3c928 100644
--- a/sflphone-common/globals.mak
+++ b/sflphone-common/globals.mak
@@ -56,6 +56,9 @@ AM_CPPFLAGS = \
 	-DPREFIX=\"$(prefix)\" \
 	-DPROGSHAREDIR=\"${datadir}/sflphone\" \
 	$(ZEROCONFFLAGS) \
+	$(GSTREAMER_CFLAGS) \
+	$(LIBAVCODEC_CFLAGS) \
+	$(LIBSWSCALE_CFLAGS) \
 	$(IAX_FLAGS) \
 	$(SIP_CFLAGS) \
 	-DCODECS_DIR=\""$(sflcodecdir)"\" \
diff --git a/sflphone-common/src/Makefile.am b/sflphone-common/src/Makefile.am
index 09ce81355ddddb126ca478e8cd91f42fd59ce1e9..0a1de7748878ed5479eb46b7f2513b7dc48ebf4b 100644
--- a/sflphone-common/src/Makefile.am
+++ b/sflphone-common/src/Makefile.am
@@ -57,7 +57,10 @@ sflphoned_LDADD = \
 
 # sflphoned_LDFLAGS= -pg -luuid
 sflphoned_LDFLAGS= $(UUID_LIBS)
+		-DVERSION=\"$(VERSION)\"
+# libsflphone 
 
+sflphoned_LDADD = ./libsflphone.la
 noinst_LTLIBRARIES = libsflphone.la
 
 noinst_HEADERS = \
@@ -94,6 +97,36 @@ libsflphone_la_LIBADD = \
 	./hooks/libhooks.la \
 	./history/libhistory.la
 
+libsflphone_la_LDFLAGS = \
+		@CCGNU2_LIBS@ \
+		@CCEXT2_LIBS@ \
+		@ZRTPCPP_LIBS@ \
+		@GSTREAMER_LIBS@ \
+		@LIBAVCODEC_LIBS@ \
+		@LIBSWSCALE_LIBS@ \
+		$(PJSIP_LIBS) \
+		@CCRTP_LIBS@ \
+		@ALSA_LIBS@ \
+		@PULSEAUDIO_LIBS@ \
+		@SAMPLERATE_LIBS@ \
+		@libssl_LIBS@ \
+		@UUID_LIBS@
+
+libsflphone_la_CFLAGS = \
+		@CCGNU2_CFLAGS@ \
+		@CCEXT2_CFLAGS@ \
+		@ZRTPCPP_CFLAGS@ \
+		@GSTREAMER_CFLAGS@ \
+		@LIBAVCODEC_CFLAGS@ \
+		@LIBSWSCALE_CFLAGS@ \
+		$(PJSIP_CFLAGS) \
+		@CCRTP_CFLAGS@ \
+		@ALSA_CFLAGS@ \
+		@PULSEAUDIO_CFLAGS@ \
+		@SAMPLERATE_CFLAGS@ \
+		@libssl_CFLAGS@ \
+		@UUID_CFLAGS@
+
 libsflphone_la_SOURCES =
 
 indent:
diff --git a/sflphone-common/src/audio/Makefile.am b/sflphone-common/src/audio/Makefile.am
index ef2452b0bd8a6a0ba46df917e0bd5394b711b2ba..fcf2c2e9b7c22d91d5f70402124026168fa8fdce 100644
--- a/sflphone-common/src/audio/Makefile.am
+++ b/sflphone-common/src/audio/Makefile.am
@@ -21,6 +21,7 @@ libaudio_la_SOURCES = \
 		speexechocancel.cpp \
 		audioprocessing.cpp \
 		dcblocker.cpp \
+		jitterbuf.cpp \
 		$(SPEEX_SOURCES_CPP)
 
 noinst_HEADERS = \
@@ -37,6 +38,15 @@ noinst_HEADERS = \
 		speexechocancel.h \
 		audioprocessing.h \
 		dcblocker.h \
+		jitterbuf.h \
 		samplerateconverter.h
 
+libaudio_la_LIBADD = \
+	./audiortp/libaudiortp.la \
+	./codecs/libcodecdescriptor.la \
+	./alsa/libalsalayer.la \
+	./pulseaudio/libpulselayer.la \
+	./sound/libsound.la 
+
+
 
diff --git a/sflphone-common/src/audio/audiortp/AudioRtpSession.h b/sflphone-common/src/audio/audiortp/AudioRtpSession.h
index 0de99baa0108d19e4cd1bc4d0ad33b3edd1f1e87..b9eef5597162c49715c3b3232c0c004ab328ba4b 100644
--- a/sflphone-common/src/audio/audiortp/AudioRtpSession.h
+++ b/sflphone-common/src/audio/audiortp/AudioRtpSession.h
@@ -52,6 +52,8 @@
 
 #include <speex/speex_jitter.h>
 
+#include "audio/jitterbuf.h"
+
 // Frequency (in packet number)
 #define RTP_TIMESTAMP_RESET_FREQ 100
 
@@ -232,12 +234,25 @@ namespace sfl {
               */
              EventQueue _eventQueue;
 
-	     JitterBuffer *_jbuffer;
+	     /**
+	      * Adaptive jitter buffer
+	      */
+	     jitterbuf * _jbuffer;
+
+	     /**
+	      * Packet size in ms
+	      */
+	     int _packetLength;
 
 	     int _ts;
 
-	     int jitterSeqNum;
-	     
+	     /**
+	      * Current time in ms
+	      */
+	     int _currentTime;
+
+	     SpeexPreprocessState *_noiseState;
+
         protected:
 
              SIPCall * _ca;
@@ -267,6 +282,7 @@ namespace sfl {
      _timestampCount(0),
      _countNotificationTime(0),
      _jbuffer(NULL),
+     _noiseState(NULL),
      _ca (sipcall)
     {
         setCancel (cancelDefault);
@@ -283,13 +299,15 @@ namespace sfl {
         _layerFrameSize = _audiolayer->getFrameSize(); // in ms
         _layerSampleRate = _audiolayer->getSampleRate();
 
-	_jbuffer = jitter_buffer_init(20);
-	_ts = 0;
-	jitterSeqNum = 0;
+	_jbuffer = jb_new();
+
+	_jbuffer->info.conf.max_jitterbuf = 1000;
+	_jbuffer->info.conf.target_extra = 100;
+	_jbuffer->info.silence_begin_ts = 0;
 
-	// int i = 160;
-	// jitter_buffer_ctl(_jbuffer, JITTER_BUFFER_SET_MARGIN, &i);
-	// jitter_buffer_ctl(_jbuffer, JITTER_BUFFER_SET_CONCEALMENT_SIZE, &i);
+	_ts= 0;
+	_packetLength = 20;
+	_currentTime = 0;
     }
     
     template <typename D>
@@ -318,7 +336,14 @@ namespace sfl {
 	    delete _audiocodec; _audiocodec = NULL;
         }
 
-	jitter_buffer_destroy(_jbuffer);
+	if(_jbuffer) {
+	    jb_destroy(_jbuffer);
+	}
+
+	if(_noiseState) {
+	    speex_preprocess_state_destroy(_noiseState);
+	}
+	
     }
     
     template <typename D>
@@ -388,6 +413,29 @@ namespace sfl {
             _debug ("RTP: Setting static payload format");
             static_cast<D*>(this)->setPayloadFormat (ost::StaticPayloadFormat ( (ost::StaticPayloadType) _audiocodec->getPayload()));
         }
+
+	if(_noiseState) {
+	    speex_preprocess_state_destroy(_noiseState);
+	    _noiseState = NULL;
+	}
+
+	_noiseState = speex_preprocess_state_init(_codecSampleRate, _codecFrameSize);
+	int i=1;
+	speex_preprocess_ctl(_noiseState, SPEEX_PREPROCESS_SET_DENOISE, &i);
+	i=-20;
+	speex_preprocess_ctl(_noiseState, SPEEX_PREPROCESS_SET_NOISE_SUPPRESS, &i);
+	i=0;
+	speex_preprocess_ctl(_noiseState, SPEEX_PREPROCESS_SET_AGC, &i);
+	i=8000;
+	speex_preprocess_ctl(_noiseState, SPEEX_PREPROCESS_SET_AGC_TARGET, &i);
+	i=16000;
+	speex_preprocess_ctl(_noiseState, SPEEX_PREPROCESS_SET_AGC_LEVEL, &i);
+	i=0;
+	speex_preprocess_ctl(_noiseState, SPEEX_PREPROCESS_SET_DEREVERB, &i);
+	float f=0.0;
+	speex_preprocess_ctl(_noiseState, SPEEX_PREPROCESS_SET_DEREVERB_DECAY, &f);
+	f=0.0;
+	speex_preprocess_ctl(_noiseState, SPEEX_PREPROCESS_SET_DEREVERB_LEVEL, &f);
     }
     
     template <typename D>
@@ -581,6 +629,8 @@ namespace sfl {
                 // Store the number of samples for recording
                 _nSamplesSpkr = nbSample;
 
+		speex_preprocess_run(_noiseState, _spkrDataConverted);
+
                 // put data in audio layer, size in byte
 		_manager->getAudioDriver()->getMainBuffer()->putData (_spkrDataConverted, nbSample * sizeof (SFLDataFormat), 100, _ca->getCallId());
 
@@ -589,6 +639,7 @@ namespace sfl {
                 // Store the number of samples for recording
                 _nSamplesSpkr = nbSample;
 
+		// speex_preprocess_run(_noiseState, _spkrDataDecoded);
 
                 // put data in audio layer, size in byte
                 _manager->getAudioDriver()->getMainBuffer()->putData (_spkrDataDecoded, expandedSize, 100, _ca->getCallId());
@@ -653,76 +704,44 @@ namespace sfl {
         }
 
         const ost::AppDataUnit* adu = NULL;
-
 	int packetTimestamp = static_cast<D*>(this)->getFirstTimestamp();
         adu = static_cast<D*>(this)->getData(packetTimestamp);
-	// packetTimestamp = adu->getgetTimestamp();
 
-        if (adu == NULL) {
-            // _debug("No RTP audio stream\n");
-            return;
-        }
+	if(!adu)
+	  return;
+
+	unsigned char* spkrDataIn = NULL;
+	unsigned int size = 0;
+	int result;
+
+	jb_frame frame;
+
+	_jbuffer->info.conf.resync_threshold = 0;
+
+	if (adu) {
+
+	  spkrDataIn  = (unsigned char*) adu->getData(); // data in char
+	  size = adu->getSize(); // size in char
+
+	  
+
+	  result = jb_put(_jbuffer, spkrDataIn, JB_TYPE_VOICE, _packetLength, _ts+=20, _currentTime);
 
-        unsigned char* spkrData  = (unsigned char*) adu->getData(); // data in char
-        unsigned int size = adu->getSize(); // size in char
-
-	JitterBufferPacket jPacketIn;
-	jPacketIn.data = (char *)spkrData;
-	jPacketIn.len = size;
-	// jPacketIn.timestamp = static_cast<D*>(this)->getFirstTimestamp();
-	jPacketIn.timestamp = jitterSeqNum * _timestampIncrement;
-	jPacketIn.span = _timestampIncrement;
-	jPacketIn.sequence = ++jitterSeqNum;
-
-	jitter_buffer_put(_jbuffer, &jPacketIn);
-
-	JitterBufferPacket jPacketOut;
-	jPacketOut.data = new char[size];
-	jPacketOut.len = size;
-	jPacketIn.timestamp = 0;
-	jPacketIn.span = 0;
-	jPacketIn.sequence = 0;
-
-	int desiredSpan = _timestampIncrement;
-	spx_int32_t offs = 0;
-
-	int result = JITTER_BUFFER_INTERNAL_ERROR;
-	result = jitter_buffer_get(_jbuffer, &jPacketOut, desiredSpan, &offs);
-	jitter_buffer_tick(_jbuffer);
-
-	/*
-	switch(result) {
-	  case JITTER_BUFFER_OK:
-	    _debug("JITTER_BUFFER_OK");
-	    break;
-	  case JITTER_BUFFER_MISSING:
-	    _debug("JITTER_BUFFER_MISSING");
-	    break;
-	  case JITTER_BUFFER_INTERNAL_ERROR:
-	    _debug("JITTER_BUFFER_INTERNAL_ERROR");
-	    break;
-	  case JITTER_BUFFER_BAD_ARGUMENT:
-	    _debug("JITTER_BUFFER_BAD_ARGUMENT");
-	    break;
-	  default:
-	    _debug("Unknown error");
-	    break;
 	}
-	*/
+	else {
+	    _debug("No RTP packet available !!!!!!!!!!!!!!!!!!!!!!!\n");
+	}
+
+	result = jb_get(_jbuffer, &frame, _currentTime+=20, _packetLength);
 
         // DTMF over RTP, size must be over 4 in order to process it as voice data
         if(size > 4) {
-	    // processDataDecode(spkrData, size);
-	    if(result == JITTER_BUFFER_OK)
-	        processDataDecode ((unsigned char *)jPacketOut.data, jPacketOut.len);
-        }
-        else {
-	    // _debug("RTP: Received an RTP event with payload: %d", adu->getType());
-	    // ost::RTPPacket::RFC2833Payload *dtmf = (ost::RTPPacket::RFC2833Payload *)adu->getData();
-	    // _debug("RTP: Data received %d", dtmf->event);
+	    // processDataDecode(spkrDataIn, size);
+	    if(result == JB_OK) {
+	      processDataDecode((unsigned char *)(frame.data), 160);
+	    }
         }
 
-	delete jPacketOut.data;
 	delete adu;
     }
     
@@ -742,8 +761,6 @@ namespace sfl {
 	// Timestamp must be initialized randomly
 	_timestamp = static_cast<D*>(this)->getCurrentTimestamp();
 
-	_ts = 0;
-
         int sessionWaiting;
         int threadSleep = 0;
 
diff --git a/sflphone-common/src/audio/echocancel.cpp b/sflphone-common/src/audio/echocancel.cpp
index 16eb50f480a794637558c5c5a07c534ae21a2efd..aab1e8f9989fc18c7c79315ef6dd64c76de12018 100644
--- a/sflphone-common/src/audio/echocancel.cpp
+++ b/sflphone-common/src/audio/echocancel.cpp
@@ -93,7 +93,7 @@ EchoCancel::EchoCancel(int smplRate, int frameLength) : _samplingRate(smplRate),
   _noiseState = speex_preprocess_state_init(_smplPerFrame, _samplingRate);
   int i=1;
   speex_preprocess_ctl(_noiseState, SPEEX_PREPROCESS_SET_DENOISE, &i);
-  i=-10;
+  i=-20;
   speex_preprocess_ctl(_noiseState, SPEEX_PREPROCESS_SET_NOISE_SUPPRESS, &i);
   i=0;
   speex_preprocess_ctl(_noiseState, SPEEX_PREPROCESS_SET_AGC, &i);
diff --git a/sflphone-common/src/audio/jitterbuf.cpp b/sflphone-common/src/audio/jitterbuf.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..c72a6387f9769ae91feefd23e332030a74a0d328
--- /dev/null
+++ b/sflphone-common/src/audio/jitterbuf.cpp
@@ -0,0 +1,881 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2004-2005, Horizon Wimba, Inc.
+ *
+ * Contributors:
+ * Steve Kann <stevek@stevek.com>
+ *
+ * A license has been granted to Digium (via disclaimer) for the use of
+ * this code.
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief jitterbuf: an application-independent jitterbuffer
+ * \author Steve Kann <stevek@stevek.com>
+ *
+ */
+
+#include "jitterbuf.h"
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "global.h"
+
+/*! define these here, just for ancient compiler systems */
+#define JB_LONGMAX 2147483647L
+#define JB_LONGMIN (-JB_LONGMAX - 1L)
+
+#define jb_warn(...) (warnf ? warnf(__VA_ARGS__) : (void)0)
+#define jb_err(...) (errf ? errf(__VA_ARGS__) : (void)0)
+#define jb_dbg(...) (dbgf ? dbgf(__VA_ARGS__) : (void)0)
+
+#ifdef DEEP_DEBUG
+#define jb_dbg2(...) (dbgf ? dbgf(__VA_ARGS__) : (void)0)
+#else
+#define jb_dbg2(...) ((void)0)
+#endif
+
+static jb_output_function_t warnf, errf, dbgf;
+
+void jb_setoutput(jb_output_function_t err, jb_output_function_t warn, jb_output_function_t dbg) 
+{
+	errf = err;
+	warnf = warn;
+	dbgf = dbg;
+}
+
+static void increment_losspct(jitterbuf *jb) 
+{
+	jb->info.losspct = (100000 + 499 * jb->info.losspct)/500;    
+}
+
+static void decrement_losspct(jitterbuf *jb) 
+{
+	jb->info.losspct = (499 * jb->info.losspct)/500;    
+}
+
+void jb_reset(jitterbuf *jb) 
+{
+	/* only save settings */
+	jb_conf s = jb->info.conf;
+	memset(jb, 0, sizeof(*jb));
+	jb->info.conf = s;
+
+	/* initialize length, using the default value */
+	jb->info.current = jb->info.target = jb->info.conf.target_extra = JB_TARGET_EXTRA;
+	jb->info.silence_begin_ts = -1; 
+}
+
+jitterbuf * jb_new() 
+{
+	jitterbuf *jb;
+
+	if (!(jb = (jitterbuf *)malloc(sizeof(*jb)))) 
+		return NULL;
+
+	jb_reset(jb);
+
+	jb_dbg2("jb_new() = %x\n", jb);
+	return jb;
+}
+
+void jb_destroy(jitterbuf *jb) 
+{
+	jb_frame *frame; 
+	jb_dbg2("jb_destroy(%x)\n", jb);
+
+	/* free all the frames on the "free list" */
+	frame = jb->free;
+	while (frame != NULL) {
+		jb_frame *next = frame->next;
+		free(frame);
+		frame = next;
+	}
+
+	/* free ourselves! */ 
+	free(jb);
+}
+
+
+
+#if 0
+static int longcmp(const void *a, const void *b) 
+{
+	return *(long *)a - *(long *)b;
+}
+#endif
+
+/*!	\brief simple history manipulation 
+ 	\note maybe later we can make the history buckets variable size, or something? */
+/* drop parameter determines whether we will drop outliers to minimize
+ * delay */
+static int history_put(jitterbuf *jb, long ts, long now, long ms) 
+{
+	long delay = now - (ts - jb->info.resync_offset);
+	long threshold = 2 * jb->info.jitter + jb->info.conf.resync_threshold;
+	long kicked;
+
+	/* don't add special/negative times to history */
+	if (ts <= 0) 
+		return 0;
+
+	/* check for drastic change in delay */
+	if (jb->info.conf.resync_threshold != -1) {
+		if (abs(delay - jb->info.last_delay) > threshold) {
+			jb->info.cnt_delay_discont++;
+			if (jb->info.cnt_delay_discont > 3) {
+				/* resync the jitterbuffer */
+				jb->info.cnt_delay_discont = 0;
+				jb->hist_ptr = 0;
+				jb->hist_maxbuf_valid = 0;
+
+				jb_warn("Resyncing the jb. last_delay %ld, this delay %ld, threshold %ld, new offset %ld\n", jb->info.last_delay, delay, threshold, ts - now);
+				jb->info.resync_offset = ts - now;
+				jb->info.last_delay = delay = 0; /* after resync, frame is right on time */
+			} else {
+				return -1;
+			}
+		} else {
+			jb->info.last_delay = delay;
+			jb->info.cnt_delay_discont = 0;
+		}
+	}
+
+	kicked = jb->history[jb->hist_ptr % JB_HISTORY_SZ];
+
+	jb->history[(jb->hist_ptr++) % JB_HISTORY_SZ] = delay;
+
+	/* optimization; the max/min buffers don't need to be recalculated, if this packet's
+	 * entry doesn't change them.  This happens if this packet is not involved, _and_ any packet
+	 * that got kicked out of the history is also not involved 
+	 * We do a number of comparisons, but it's probably still worthwhile, because it will usually
+	 * succeed, and should be a lot faster than going through all 500 packets in history */
+	if (!jb->hist_maxbuf_valid)
+		return 0;
+
+	/* don't do this until we've filled history 
+	 * (reduces some edge cases below) */
+	if (jb->hist_ptr < JB_HISTORY_SZ)
+		goto invalidate;
+
+	/* if the new delay would go into min */
+	if (delay < jb->hist_minbuf[JB_HISTORY_MAXBUF_SZ-1])
+		goto invalidate;
+
+	/* or max.. */
+	if (delay > jb->hist_maxbuf[JB_HISTORY_MAXBUF_SZ-1])
+		goto invalidate;
+
+	/* or the kicked delay would be in min */
+	if (kicked <= jb->hist_minbuf[JB_HISTORY_MAXBUF_SZ-1]) 
+		goto invalidate;
+
+	if (kicked >= jb->hist_maxbuf[JB_HISTORY_MAXBUF_SZ-1]) 
+		goto invalidate;
+
+	/* if we got here, we don't need to invalidate, 'cause this delay didn't 
+	 * affect things */
+	return 0;
+	/* end optimization */
+
+
+invalidate:
+	jb->hist_maxbuf_valid = 0;
+	return 0;
+}
+
+static void history_calc_maxbuf(jitterbuf *jb) 
+{
+	int i,j;
+
+	if (jb->hist_ptr == 0) 
+		return;
+
+
+	/* initialize maxbuf/minbuf to the latest value */
+	for (i=0;i<JB_HISTORY_MAXBUF_SZ;i++) {
+/*
+ * jb->hist_maxbuf[i] = jb->history[(jb->hist_ptr-1) % JB_HISTORY_SZ];
+ * jb->hist_minbuf[i] = jb->history[(jb->hist_ptr-1) % JB_HISTORY_SZ];
+ */
+		jb->hist_maxbuf[i] = JB_LONGMIN;
+		jb->hist_minbuf[i] = JB_LONGMAX;
+	}
+
+	/* use insertion sort to populate maxbuf */
+	/* we want it to be the top "n" values, in order */
+
+	/* start at the beginning, or JB_HISTORY_SZ frames ago */
+	i = (jb->hist_ptr > JB_HISTORY_SZ) ? (jb->hist_ptr - JB_HISTORY_SZ) : 0; 
+
+	for (;i<jb->hist_ptr;i++) {
+		long toins = jb->history[i % JB_HISTORY_SZ];
+
+		/* if the maxbuf should get this */
+		if (toins > jb->hist_maxbuf[JB_HISTORY_MAXBUF_SZ-1])  {
+
+			/* insertion-sort it into the maxbuf */
+			for (j=0;j<JB_HISTORY_MAXBUF_SZ;j++) {
+				/* found where it fits */
+				if (toins > jb->hist_maxbuf[j]) {
+					/* move over */
+					memmove(jb->hist_maxbuf + j + 1, jb->hist_maxbuf + j, (JB_HISTORY_MAXBUF_SZ - (j + 1)) * sizeof(jb->hist_maxbuf[0]));
+					/* insert */
+					jb->hist_maxbuf[j] = toins;
+
+					break;
+				}
+			}
+		}
+
+		/* if the minbuf should get this */
+		if (toins < jb->hist_minbuf[JB_HISTORY_MAXBUF_SZ-1])  {
+
+			/* insertion-sort it into the maxbuf */
+			for (j=0;j<JB_HISTORY_MAXBUF_SZ;j++) {
+				/* found where it fits */
+				if (toins < jb->hist_minbuf[j]) {
+					/* move over */
+					memmove(jb->hist_minbuf + j + 1, jb->hist_minbuf + j, (JB_HISTORY_MAXBUF_SZ - (j + 1)) * sizeof(jb->hist_minbuf[0]));
+					/* insert */
+					jb->hist_minbuf[j] = toins;
+
+					break;
+				}
+			}
+		}
+
+		if (0) { 
+			int k;
+			_debug("toins = %ld\n", toins);
+			_debug("maxbuf =");
+			for (k=0;k<JB_HISTORY_MAXBUF_SZ;k++) 
+				_debug("%ld ", jb->hist_maxbuf[k]);
+			_debug("\nminbuf =");
+			for (k=0;k<JB_HISTORY_MAXBUF_SZ;k++) 
+				_debug("%ld ", jb->hist_minbuf[k]);
+			_debug("\n");
+		}
+	}
+
+	jb->hist_maxbuf_valid = 1;
+}
+
+static void history_get(jitterbuf *jb) 
+{
+	long max, min, jitter;
+	int idx;
+	int count;
+
+	if (!jb->hist_maxbuf_valid) 
+		history_calc_maxbuf(jb);
+
+	/* count is how many items in history we're examining */
+	count = (jb->hist_ptr < JB_HISTORY_SZ) ? jb->hist_ptr : JB_HISTORY_SZ;
+
+	/* idx is the "n"ths highest/lowest that we'll look for */
+	idx = count * JB_HISTORY_DROPPCT / 100;
+
+	/* sanity checks for idx */
+	if (idx > (JB_HISTORY_MAXBUF_SZ - 1)) 
+		idx = JB_HISTORY_MAXBUF_SZ - 1;
+
+	if (idx < 0) {
+		jb->info.min = 0;
+		jb->info.jitter = 0;
+		return;
+	}
+
+	max = jb->hist_maxbuf[idx];
+	min = jb->hist_minbuf[idx];
+
+	jitter = max - min;
+
+	/* these debug stmts compare the difference between looking at the absolute jitter, and the
+	 * values we get by throwing away the outliers */
+	// printf("[%ld] min=%ld, max=%ld, jitter=%ld\n", index, min, max, jitter);
+	// printf("[%ld] min=%ld, max=%ld, jitter=%ld\n", 0, jb->hist_minbuf[0], jb->hist_maxbuf[0], jb->hist_maxbuf[0]-jb->hist_minbuf[0]);
+
+	jb->info.min = min;
+	jb->info.jitter = jitter;
+}
+
+/* returns 1 if frame was inserted into head of queue, 0 otherwise */
+static int queue_put(jitterbuf *jb, void *data, const enum jb_frame_type type, long ms, long ts) 
+{
+	jb_frame *frame;
+	jb_frame *p;
+	int head = 0;
+	long resync_ts = ts - jb->info.resync_offset;
+
+	if ((frame = jb->free)) {
+		jb->free = frame->next;
+	} else if (!(frame = (jb_frame *)malloc(sizeof(*frame)))) {
+		jb_err("cannot allocate frame\n");
+		return 0;
+	}
+
+	jb->info.frames_cur++;
+
+	frame->data = data;
+	frame->ts = resync_ts;
+	frame->ms = ms;
+	frame->type = type;
+
+	/* 
+	 * frames are a circular list, jb-frames points to to the lowest ts, 
+	 * jb->frames->prev points to the highest ts
+	 */
+
+	if (!jb->frames) {  /* queue is empty */
+		jb->frames = frame;
+		frame->next = frame;
+		frame->prev = frame;
+		head = 1;
+	} else if (resync_ts < jb->frames->ts) {
+		frame->next = jb->frames;
+		frame->prev = jb->frames->prev;
+
+		frame->next->prev = frame;
+		frame->prev->next = frame;
+
+		/* frame is out of order */
+		jb->info.frames_ooo++;
+
+		jb->frames = frame;
+		head = 1;
+	} else { 
+		p = jb->frames;
+
+		/* frame is out of order */
+		if (resync_ts < p->prev->ts) jb->info.frames_ooo++;
+
+		while (resync_ts < p->prev->ts && p->prev != jb->frames) 
+			p = p->prev;
+
+		frame->next = p;
+		frame->prev = p->prev;
+
+		frame->next->prev = frame;
+		frame->prev->next = frame;
+	}
+	return head;
+}
+
+static long queue_next(jitterbuf *jb) 
+{
+	if (jb->frames) 
+		return jb->frames->ts;
+	else 
+		return -1;
+}
+
+static long queue_last(jitterbuf *jb) 
+{
+	if (jb->frames) 
+		return jb->frames->prev->ts;
+	else 
+		return -1;
+}
+
+static jb_frame *_queue_get(jitterbuf *jb, long ts, int all) 
+{
+	jb_frame *frame;
+	frame = jb->frames;
+
+	if (!frame)
+		return NULL;
+
+	_debug("queue_get: ASK %ld FIRST %ld\n", ts, frame->ts);
+
+	if (all || ts >= frame->ts) {
+		/* remove this frame */
+		frame->prev->next = frame->next;
+		frame->next->prev = frame->prev;
+
+		if (frame->next == frame)
+			jb->frames = NULL;
+		else
+			jb->frames = frame->next;
+
+
+		/* insert onto "free" single-linked list */
+		frame->next = jb->free;
+		jb->free = frame;
+
+		jb->info.frames_cur--;
+
+		/* we return the frame pointer, even though it's on free list, 
+		 * but caller must copy data */
+		return frame;
+	} 
+
+	return NULL;
+}
+
+static jb_frame *queue_get(jitterbuf *jb, long ts) 
+{
+	return _queue_get(jb,ts,0);
+}
+
+static jb_frame *queue_getall(jitterbuf *jb) 
+{
+	return _queue_get(jb,0,1);
+}
+
+/* some diagnostics */
+void jb_dbginfo(jitterbuf *jb) 
+{
+
+	_debug("\njb info: fin=%ld fout=%ld flate=%ld flost=%ld fdrop=%ld fcur=%ld\n",
+		jb->info.frames_in, jb->info.frames_out, jb->info.frames_late, jb->info.frames_lost, jb->info.frames_dropped, jb->info.frames_cur);
+	
+	_debug("jitter=%ld current=%ld target=%ld min=%ld sil=%ld len=%ld len/fcur=%ld\n",
+		jb->info.jitter, jb->info.current, jb->info.target, jb->info.min, jb->info.silence_begin_ts, jb->info.current - jb->info.min, 
+		jb->info.frames_cur ? (jb->info.current - jb->info.min)/jb->info.frames_cur : -8);
+	if (jb->info.frames_in > 0) 
+		_debug("jb info: Loss PCT = %ld%%, Late PCT = %ld%%\n",
+			jb->info.frames_lost * 100/(jb->info.frames_in + jb->info.frames_lost), 
+			jb->info.frames_late * 100/jb->info.frames_in);
+        _debug("jb info: queue %ld -> %ld.  last_ts %ld (queue len: %ld) last_ms %ld\n\n",
+		queue_next(jb), 
+		queue_last(jb),
+		jb->info.next_voice_ts, 
+		queue_last(jb) - queue_next(jb),
+		jb->info.last_voice_ms);
+}
+
+
+#ifdef DEEP_DEBUG
+static void jb_chkqueue(jitterbuf *jb) 
+{
+	int i=0;
+	jb_frame *p = jb->frames;
+
+	if (!p) {
+		return;
+	}
+
+	do {
+		if (p->next == NULL)  {
+			jb_err("Queue is BROKEN at item [%d]", i);	
+		}
+		i++;
+		p=p->next;
+	} while (p->next != jb->frames);
+}
+
+static void jb_dbgqueue(jitterbuf *jb) 
+{
+	int i=0;
+	jb_frame *p = jb->frames;
+
+	jb_dbg("queue: ");
+
+	if (!p) {
+		jb_dbg("EMPTY\n");
+		return;
+	}
+
+	do {
+		jb_dbg("[%d]=%ld ", i++, p->ts);
+		p=p->next;
+	} while (p->next != jb->frames);
+
+	jb_dbg("\n");
+}
+#endif
+
+jb_return_code jb_put(jitterbuf *jb, void *data, const enum jb_frame_type type, long ms, long ts, long now) 
+{
+	long numts;
+
+	_debug("jb_put(%p,%p,%ld,%ld,%ld)\n", jb, data, ms, ts, now);
+
+	numts = 0;
+	if (jb->frames)
+		numts = jb->frames->prev->ts - jb->frames->ts;
+
+	_debug("numts %ld\n", numts);
+
+	if (numts >= jb->info.conf.max_jitterbuf) {
+		if (!jb->dropem) {
+			_debug("Attempting to exceed Jitterbuf max %ld timeslots\n",
+				jb->info.conf.max_jitterbuf);
+			jb->dropem = 1;
+		}
+		jb->info.frames_dropped++;
+		return JB_DROP;
+	} else {
+		jb->dropem = 0;
+	}
+
+	if (type == JB_TYPE_VOICE) {
+		/* presently, I'm only adding VOICE frames to history and drift calculations; mostly because with the
+		 * IAX integrations, I'm sending retransmitted control frames with their awkward timestamps through */
+		if (history_put(jb,ts,now,ms)) {
+			jb->info.frames_dropped++;
+			return JB_DROP;
+		}
+	}
+
+	jb->info.frames_in++;
+
+	/* if put into head of queue, caller needs to reschedule */
+	if (queue_put(jb,data,type,ms,ts)) {
+		return JB_SCHED;
+	}
+	return JB_OK;
+}
+
+
+static enum jb_return_code _jb_get(jitterbuf *jb, jb_frame *frameout, long now, long interpl) 
+{
+	jb_frame *frame;
+	long diff;
+	static int dbg_cnt = 0;
+
+	_debug("_jb_get\n");
+
+	/*if ((now - jb_next(jb)) > 2 * jb->info.last_voice_ms) jb_warn("SCHED: %ld", (now - jb_next(jb))); */
+	/* get jitter info */
+	history_get(jb);
+
+	if (dbg_cnt && dbg_cnt % 50 == 0) {
+		jb_dbg("\n");
+	}
+	dbg_cnt++;
+
+	/* target */
+	jb->info.target = jb->info.jitter + jb->info.min + jb->info.conf.target_extra; 
+
+	/* if a hard clamp was requested, use it */
+	if ((jb->info.conf.max_jitterbuf) && ((jb->info.target - jb->info.min) > jb->info.conf.max_jitterbuf)) {
+		_debug("clamping target from %ld to %ld\n", (jb->info.target - jb->info.min), jb->info.conf.max_jitterbuf);
+		jb->info.target = jb->info.min + jb->info.conf.max_jitterbuf;
+	}
+
+	diff = jb->info.target - jb->info.current;
+
+	_debug("diff = %ld lms=%ld last = %ld now = %ld, djust delay = %ld\n", diff,
+		jb->info.last_voice_ms, jb->info.last_adjustment, now);
+
+	/* let's work on non-silent case first */
+	if (!jb->info.silence_begin_ts) {
+
+	  /*
+	        if(diff > 0)
+		    printf("diff > 0\n");
+
+		if((jb->info.last_adjustment + JB_ADJUST_DELAY) < now)
+		    printf("(jb->info.last_adjustment + JB_ADJUST_DELAY) < now\n");
+
+		if((diff > queue_last(jb)  - queue_next(jb)))
+		    printf("diff > queue_last(jb)  - queue_next(jb)\n");
+	  */
+	  _debug("** Non-silent case update timing info **\n");
+	  _debug("diff %ld\n", diff);
+	  _debug("jb->info.last_adjustment %ld\n", jb->info.last_adjustment);
+	  _debug("JB_ADJUST_DELAY %ld\n", JB_ADJUST_DELAY);
+	  _debug("now %ld\n", now);
+
+		/* we want to grow */
+		if ((diff > 0) && 
+			/* we haven't grown in the delay length */
+			(((jb->info.last_adjustment + JB_ADJUST_DELAY) < now) || 
+			/* we need to grow more than the "length" we have left */
+			(diff > queue_last(jb)  - queue_next(jb)) ) ) {
+
+		        
+		        
+
+			/* grow by interp frame length */
+			jb->info.current += interpl;
+			jb->info.next_voice_ts += interpl;
+			jb->info.last_voice_ms = interpl;
+			jb->info.last_adjustment = now;
+			jb->info.cnt_contig_interp++;
+			if (jb->info.conf.max_contig_interp && jb->info.cnt_contig_interp >= jb->info.conf.max_contig_interp) {
+				jb->info.silence_begin_ts = jb->info.next_voice_ts - jb->info.current;
+			}
+
+			_debug("Non silent case\n");
+			return JB_INTERP;
+		}
+
+	        _debug("queue get\n");
+
+		frame = queue_get(jb, jb->info.next_voice_ts - jb->info.current);
+
+		if(!frame)
+		  _debug("frame not valid\n");
+
+		/* not a voice frame; just return it. */
+		if (frame && frame->type != JB_TYPE_VOICE) {
+			if (frame->type == JB_TYPE_SILENCE) {
+				jb->info.silence_begin_ts = frame->ts;
+				jb->info.cnt_contig_interp = 0;
+			}
+
+			*frameout = *frame;
+			jb->info.frames_out++;
+			_debug("Not a voice packet\n");
+			return JB_OK;
+		}
+
+
+		/* voice frame is later than expected */
+		if (frame && frame->ts + jb->info.current < jb->info.next_voice_ts) {
+			if (frame->ts + jb->info.current > jb->info.next_voice_ts - jb->info.last_voice_ms) {
+				/* either we interpolated past this frame in the last jb_get */
+				/* or the frame is still in order, but came a little too quick */ 
+				*frameout = *frame;
+				/* reset expectation for next frame */
+				jb->info.next_voice_ts = frame->ts + jb->info.current + frame->ms;
+				jb->info.frames_out++;
+				decrement_losspct(jb);
+				jb->info.cnt_contig_interp = 0;
+				_debug("Either we interpolated past this frame in the last jb_get" \
+				       "or the frame is still in order, but came a little too quick\n");
+				return JB_OK;
+			} else {
+				/* voice frame is late */
+				*frameout = *frame;
+				jb->info.frames_out++;
+				decrement_losspct(jb);
+				jb->info.frames_late++;
+				jb->info.frames_lost--;
+				_debug("Voice frame is late\n");
+				_debug("late: wanted=%ld, this=%ld, next=%ld\n", jb->info.next_voice_ts - jb->info.current, frame->ts, queue_next(jb));
+				return JB_DROP;
+			}
+		}
+
+		/* keep track of frame sizes, to allow for variable sized-frames */
+		if (frame && frame->ms > 0) {
+			jb->info.last_voice_ms = frame->ms;
+		}
+
+		/* we want to shrink; shrink at 1 frame / 500ms */
+		/* unless we don't have a frame, then shrink 1 frame */
+		/* every 80ms (though perhaps we can shrink even faster */
+		/* in this case) */
+		if (diff < -jb->info.conf.target_extra && 
+			((!frame && jb->info.last_adjustment + 80 < now) || 
+			(jb->info.last_adjustment + 500 < now))) {
+
+			jb->info.last_adjustment = now;
+			jb->info.cnt_contig_interp = 0;
+
+			if (frame) {
+				*frameout = *frame;
+				/* shrink by frame size we're throwing out */
+				jb->info.current -= frame->ms;
+				jb->info.frames_out++;
+				decrement_losspct(jb);
+				jb->info.frames_dropped++;
+				_debug("Shrink by frame size we're throwing out");
+				return JB_DROP;
+			} else {
+				/* shrink by last_voice_ms */
+				jb->info.current -= jb->info.last_voice_ms;
+				jb->info.frames_lost++;
+				increment_losspct(jb);
+				jb_dbg("S");
+				_debug("No frames, shrink by last_voice_ms");
+				return JB_NOFRAME;
+			}
+		}
+
+		/* lost frame */
+		if (!frame) {
+			/* this is a bit of a hack for now, but if we're close to
+			 * target, and we find a missing frame, it makes sense to
+			 * grow, because the frame might just be a bit late;
+			 * otherwise, we presently get into a pattern where we return
+			 * INTERP for the lost frame, then it shows up next, and we
+			 * throw it away because it's late */
+	  		/* I've recently only been able to replicate this using
+			 * iaxclient talking to app_echo on asterisk.  In this case,
+			 * my outgoing packets go through asterisk's (old)
+			 * jitterbuffer, and then might get an unusual increasing delay 
+			 * there if it decides to grow?? */
+			/* Update: that might have been a different bug, that has been fixed..
+			 * But, this still seemed like a good idea, except that it ended up making a single actual
+			 * lost frame get interpolated two or more times, when there was "room" to grow, so it might
+			 * be a bit of a bad idea overall */
+			/*if (diff > -1 * jb->info.last_voice_ms) { 
+				jb->info.current += jb->info.last_voice_ms;
+				jb->info.last_adjustment = now;
+				jb_warn("g");
+				return JB_INTERP;
+			} */
+			jb->info.frames_lost++;
+			increment_losspct(jb);
+			jb->info.next_voice_ts += interpl;
+			jb->info.last_voice_ms = interpl;
+			jb->info.cnt_contig_interp++;
+			if (jb->info.conf.max_contig_interp && jb->info.cnt_contig_interp >= jb->info.conf.max_contig_interp) {
+				jb->info.silence_begin_ts = jb->info.next_voice_ts - jb->info.current;
+			}
+			
+			return JB_INTERP;
+		}
+
+		/* normal case; return the frame, increment stuff */
+		*frameout = *frame;
+		jb->info.next_voice_ts += frame->ms;
+		jb->info.frames_out++;
+		jb->info.cnt_contig_interp = 0;
+		decrement_losspct(jb);
+		jb_dbg("v");
+		return JB_OK;
+	} else {     
+
+	        _debug("Silence???\n");
+		/* TODO: after we get the non-silent case down, we'll make the
+		 * silent case -- basically, we'll just grow and shrink faster
+		 * here, plus handle next_voice_ts a bit differently */
+
+		/* to disable silent special case altogether, just uncomment this: */
+		/* jb->info.silence_begin_ts = 0; */
+
+ 		/* shrink interpl len every 10ms during silence */
+ 		if (diff < -jb->info.conf.target_extra &&
+ 			jb->info.last_adjustment + 10 <= now) {
+ 			jb->info.current -= interpl;
+ 			jb->info.last_adjustment = now;
+ 		}
+
+		frame = queue_get(jb, now - jb->info.current);
+		if (!frame) {
+			return JB_NOFRAME;
+		} else if (frame->type != JB_TYPE_VOICE) {
+			/* normal case; in silent mode, got a non-voice frame */
+			*frameout = *frame;
+			jb->info.frames_out++;
+			return JB_OK;
+		}
+		if (frame->ts < jb->info.silence_begin_ts) {
+			/* voice frame is late */
+			*frameout = *frame;
+			jb->info.frames_out++;
+			decrement_losspct(jb);
+			jb->info.frames_late++;
+			jb->info.frames_lost--;
+			jb_dbg("l");
+			/*jb_warn("\nlate: wanted=%ld, this=%ld, next=%ld\n", jb->info.next_voice_ts - jb->info.current, frame->ts, queue_next(jb));
+			jb_warninfo(jb); */
+			return JB_DROP;
+		} else {
+			/* voice frame */
+			/* try setting current to target right away here */
+			jb->info.current = jb->info.target;
+			jb->info.silence_begin_ts = 0;
+			jb->info.next_voice_ts = frame->ts + jb->info.current + frame->ms;
+			jb->info.last_voice_ms = frame->ms;
+			jb->info.frames_out++;
+			decrement_losspct(jb);
+			*frameout = *frame;
+			jb_dbg("V");
+			return JB_OK;
+		}
+	}
+}
+
+long jb_next(jitterbuf *jb) 
+{
+	if (jb->info.silence_begin_ts) {
+		if (jb->frames) {
+			long next = queue_next(jb);
+			history_get(jb);
+			/* shrink during silence */
+			if (jb->info.target - jb->info.current < -jb->info.conf.target_extra)
+				return jb->info.last_adjustment + 10;
+			return next + jb->info.target;
+		}
+		else 
+			return JB_LONGMAX;
+	} else {
+		return jb->info.next_voice_ts;
+	}
+}
+
+enum jb_return_code jb_get(jitterbuf *jb, jb_frame *frameout, long now, long interpl) 
+{
+        _debug("\n***** JB_GET *****\n\n");
+
+	enum jb_return_code ret = _jb_get(jb, frameout, now, interpl);
+#if 0
+	static int lastts=0;
+	int thists = ((ret == JB_OK) || (ret == JB_DROP)) ? frameout->ts : 0;
+	jb_warn("jb_get(%x,%x,%ld) = %d (%d)\n", jb, frameout, now, ret, thists);
+	if (thists && thists < lastts) jb_warn("XXXX timestamp roll-back!!!\n");
+	lastts = thists;
+#endif
+	if (ret == JB_INTERP) 
+		frameout->ms = jb->info.last_voice_ms;
+	
+	return ret;
+}
+
+enum jb_return_code jb_getall(jitterbuf *jb, jb_frame *frameout) 
+{
+	jb_frame *frame;
+	frame = queue_getall(jb);
+
+	if (!frame) {
+		return JB_NOFRAME;
+	}
+
+	*frameout = *frame;
+	return JB_OK;
+}
+
+
+enum jb_return_code jb_getinfo(jitterbuf *jb, jb_info *stats) 
+{
+
+	history_get(jb);
+
+	*stats = jb->info;
+
+	return JB_OK;
+}
+
+enum jb_return_code jb_setconf(jitterbuf *jb, jb_conf *conf) 
+{
+	/* take selected settings from the struct */
+
+	jb->info.conf.max_jitterbuf = conf->max_jitterbuf;
+ 	jb->info.conf.resync_threshold = conf->resync_threshold;
+	jb->info.conf.max_contig_interp = conf->max_contig_interp;
+
+	/* -1 indicates use of the default JB_TARGET_EXTRA value */
+	jb->info.conf.target_extra = ( conf->target_extra == -1 )
+		? JB_TARGET_EXTRA
+		: conf->target_extra
+		;
+		
+	/* update these to match new target_extra setting */
+	jb->info.current = jb->info.conf.target_extra;
+	jb->info.target = jb->info.conf.target_extra;
+
+	return JB_OK;
+}
+
+
diff --git a/sflphone-common/src/audio/jitterbuf.h b/sflphone-common/src/audio/jitterbuf.h
new file mode 100755
index 0000000000000000000000000000000000000000..8de8bf0885d87f476550bc27c5201065d677b51d
--- /dev/null
+++ b/sflphone-common/src/audio/jitterbuf.h
@@ -0,0 +1,177 @@
+/*
+ * jitterbuf: an application-independent jitterbuffer
+ *
+ * Copyrights:
+ * Copyright (C) 2004-2005, Horizon Wimba, Inc.
+ *
+ * Contributors:
+ * Steve Kann <stevek@stevek.com>
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU Lesser (Library) General Public License
+ *
+ * Copyright on this file is disclaimed to Digium for inclusion in Asterisk
+ */
+
+/*! \file
+ * \brief 
+ * jitterbuf: an application-independent jitterbuffer
+ * \ref jitterbuf.c
+ */
+
+
+#ifndef _JITTERBUF_H_
+#define _JITTERBUF_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*! \name configuration constants */
+/*@{ */
+	/*! Number of historical timestamps to use in calculating jitter and drift */
+#define JB_HISTORY_SZ		500	
+	/*! what percentage of timestamps should we drop from the history when we examine it;
+	 * this might eventually be something made configurable */
+#define JB_HISTORY_DROPPCT	3
+	/*! the maximum droppct we can handle (say it was configurable). */
+#define JB_HISTORY_DROPPCT_MAX	4
+	/*! the size of the buffer we use to keep the top and botton timestamps for dropping */
+#define JB_HISTORY_MAXBUF_SZ	JB_HISTORY_SZ * JB_HISTORY_DROPPCT_MAX / 100 
+	/*! amount of additional jitterbuffer adjustment  */
+#define JB_TARGET_EXTRA 40
+	/*! ms between growing and shrinking; may not be honored if jitterbuffer runs out of space */
+#define JB_ADJUST_DELAY 40
+/*@} */
+
+enum jb_return_code {
+	/* return codes */
+	JB_OK,            /* 0 */
+	JB_EMPTY,         /* 1 */
+	JB_NOFRAME,       /* 2 */
+	JB_INTERP,        /* 3 */
+	JB_DROP,          /* 4 */
+	JB_SCHED          /* 5 */
+};
+
+enum jb_frame_type {
+	/* frame types */
+	JB_TYPE_CONTROL,  /*!< 0            */
+	JB_TYPE_VOICE,    /*!< 1            */
+	JB_TYPE_VIDEO,    /*!< 2 - reserved */
+	JB_TYPE_SILENCE   /*!< 3            */
+};
+
+typedef struct jb_conf {
+	/* settings */
+	long max_jitterbuf;	/*!< defines a hard clamp to use in setting the jitter buffer delay */
+ 	long resync_threshold;  /*!< the jb will resync when delay increases to (2 * jitter) + this param */
+	long max_contig_interp; /*!< the max interp frames to return in a row */
+	long target_extra ;      /*!< amount of additional jitterbuffer adjustment, overrides JB_TARGET_EXTRA */
+} jb_conf;
+
+typedef struct jb_info {
+	jb_conf conf;
+
+	/* statistics */
+	long frames_in;  	/*!< number of frames input to the jitterbuffer.*/
+	long frames_out;  	/*!< number of frames output from the jitterbuffer.*/
+	long frames_late; 	/*!< number of frames which were too late, and dropped.*/
+	long frames_lost; 	/*!< number of missing frames.*/
+	long frames_dropped; 	/*!< number of frames dropped (shrinkage) */
+	long frames_ooo; 	/*!< number of frames received out-of-order */
+	long frames_cur; 	/*!< number of frames presently in jb, awaiting delivery.*/
+	long jitter; 		/*!< jitter measured within current history interval*/
+	long min;		/*!< minimum lateness within current history interval */
+	long current; 		/*!< the present jitterbuffer adjustment */
+	long target; 		/*!< the target jitterbuffer adjustment */
+	long losspct; 		/*!< recent lost frame percentage (* 1000) */
+	long next_voice_ts;	/*!< the ts of the next frame to be read from the jb - in receiver's time */
+	long last_voice_ms;	/*!< the duration of the last voice frame */
+	long silence_begin_ts;	/*!< the time of the last CNG frame, when in silence */
+	long last_adjustment;   /*!< the time of the last adjustment */
+ 	long last_delay;        /*!< the last now added to history */
+ 	long cnt_delay_discont;	/*!< the count of discontinuous delays */
+ 	long resync_offset;     /*!< the amount to offset ts to support resyncs */
+	long cnt_contig_interp; /*!< the number of contiguous interp frames returned */
+} jb_info;
+
+typedef struct jb_frame {
+	void *data;               /* the frame data */
+	long ts;                  /* the relative delivery time expected */
+	long ms;                  /* the time covered by this frame, in sec/8000 */
+	enum jb_frame_type type;  /* the type of frame */
+	struct jb_frame *next, *prev;
+} jb_frame;
+
+typedef struct jitterbuf {
+	jb_info info;
+
+	/* history */
+	long history[JB_HISTORY_SZ];   		/*!< history */
+	int  hist_ptr;				/*!< points to index in history for next entry */
+	long hist_maxbuf[JB_HISTORY_MAXBUF_SZ];	/*!< a sorted buffer of the max delays (highest first) */
+	long hist_minbuf[JB_HISTORY_MAXBUF_SZ];	/*!< a sorted buffer of the min delays (lowest first) */
+	int  hist_maxbuf_valid;			/*!< are the "maxbuf"/minbuf valid? */
+	unsigned int dropem:1;                  /*!< flag to indicate dropping frames (overload) */
+
+	jb_frame *frames; 		/*!< queued frames */
+	jb_frame *free; 		/*!< free frames (avoid malloc?) */
+} jitterbuf;
+
+
+/*! \brief new jitterbuf */
+jitterbuf *		jb_new(void);
+
+/*! \brief destroy jitterbuf */
+void			jb_destroy(jitterbuf *jb);
+
+/*! \brief reset jitterbuf
+ * \note The jitterbuffer should be empty before you call this, otherwise
+ * you will leak queued frames, and some internal structures */
+void			jb_reset(jitterbuf *jb);
+
+/*!\brief  queue a frame 
+ * 
+ * data=frame data, timings (in ms): ms=length of frame (for voice), ts=ts (sender's time) 
+ * now=now (in receiver's time) return value is one of 
+ * JB_OK: Frame added. Last call to jb_next() still valid
+ * JB_DROP: Drop this frame immediately
+ * JB_SCHED: Frame added. Call jb_next() to get a new time for the next frame
+ */
+enum jb_return_code jb_put(jitterbuf *jb, void *data, const enum jb_frame_type type, long ms, long ts, long now);
+
+/*! \brief get a frame for time now (receiver's time)  return value is one of
+ * JB_OK:  You've got frame!
+ * JB_DROP: Here's an audio frame you should just drop.  Ask me again for this time..
+ * JB_NOFRAME: There's no frame scheduled for this time.
+ * JB_INTERP: Please interpolate an interpl-length frame for this time (either we need to grow, or there was a lost frame) 
+ * JB_EMPTY: The jb is empty.
+ */
+enum jb_return_code jb_get(jitterbuf *jb, jb_frame *frame, long now, long interpl);
+
+/*! \brief unconditionally get frames from jitterbuf until empty */
+enum jb_return_code jb_getall(jitterbuf *jb, jb_frame *frameout);
+
+/*! \brief when is the next frame due out, in receiver's time (0=EMPTY) 
+ * This value may change as frames are added (esp non-audio frames) */
+long	jb_next(jitterbuf *jb);
+
+/*! \brief get jitterbuf info: only "statistics" may be valid */
+enum jb_return_code jb_getinfo(jitterbuf *jb, jb_info *stats);
+
+/* some diagnostics */
+void jb_dbginfo(jitterbuf *jb);
+
+/*! \brief set jitterbuf conf */
+enum jb_return_code jb_setconf(jitterbuf *jb, jb_conf *conf);
+
+typedef void __attribute__((format(printf, 1, 2))) (*jb_output_function_t)(const char *fmt, ...);
+void jb_setoutput(jb_output_function_t err, jb_output_function_t warn, jb_output_function_t dbg);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/sflphone-common/src/audio/mainbuffer.cpp b/sflphone-common/src/audio/mainbuffer.cpp
index 4782b6ddf71e79757b3e03890938532909eb7d05..91e0d238d850ce61b14d3fe563156c084a498263 100644
--- a/sflphone-common/src/audio/mainbuffer.cpp
+++ b/sflphone-common/src/audio/mainbuffer.cpp
@@ -203,6 +203,22 @@ void MainBuffer::bindCallID (CallID call_id1, CallID call_id2)
 
 }
 
+void MainBuffer::bindHalfDuplexOut(CallID process_id, CallID call_id)
+{
+
+  // This method is used only for active calls, if this call does not exist, do nothing
+  if(!getRingBuffer(call_id))
+    return;
+  
+  if(!getCallIDSet(process_id))
+    createCallIDSet(process_id);
+
+  getRingBuffer(call_id)->createReadPointer(process_id);
+
+  addCallIDtoSet(process_id, call_id);
+
+}
+
 
 void MainBuffer::unBindCallID (CallID call_id1, CallID call_id2)
 {
@@ -216,7 +232,7 @@ void MainBuffer::unBindCallID (CallID call_id1, CallID call_id2)
 
     ringbuffer = getRingBuffer (call_id2);
 
-    if (ringbuffer != NULL) {
+    if (ringbuffer) {
 
         ringbuffer->removeReadPointer (call_id1);
 
@@ -229,18 +245,36 @@ void MainBuffer::unBindCallID (CallID call_id1, CallID call_id2)
 
     ringbuffer = getRingBuffer (call_id1);
 
-    if (ringbuffer != NULL) {
-        ringbuffer->removeReadPointer (call_id2);
-
-        if (ringbuffer->getNbReadPointer() == 0) {
-            removeCallIDSet (call_id1);
-            removeRingBuffer (call_id1);
-        }
+    if (ringbuffer) {
+      ringbuffer->removeReadPointer (call_id2);
+      
+      if (ringbuffer->getNbReadPointer() == 0) {
+	removeCallIDSet (call_id1);
+	removeRingBuffer (call_id1);
+      }
     }
+}
 
+void MainBuffer::unBindHalfDuplexOut(CallID call_id, CallID process_id)
+{
+
+  removeCallIDfromSet(process_id, call_id);
+
+  RingBuffer* ringbuffer;
+
+  ringbuffer = getRingBuffer(process_id);
+
+  if(ringbuffer) {
+    ringbuffer->removeReadPointer(call_id);
 
+    if(ringbuffer->getNbReadPointer() == 0) {
+      removeCallIDSet(process_id);
+      removeRingBuffer(process_id);
+    }
+  }
 }
 
+
 void MainBuffer::unBindAll (CallID call_id)
 {
 
@@ -268,10 +302,32 @@ void MainBuffer::unBindAll (CallID call_id)
 }
 
 
-int MainBuffer::putData (void *buffer, int toCopy, unsigned short volume, CallID call_id)
+void MainBuffer::unBindAllHalfDuplexOut(CallID process_id)
 {
 
-    // ost::MutexLock guard (_mutex);
+  CallIDSet* callid_set = getCallIDSet(process_id);
+
+  if(!callid_set)
+    return;
+
+  if(callid_set->empty())
+    return;
+
+  CallIDSet temp_set = *callid_set;
+
+  CallIDSet::iterator iter_set = temp_set.begin();
+
+  while(iter_set != temp_set.end()) {
+    CallID call_id_in_set = *iter_set;
+    unBindCallID(process_id, call_id_in_set);
+
+    iter_set++;
+  }
+}
+
+
+int MainBuffer::putData (void *buffer, int toCopy, unsigned short volume, CallID call_id)
+{
 
     RingBuffer* ring_buffer = getRingBuffer (call_id);
 
@@ -281,7 +337,6 @@ int MainBuffer::putData (void *buffer, int toCopy, unsigned short volume, CallID
 
     int a;
 
-    // ost::MutexLock guard (_mutex);
     a = ring_buffer->AvailForPut();
 
     if (a >= toCopy) {
@@ -298,8 +353,6 @@ int MainBuffer::putData (void *buffer, int toCopy, unsigned short volume, CallID
 int MainBuffer::availForPut (CallID call_id)
 {
 
-    // ost::MutexLock guard (_mutex);
-
     RingBuffer* ringbuffer = getRingBuffer (call_id);
 
     if (ringbuffer == NULL)
@@ -312,7 +365,6 @@ int MainBuffer::availForPut (CallID call_id)
 
 int MainBuffer::getData (void *buffer, int toCopy, unsigned short volume, CallID call_id)
 {
-  // ost::MutexLock guard (_mutex);
 
     CallIDSet* callid_set = getCallIDSet (call_id);
 
@@ -377,8 +429,6 @@ int MainBuffer::getDataByID (void *buffer, int toCopy, unsigned short volume, Ca
 int MainBuffer::availForGet (CallID call_id)
 {
 
-  // ost::MutexLock guard (_mutex);
-
     CallIDSet* callid_set = getCallIDSet (call_id);
 
     if (callid_set == NULL)
@@ -396,10 +446,10 @@ int MainBuffer::availForGet (CallID call_id)
             _debug ("This problem should not occur since we have %i element", (int) callid_set->size());
         }
 
-        // else
         return availForGetByID (*iter_id, call_id);
+
     } else {
-        // _debug("CallIDSet with ID: \"%s\" is a conference!", call_id.c_str());
+
         int avail_bytes = 99999;
         int nb_bytes;
         CallIDSet::iterator iter_id = callid_set->begin();
@@ -437,9 +487,6 @@ int MainBuffer::availForGetByID (CallID call_id, CallID reader_id)
 
 int MainBuffer::discard (int toDiscard, CallID call_id)
 {
-    // _debug("MainBuffer::discard");
-
-    // ost::MutexLock guard (_mutex);
 
     CallIDSet* callid_set = getCallIDSet (call_id);
 
@@ -447,7 +494,6 @@ int MainBuffer::discard (int toDiscard, CallID call_id)
         return 0;
 
     if (callid_set->empty()) {
-        // _debug("CallIDSet with ID: \"%s\" is empty!", call_id.c_str());
         return 0;
     }
 
diff --git a/sflphone-common/src/audio/mainbuffer.h b/sflphone-common/src/audio/mainbuffer.h
index 402fe84d6d745b172876db958106f29a094104d3..551cf8c0871d92f3fd3b686515505b9b94997c28 100644
--- a/sflphone-common/src/audio/mainbuffer.h
+++ b/sflphone-common/src/audio/mainbuffer.h
@@ -51,7 +51,7 @@ typedef std::map<CallID, CallIDSet*> CallIDMap;
 
 class MainBuffer {
 
-public:
+ public:
 
         MainBuffer();
 
@@ -67,20 +67,40 @@ public:
 
 	bool removeCallIDSet(CallID set_id);
 
+	/**
+	 * Add a new call id to this set
+	 */
 	void addCallIDtoSet(CallID set_id, CallID call_id);
 
 	void removeCallIDfromSet(CallID set_id, CallID call_id);
 
+	/**
+	 * Create a new ringbuffer with default readpointer
+	 */
 	RingBuffer* createRingBuffer(CallID call_id);
 
 	bool removeRingBuffer(CallID call_id);
 
 	void bindCallID(CallID call_id1, CallID call_id2 = default_id);
 
+	/**
+	 * Add a new call_id to unidirectional outgoing stream
+	 * \param call_id New call id to be added for this stream
+	 * \param process_id Process that require this stream
+	 */
+	void bindHalfDuplexOut(CallID process_id, CallID call_id = default_id);
+
+	/**
+	 * Unbind two calls
+	 */
 	void unBindCallID(CallID call_id1, CallID call_id2 = default_id);
 
+	void unBindHalfDuplexOut(CallID process_id, CallID call_id = default_id);
+
 	void unBindAll(CallID call_id);
 
+	void unBindAllHalfDuplexOut(CallID process_id);
+
 	int putData(void *buffer, int toCopy, unsigned short volume = 100, CallID call_id = default_id);
 
 	int getData(void *buffer, int toCopy, unsigned short volume = 100, CallID call_id = default_id);
diff --git a/sflphone-common/src/audio/recordable.cpp b/sflphone-common/src/audio/recordable.cpp
index f8044c12a4f7376cd34851cc54c04a42393877f6..7e3c37addf2db1648db1f1cf00ead48922502090 100644
--- a/sflphone-common/src/audio/recordable.cpp
+++ b/sflphone-common/src/audio/recordable.cpp
@@ -29,8 +29,9 @@
 
 #include "recordable.h"
 #include "manager.h"
+#include "mainbuffer.h"
 
-Recordable::Recordable()
+Recordable::Recordable() : recorder(&recAudio)
 {
 
     FILE_TYPE fileType = FILE_WAV;
@@ -61,3 +62,5 @@ void Recordable::setRecordingSmplRate (int smplRate)
     recAudio.setSndSamplingRate (smplRate);
 
 }
+
+
diff --git a/sflphone-common/src/audio/recordable.h b/sflphone-common/src/audio/recordable.h
index 8ab5281cc9fe0509b8e33876bbf47455ecf32464..4cd83dcc5064efb43a664363a80272e367469009 100644
--- a/sflphone-common/src/audio/recordable.h
+++ b/sflphone-common/src/audio/recordable.h
@@ -31,6 +31,7 @@
 #define RECORDABLE_H
 
 #include "../plug-in/audiorecorder/audiorecord.h"
+#include "../plug-in/audiorecorder/audiorecorder.h"
 
 class Recordable {
 
@@ -42,7 +43,7 @@ class Recordable {
 
 	bool isRecording(){ return recAudio.isRecording(); }
 
-	bool setRecording(){ return recAudio.setRecording(); }
+	virtual bool setRecording() = 0;
 
 	void stopRecording(){ recAudio.stopRecording(); }
 
@@ -61,13 +62,12 @@ class Recordable {
 	 */
          AudioRecord recAudio;
 
+	 AudioRecorder recorder;
 
     private:
 
 	/** File name for his call : time YY-MM-DD */
-        // std::string _filename;
-
-        
+        // std::string _filename;        
 
 };
 
diff --git a/sflphone-common/src/call.cpp b/sflphone-common/src/call.cpp
index 93e71226af15973500be6978febde563a6946d85..65195f5f50c5230641298ea18dc79d59ffccec0b 100644
--- a/sflphone-common/src/call.cpp
+++ b/sflphone-common/src/call.cpp
@@ -30,6 +30,7 @@
  */
 #include "call.h"
 #include "manager.h"
+#include "audio/mainbuffer.h"
 
 Call::Call (const CallID& id, Call::CallType type)
         : _callMutex()
@@ -184,3 +185,23 @@ Call::isAudioStarted()
     return _audioStarted;
 }
 
+
+bool
+Call::setRecording()
+{
+    bool recordStatus = Recordable::recAudio.setRecording();
+
+    if(!recordStatus)
+      return false;
+
+    MainBuffer *mbuffer = &(Manager::instance()._mainBuffer);
+
+    CallID process_id = Recordable::recorder.getRecorderID();
+
+    mbuffer->bindHalfDuplexOut(process_id, _id);
+    mbuffer->bindHalfDuplexOut(process_id);
+    
+    Recordable::recorder.start();
+  
+    return recordStatus;
+}
diff --git a/sflphone-common/src/call.h b/sflphone-common/src/call.h
index 6fcc87fd2f9908fb6b5bdbb744d80e927618a0be..89c81c1f67b0c196243e5e2a678d8c213b151dba 100644
--- a/sflphone-common/src/call.h
+++ b/sflphone-common/src/call.h
@@ -235,9 +235,11 @@ class Call: public Recordable{
          */
         unsigned int getLocalAudioPort();
 
-	std::string getRecFileId(){ return getPeerName(); }
+	std::string getRecFileId(void){ return getPeerName(); }
 
-	std::string getFileName() { return _filename; }
+	std::string getFileName(void) { return _filename; }
+
+	virtual bool setRecording(void);
 
     protected:
         /** Protect every attribute that can be changed by two threads */
diff --git a/sflphone-common/src/conference.cpp b/sflphone-common/src/conference.cpp
index d93cf8a0a486b8a97ac08e233e04f02462b096d3..17ee9a39b50cf1334f780e1c33c63a8694e795b4 100644
--- a/sflphone-common/src/conference.cpp
+++ b/sflphone-common/src/conference.cpp
@@ -34,6 +34,7 @@
 #include "conference.h"
 #include "manager.h"
 #include "audio/audiolayer.h"
+#include "audio/mainbuffer.h"
 
 int Conference::count = 0;
 
@@ -157,3 +158,30 @@ ParticipantSet Conference::getParticipantList()
     return _participants;
 }
 
+
+
+bool Conference::setRecording() {
+
+  bool recordStatus = Recordable::recAudio.setRecording();
+
+  if(!recordStatus)
+    return false;
+
+  MainBuffer *mbuffer = &(Manager::instance()._mainBuffer);
+
+  ParticipantSet::iterator iter = _participants.begin();
+
+  CallID process_id = Recordable::recorder.getRecorderID();
+
+  while(iter != _participants.end()) {
+      mbuffer->bindHalfDuplexOut(process_id, *iter);
+      iter++;
+  }
+
+  mbuffer->bindHalfDuplexOut(process_id);
+
+  Recordable::recorder.start();
+
+  return recordStatus;
+
+}
diff --git a/sflphone-common/src/conference.h b/sflphone-common/src/conference.h
index a20a9a25842faf1ff97f13048f4a98d9b9902468..77952531d1a7b979e6bcfb9c1d7e1a99c59d21b2 100644
--- a/sflphone-common/src/conference.h
+++ b/sflphone-common/src/conference.h
@@ -75,6 +75,8 @@ class Conference: public Recordable{
 
 	std::string getRecFileId(){ return getConfID(); }
 
+	virtual bool setRecording();
+
     private:  
 
         /** Unique ID of the conference */
diff --git a/sflphone-common/src/eventthread.h b/sflphone-common/src/eventthread.h
index aed9f5b5159052acb9cb776c94948798cf3cb384..eca20c22dc8c40ec39135eaf2539943f85373876 100644
--- a/sflphone-common/src/eventthread.h
+++ b/sflphone-common/src/eventthread.h
@@ -33,6 +33,7 @@
 
 #include <cc++/thread.h>
 
+
 class VoIPLink;
 class AlsaLayer;
 
diff --git a/sflphone-common/src/managerimpl.cpp b/sflphone-common/src/managerimpl.cpp
index 69ae92be43194567ee0ada907f07e6012d3a0720..da9bbcf51f4c5b0d39c2541c9d25035863727533 100644
--- a/sflphone-common/src/managerimpl.cpp
+++ b/sflphone-common/src/managerimpl.cpp
@@ -2556,16 +2556,19 @@ void ManagerImpl::setVolumeControls (bool display) {
 }
 
 void ManagerImpl::setRecordingCall (const CallID& id) {
-	/*
-	 _debug ("ManagerImpl::setRecording()! ");
-	 AccountID accountid = getAccountFromCall (id);
+  /*
+    _debug ("ManagerImpl::setRecording()! ");
+    AccountID accountid = getAccountFromCall (id);
+    
+    getAccountLink (accountid)->setRecording (id);
+  */
 
-	 getAccountLink (accountid)->setRecording (id);
-	 */
-	AccountID accountid = getAccountFromCall(id);
-	Recordable* rec = (Recordable*) getAccountLink(accountid)->getCall(id);
+  AccountID accountid = getAccountFromCall(id);
+  Recordable* rec = (Recordable *) getAccountLink(accountid)->getCall(id);
 
-	rec->setRecording();
+  rec->setRecording();
+
+	
 }
 
 bool ManagerImpl::isRecording (const CallID& id) {
diff --git a/sflphone-common/src/managerimpl.h b/sflphone-common/src/managerimpl.h
index 3c88ba6a14ce54c51141d528cdaefe3ea4a1f73a..700bb1721d5a906a7df5d8112f9ece9fe251728d 100644
--- a/sflphone-common/src/managerimpl.h
+++ b/sflphone-common/src/managerimpl.h
@@ -93,7 +93,6 @@ typedef std::map<CallID, Conference*> ConferenceMap;
 
 static CallID default_conf = "conf"; 
 
-
 static char * mapStateToChar[] = {
     (char*) "UNREGISTERED",
     (char*) "TRYING",
@@ -1241,6 +1240,7 @@ class ManagerImpl {
     void unloadAccountMap();
 
 
+ public:
     /**
      * Instance of the MainBuffer for the whole application
      *
@@ -1250,8 +1250,6 @@ class ManagerImpl {
      */ 
      MainBuffer _mainBuffer;
 
-    
-   public:
 
     /**
      * Tell if there is a current call processed
@@ -1309,14 +1307,12 @@ class ManagerImpl {
     int isStunEnabled (void);
     void enableStun (void);
 
-    // Map 
+    // Map containing reference between conferences and calls 
     ConferenceCallMap _conferencecall;
 
-    // 
+    // Map containing conference pointers
     ConferenceMap _conferencemap;
 
-
-
 private:
 
     // Copy Constructor
diff --git a/sflphone-common/src/plug-in/audiorecorder/Makefile.am b/sflphone-common/src/plug-in/audiorecorder/Makefile.am
index 2a37f147295de545974f83dbf48e097a5a0d53dc..811f75102fd1d58b44a735ce14b7158340dd326a 100644
--- a/sflphone-common/src/plug-in/audiorecorder/Makefile.am
+++ b/sflphone-common/src/plug-in/audiorecorder/Makefile.am
@@ -3,4 +3,5 @@ include $(top_srcdir)/globals.mak
 noinst_LTLIBRARIES = libaudiorecorder.la
 
 libaudiorecorder_la_SOURCES = \
-		audiorecord.cpp
\ No newline at end of file
+		audiorecord.cpp \
+		audiorecorder.cpp
\ No newline at end of file
diff --git a/sflphone-common/src/plug-in/audiorecorder/audiorecorder.cpp b/sflphone-common/src/plug-in/audiorecorder/audiorecorder.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..77587a501171e11490761734024b370245058905
--- /dev/null
+++ b/sflphone-common/src/plug-in/audiorecorder/audiorecorder.cpp
@@ -0,0 +1,56 @@
+/*
+ *  Copyright (C) 2004, 2005, 2006, 2009, 2008, 2009, 2010 Savoir-Faire Linux Inc.
+ *  Alexandre Savard <alexandre.savard@savoirfairelinux.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 3 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  Additional permission under GNU GPL version 3 section 7:
+ *
+ *  If you modify this program, or any covered work, by linking or
+ *  combining it with the OpenSSL project's OpenSSL library (or a
+ *  modified version of that library), containing parts covered by the
+ *  terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
+ *  grants you additional permission to convey the resulting work.
+ *  Corresponding Source for a non-source form of such a combination
+ *  shall include the source code for the parts of OpenSSL used as well
+ *  as that of the covered work.
+ */
+
+#include "audiorecorder.h"
+
+AudioRecorder::AudioRecorder (AudioRecord  *arec)
+  : Thread(), recorderId("recorder_id")
+{
+    setCancel (cancelDeferred);
+
+    arecord = arec;
+}
+
+
+/**
+ * Reimplementation of run()
+ */
+void AudioRecorder::run (void)
+{
+
+    SFLDataFormat buffer[10000];
+
+    // int availBytes = mbuffer->availForGet(recorderId);
+
+    // mbuffer->getData(buffer, availBytes, 100, recorderId);
+
+    // arecord->recData(buffer, availBytes/sizeof(SFLDataFormat));
+
+}
diff --git a/sflphone-common/src/plug-in/audiorecorder/audiorecorder.h b/sflphone-common/src/plug-in/audiorecorder/audiorecorder.h
new file mode 100644
index 0000000000000000000000000000000000000000..9b3ef3d26ed9fd242732834a159cf850aeeae5af
--- /dev/null
+++ b/sflphone-common/src/plug-in/audiorecorder/audiorecorder.h
@@ -0,0 +1,60 @@
+/*
+ *  Copyright (C) 2004, 2005, 2006, 2009, 2008, 2009, 2010 Savoir-Faire Linux Inc.
+ *  Alexandre Savard <alexandre.savard@savoirfairelinux.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 3 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  Additional permission under GNU GPL version 3 section 7:
+ *
+ *  If you modify this program, or any covered work, by linking or
+ *  combining it with the OpenSSL project's OpenSSL library (or a
+ *  modified version of that library), containing parts covered by the
+ *  terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
+ *  grants you additional permission to convey the resulting work.
+ *  Corresponding Source for a non-source form of such a combination
+ *  shall include the source code for the parts of OpenSSL used as well
+ *  as that of the covered work.
+ */
+
+#ifndef __AUDIORECORDER_H_
+#define __AUDIORECORDER_H_
+
+#include <cc++/thread.h>
+#include "audiorecord.h"
+#include <string>
+
+class AudioRecorder : public ost::Thread {
+
+   public:
+      AudioRecorder(AudioRecord  *arec);
+
+      ~AudioRecorder(void){ terminate(); }
+
+      std::string getRecorderID() { return recorderId; }
+
+      virtual void run();
+
+   private:
+      AudioRecorder (const AudioRecorder& ar);
+      AudioRecorder& operator=(const AudioRecorder& ar);
+
+      // MainBuffer *mbuffer;
+
+      std::string recorderId;
+
+      AudioRecord *arecord;
+};
+
+#endif
diff --git a/sflphone-common/src/video/Makefile.am b/sflphone-common/src/video/Makefile.am
new file mode 100644
index 0000000000000000000000000000000000000000..b7a60a35b6d3e5f440656a835268f4e42a8f4e13
--- /dev/null
+++ b/sflphone-common/src/video/Makefile.am
@@ -0,0 +1,35 @@
+include $(top_srcdir)/globals.mak
+
+SUBDIRS = decoder rtp
+
+AM_CXXFLAGS = $(GSTREAMER_CFLAGS)
+
+noinst_LTLIBRARIES = libvideo.la
+
+libvideo_la_SOURCES = \
+	VideoInputSource.cpp \
+	VideoInputSourceGst.cpp  \
+	VideoEndpoint.cpp \
+	VideoFrame.cpp  \
+	FrameFormat.cpp \
+	VideoDevice.cpp \
+	GstVideoDevice.cpp
+
+libvideo_la_LIBADD = \
+	decoder/libvideodecoder.la \
+	rtp/libvideortp.la
+
+libvideo_la_LDFLAGS = $(GSTREAMER_LIBS) $(LIBS)
+
+noinst_HEADERS = \
+	VideoInputSource.h \
+	VideoInputSourceGst.h \
+	VideoEndpoint.h \
+	FrameFormat.h \
+	VideoDevice.h \
+	VideoFrame.h \
+	FrameFormat.h \
+	VideoDevice.h \
+	GstVideoDevice.h
+					
+
diff --git a/sflphone-common/src/video/decoder/Makefile.am b/sflphone-common/src/video/decoder/Makefile.am
new file mode 100644
index 0000000000000000000000000000000000000000..6dbf239905378d107cecb4bd6acef0e015955aad
--- /dev/null
+++ b/sflphone-common/src/video/decoder/Makefile.am
@@ -0,0 +1,17 @@
+include $(top_srcdir)/globals.mak
+
+AM_CXXFLAGS = $(LIBAVCODEC_CFLAGS) $(LIBSWSCALE_CFLAGS)
+
+noinst_LTLIBRARIES = libvideodecoder.la
+
+libvideodecoder_la_SOURCES = \
+		H264Decoder.cpp \
+		VideoDecoder.cpp
+		
+noinst_HEADERS = \
+		VideoDecoder.h \
+		H264Decoder.h
+			
+libvideodecoder_la_LDFLAGS = $(LIBAVCODEC_LIBS) $(LIBSWSCALE_LIBS) $(LIBS)
+
+libvideodecoder_la_LIBADD = $(LIBAVCODEC_LIBS) $(LIBSWSCALE_LIBS) $(LIBS)
\ No newline at end of file
diff --git a/sflphone-common/test/Makefile.am b/sflphone-common/test/Makefile.am
index ff5d1090418742397676c3db0ee240eb094fe324..b2ae6aae0c29f2449ac90c8c11c6ee023a3707f8 100644
--- a/sflphone-common/test/Makefile.am
+++ b/sflphone-common/test/Makefile.am
@@ -1,11 +1,12 @@
 include ../globals.mak
 
-TESTS = test
-check_PROGRAMS = $(TESTS)
+check_PROGRAMS = test
+
 test_CXXFLAGS = $(CPPUNIT_CFLAGS)
 test_LDADD = $(LLIBS)
-test_LDFLAGS = -ldl
-test_SOURCES = main.cpp \
+
+test_SOURCES = \
+	main.cpp \
 	validator.cpp \
 	validator.h \
 	accounttest.h \
@@ -18,8 +19,6 @@ test_SOURCES = main.cpp \
 	historytest.cpp \
 	hookmanagertest.h \
 	hookmanagertest.cpp \
-	mainbuffertest.h \
-	mainbuffertest.cpp \
 	numbercleanertest.h \
 	numbercleanertest.cpp \
 	pluginmanagertest.h \
@@ -35,9 +34,6 @@ test_SOURCES = main.cpp \
 
 
 LLIBS=$(CPPUNIT_LIBS) \
-	../src/libsflphone.la  \
-	$(ZEROCONFLIB) \
-	$(LIB_DNSSD) \
 	@ALSA_LIBS@ \
 	@PULSEAUDIO_LIBS@ \
 	@CPPUNIT_LIBS@ \
@@ -48,27 +44,4 @@ LLIBS=$(CPPUNIT_LIBS) \
 	@libssl_LIBS@ \
 	@SAMPLERATE_LIBS@ \
 	$(PJSIP_LIBS) \
-	../src/sflphoned-logger.o \
-	../src/sflphoned-managerimpl.o \
-	../src/sflphoned-account.o\
-	../src/sflphoned-accountcreator.o \
-	../src/sflphoned-call.o \
-	../src/sflphoned-conference.o \
-	../src/sflphoned-eventthread.o \
-	../src/sflphoned-managerimpl_registration.o \
-	../src/sflphoned-numbercleaner.o \
-	../src/sflphoned-observer.o \
-	../src/sflphoned-voiplink.o \
-	../src/sip/libsiplink_la-sipcall.o \
-	../src/iax/libiaxlink_la-iaxcall.o \
-	../src/sip/libsiplink_la-sipvoiplink.o \
-	../src/iax/libiaxlink_la-iaxvoiplink.o \
-	../src/sip/libsiplink_la-sipaccount.o \
-	../src/iax/libiaxlink_la-iaxaccount.o \
-	../src/sip/libsiplink_la-sdp.o \
-	../src/sip/libsiplink_la-sdpmedia.o \
-	../src/plug-in/pluginmanager.o \
-	../src/plug-in/audiorecorder/audiorecord.o \
-	../src/audio/samplerateconverter.o \
-	../src/audio/delaydetection.o \
-        ../src/history/historymanager.o
\ No newline at end of file
+	../src/libsflphone.la
diff --git a/sflphone-common/test/main.cpp b/sflphone-common/test/main.cpp
index 98f792ad1eb8def07bf678ca9403de4de0e66bbe..131630b33d46feb5d6e8f3a7ce7cb9caba5ff487 100644
--- a/sflphone-common/test/main.cpp
+++ b/sflphone-common/test/main.cpp
@@ -28,10 +28,10 @@
  *  as that of the covered work.
  */
 
-#include "logger.h"
-#include "global.h"
-#include "manager.h"
-#include "constants.h"
+#include <logger.h>
+#include <manager.h>
+
+#define CONFIG_SAMPLE   "sflphonedrc-sample"
 
 #include <cppunit/CompilerOutputter.h>
 #include <cppunit/extensions/TestFactoryRegistry.h>