src/org/sipdroid/media/RtpStreamReceiver.java
changeset 834 e8d6255306f8
parent 830 c8b4ace735ea
child 835 4e40f3481f23
--- a/src/org/sipdroid/media/RtpStreamReceiver.java	Sat Jan 23 21:48:58 2010 +0100
+++ b/src/org/sipdroid/media/RtpStreamReceiver.java	Sat Jan 23 22:19:43 2010 +0100
@@ -19,18 +19,19 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-package org.sipdroid.media;
+package src.org.sipdroid.media;
+
+import java.io.IOException;
+import java.net.SocketException;
 
-import jlibrtp.AppCallerThread;
-import jlibrtp.DataFrame;
-import jlibrtp.Participant;
-import jlibrtp.RTPAppIntf;
-import jlibrtp.RTPReceiverThread;
-import jlibrtp.RTPSession;
+import org.sipdroid.sipua.UserAgent;
+import org.sipdroid.sipua.ui.Receiver;
+import org.sipdroid.sipua.ui.Sipdroid;
+import org.sipdroid.pjlib.Codec;
 
-import org.sipdroid.media.codecs.Codec;
-import org.sipdroid.net.tools.DataFramePool;
-import org.sipdroid.net.tools.DatagramPool;
+import src.org.sipdroid.net.RtpPacket;
+import src.org.sipdroid.net.RtpSocket;
+import src.org.sipdroid.net.SipdroidSocket;
 
 import android.content.ContentResolver;
 import android.content.Context;
@@ -39,6 +40,7 @@
 import android.media.AudioManager;
 import android.media.AudioTrack;
 import android.media.ToneGenerator;
+import android.os.PowerManager;
 import android.preference.PreferenceManager;
 import android.provider.Settings;
 
@@ -46,11 +48,14 @@
  * RtpStreamReceiver is a generic stream receiver. It receives packets from RTP
  * and writes them into an OutputStream.
  */
-public class RtpStreamReceiver extends Thread implements RTPAppIntf{
+public class RtpStreamReceiver extends Thread {
 
 	/** Whether working in debug mode. */
 	public static boolean DEBUG = true;
 
+	/** Payload type */
+	int p_type;
+
 	/** Size of the read buffer */
 	public static final int BUFFER_SIZE = 1024;
 
@@ -58,61 +63,31 @@
 	public static final int SO_TIMEOUT = 200;
 
 	/** The RtpSocket */
-	RTPSession rtpSession = null;
-	byte[] buffer;
-
-	/** The codec */
-	private Codec codec;
-	private Context mContext;
-
-	private int frame_size;
-	private int codec_frame_size;
-	private int sampling_rate;
+	RtpSocket rtp_socket = null;
 
 	/** Whether it is running */
 	boolean running;
 	AudioManager am;
 	ContentResolver cr;
-
-	private int codec_divider;
 	public static int speakermode;
-
-	short lin[];
-	short lin2[];
-	int user, server, lserver, luser, cnt, todo, headroom, len, timeout = 1, seq = 0, cnt2 = 0, m = 1,
-	expseq, getseq, vm = 1, gap, oldvol;
-	boolean islate;
-
-	Codec.Context codecCtx;
-
-	AudioTrack track;
-
+	
 	/**
 	 * Constructs a RtpStreamReceiver.
-	 * @param ctx 
-	 * @param remoteAddr 
 	 * 
 	 * @param output_stream
 	 *            the stream sink
 	 * @param socket
 	 *            the local receiver SipdroidSocket
 	 */
-	public RtpStreamReceiver(Codec ci, RTPSession rtpSession, Context ctx) {
-		init(ci, rtpSession, ctx);
+	public RtpStreamReceiver(SipdroidSocket socket, int payload_type) {
+		init(socket);
+		p_type = payload_type;
 	}
 
-	/** Inits the RtpStreamReceiver 
-	 * @param ctx 
-	 * @param remoteAddr
-	 **/
-	private void init(Codec ci, RTPSession rtpSession, Context ctx) {
-		this.rtpSession = rtpSession;
-		codec = ci;
-		codec_frame_size = codec.getInfo().codecFrameSize;		
-		codec_divider = codec.getInfo().rtpSampleDivider;
-		frame_size = 160 * codec_divider;
-		sampling_rate = codec.getInfo().samplingRate;
-		mContext = ctx;
+	/** Inits the RtpStreamReceiver */
+	private void init(SipdroidSocket socket) {
+		if (socket != null)
+			rtp_socket = new RtpSocket(socket);
 	}
 
 	/** Whether is running */
@@ -124,25 +99,25 @@
 	public void halt() {
 		running = false;
 	}
-
+	
 	public int speaker(int mode) {
 		int old = speakermode;
-
+		
+		if (Receiver.headset > 0 && mode == AudioManager.MODE_NORMAL)
+			return old;
 		saveVolume();
-		speakermode = mode;
+		setMode(speakermode = mode);
 		restoreVolume();
 		return old;
 	}
 
 	double smin = 200,s;
-
-	private int REAL_BUFFER_SIZE;
 	public static int nearend;
-
+	
 	void calc(short[] lin,int off,int len) {
 		int i,j;
 		double sm = 30000,r;
-
+		
 		for (i = 0; i < len; i += 5) {
 			j = lin[i+off];
 			s = 0.03*Math.abs(j) + 0.97*s;
@@ -162,30 +137,58 @@
 		r = (double)len/100000;
 		smin = sm*r + smin*(1-r);
 	}
-
+	
+	static void setStreamVolume(final int stream,final int vol,final int flags) {
+        (new Thread() {
+			public void run() {
+				AudioManager am = (AudioManager) Receiver.mContext.getSystemService(Context.AUDIO_SERVICE);
+				am.setStreamVolume(stream, vol, flags);
+				if (stream == AudioManager.STREAM_MUSIC) restored = true;
+			}
+        }).start();
+	}
+	
+	static boolean restored;
+	
 	void restoreVolume() {
-		am.setStreamVolume(AudioManager.STREAM_MUSIC,
-				PreferenceManager.getDefaultSharedPreferences(mContext).getInt("volume"+speakermode, 
-						am.getStreamMaxVolume(AudioManager.STREAM_MUSIC)*
-						(speakermode == AudioManager.MODE_NORMAL?4:3)/4
+		switch (am.getMode()) {
+		case AudioManager.MODE_IN_CALL:
+				setStreamVolume(AudioManager.STREAM_RING,(int)(
+						am.getStreamMaxVolume(AudioManager.STREAM_RING)*
+						org.sipdroid.sipua.ui.Settings.getEarGain()), 0);
+				track.setStereoVolume(AudioTrack.getMaxVolume()*
+						org.sipdroid.sipua.ui.Settings.getEarGain()
+						,AudioTrack.getMaxVolume()*
+						org.sipdroid.sipua.ui.Settings.getEarGain());
+				break;
+		case AudioManager.MODE_NORMAL:
+				track.setStereoVolume(AudioTrack.getMaxVolume(),AudioTrack.getMaxVolume());
+				break;
+		}
+		setStreamVolume(AudioManager.STREAM_MUSIC,
+				PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).getInt("volume"+speakermode, 
+				am.getStreamMaxVolume(AudioManager.STREAM_MUSIC)*
+				(speakermode == AudioManager.MODE_NORMAL?4:3)/4
 				),0);
 	}
-
+	
 	void saveVolume() {
-		Editor edit = PreferenceManager.getDefaultSharedPreferences(mContext).edit();
-		edit.putInt("volume"+speakermode,am.getStreamVolume(AudioManager.STREAM_MUSIC));
-		edit.commit();
+		if (restored) {
+			Editor edit = PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).edit();
+			edit.putInt("volume"+speakermode,am.getStreamVolume(AudioManager.STREAM_MUSIC));
+			edit.commit();
+		}
 	}
-
+	
 	void saveSettings() {
-		if (!PreferenceManager.getDefaultSharedPreferences(mContext).getBoolean("oldvalid",false)) {
+		if (!PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).getBoolean("oldvalid",false)) {
 			int oldvibrate = am.getVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER);
 			int oldvibrate2 = am.getVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION);
-			if (!PreferenceManager.getDefaultSharedPreferences(mContext).contains("oldvibrate2"))
+			if (!PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).contains("oldvibrate2"))
 				oldvibrate2 = AudioManager.VIBRATE_SETTING_ON;
 			int oldpolicy = android.provider.Settings.System.getInt(cr, android.provider.Settings.System.WIFI_SLEEP_POLICY, 
 					Settings.System.WIFI_SLEEP_POLICY_DEFAULT);
-			Editor edit = PreferenceManager.getDefaultSharedPreferences(mContext).edit();
+			Editor edit = PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).edit();
 			edit.putInt("oldvibrate", oldvibrate);
 			edit.putInt("oldvibrate2", oldvibrate2);
 			edit.putInt("oldpolicy", oldpolicy);
@@ -194,164 +197,287 @@
 			edit.commit();
 		}
 	}
+	
+	public static void setMode(int mode) {
+		Editor edit = PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).edit();
+		edit.putBoolean("setmode", mode != AudioManager.MODE_NORMAL);
+		edit.commit();
+		AudioManager am = (AudioManager) Receiver.mContext.getSystemService(Context.AUDIO_SERVICE);
+		am.setMode(mode);
+	}
+	
+	public static void restoreMode() {
+		if (PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).getBoolean("setmode",true)) {
+			if (Receiver.pstn_state == null || Receiver.pstn_state.equals("IDLE"))
+				setMode(AudioManager.MODE_NORMAL);
+			else {
+				Editor edit = PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).edit();
+				edit.putBoolean("setmode", false);
+				edit.commit();
+			}
+		}
+	}
 
-	void restoreSettings() {
-		int oldvibrate = PreferenceManager.getDefaultSharedPreferences(mContext).getInt("oldvibrate",0);
-		int oldvibrate2 = PreferenceManager.getDefaultSharedPreferences(mContext).getInt("oldvibrate2",0);
-		int oldpolicy = PreferenceManager.getDefaultSharedPreferences(mContext).getInt("oldpolicy",0);
-		am.setVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER,oldvibrate);
-		am.setVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION,oldvibrate2);
-		Settings.System.putInt(cr, Settings.System.WIFI_SLEEP_POLICY, oldpolicy);
-		am.setStreamVolume(AudioManager.STREAM_RING, PreferenceManager.getDefaultSharedPreferences(mContext).getInt("oldring",0), 0);
-		Editor edit = PreferenceManager.getDefaultSharedPreferences(mContext).edit();
-		edit.putBoolean("oldvalid", false);
-		edit.commit();
+	public static void restoreSettings() {
+		if (PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).getBoolean("oldvalid",true)) {
+			AudioManager am = (AudioManager) Receiver.mContext.getSystemService(Context.AUDIO_SERVICE);
+	        ContentResolver cr = Receiver.mContext.getContentResolver();
+			int oldvibrate = PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).getInt("oldvibrate",0);
+			int oldvibrate2 = PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).getInt("oldvibrate2",0);
+			int oldpolicy = PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).getInt("oldpolicy",0);
+			am.setVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER,oldvibrate);
+			am.setVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION,oldvibrate2);
+			Settings.System.putInt(cr, Settings.System.WIFI_SLEEP_POLICY, oldpolicy);
+			setStreamVolume(AudioManager.STREAM_RING, PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).getInt("oldring",0), 0);
+			Editor edit = PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).edit();
+			edit.putBoolean("oldvalid", false);
+			edit.commit();
+			PowerManager pm = (PowerManager) Receiver.mContext.getSystemService(Context.POWER_SERVICE);
+			PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK |
+					PowerManager.ACQUIRE_CAUSES_WAKEUP, "Sipdroid.RtpStreamReceiver");
+			wl.acquire(1000);
+		}
+		restoreMode();
 	}
 
 	public static float good, late, lost, loss;
-
+	public static int timeout;
+	
+	void empty() {
+		try {
+			rtp_socket.getDatagramSocket().setSoTimeout(1);
+			for (;;)
+				rtp_socket.receive(rtp_packet);
+		} catch (SocketException e2) {
+			if (!Sipdroid.release) e2.printStackTrace();
+		} catch (IOException e) {
+		}
+		try {
+			rtp_socket.getDatagramSocket().setSoTimeout(1000);
+		} catch (SocketException e2) {
+			if (!Sipdroid.release) e2.printStackTrace();
+		}
+	}
+	
+	RtpPacket rtp_packet;
+	AudioTrack track;
+	
 	/** Runs it in a new Thread. */
-	@Override
 	public void run() {
-		REAL_BUFFER_SIZE = BUFFER_SIZE * codec_divider;
-		speakermode = AudioManager.MODE_IN_CALL;
-		android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_AUDIO);
-		am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
-		cr = mContext.getContentResolver();
-		//saveSettings();
+		boolean nodata = PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).getBoolean("nodata",false);
+		
+		if (rtp_socket == null) {
+			if (DEBUG)
+				println("ERROR: RTP socket is null");
+			return;
+		}
 
-		Settings.System.putInt(cr, Settings.System.WIFI_SLEEP_POLICY,Settings.System.WIFI_SLEEP_POLICY_NEVER);
-		//am.setVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER,AudioManager.VIBRATE_SETTING_OFF);
-		//am.setVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION,AudioManager.VIBRATE_SETTING_OFF);
-		//oldvol = am.getStreamVolume(AudioManager.STREAM_MUSIC);
-		restoreVolume();
+		byte[] buffer = new byte[BUFFER_SIZE+12];
+		byte[] buffer_gsm = new byte[33+12];
+		int i;
+		rtp_packet = new RtpPacket(buffer, 0);
+
+		if (DEBUG)
+			println("Reading blocks of max " + buffer.length + " bytes");
 
-		track = new AudioTrack(AudioManager.STREAM_MUSIC, sampling_rate, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT,
-				REAL_BUFFER_SIZE*2*2, AudioTrack.MODE_STREAM);
+		running = true;
+		speakermode = Receiver.docked > 0?AudioManager.MODE_NORMAL:AudioManager.MODE_IN_CALL;
+		restored = false;
+
+		android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_AUDIO);
+		am = (AudioManager) Receiver.mContext.getSystemService(Context.AUDIO_SERVICE);
+        cr = Receiver.mContext.getContentResolver();
+		saveSettings();
+		Settings.System.putInt(cr, Settings.System.WIFI_SLEEP_POLICY,Settings.System.WIFI_SLEEP_POLICY_NEVER);
+		am.setVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER,AudioManager.VIBRATE_SETTING_OFF);
+		am.setVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION,AudioManager.VIBRATE_SETTING_OFF);
+		int oldvol = am.getStreamVolume(AudioManager.STREAM_MUSIC);
+		track = new AudioTrack(AudioManager.STREAM_MUSIC, 8000, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT,
+				BUFFER_SIZE*2*2, AudioTrack.MODE_STREAM);
+		short lin[] = new short[BUFFER_SIZE];
+		short lin2[] = new short[BUFFER_SIZE];
+		int user, server, lserver, luser, cnt, todo, headroom, len = 0, seq = 0, cnt2 = 0, m = 1,
+			expseq, getseq, vm = 1, gap, gseq;
+		timeout = 1;
+		boolean islate;
+		user = 0;
+		lserver = 0;
+		luser = -8000;
+		cnt = 0;
+		switch (p_type) {
+		case 3:
+			Codec.init();
+			break;
+		case 0:
+		case 8:
+			G711.init();
+			break;
+		}
+		ToneGenerator tg = new ToneGenerator(AudioManager.STREAM_MUSIC,(int)(ToneGenerator.MAX_VOLUME*2*org.sipdroid.sipua.ui.Settings.getEarGain()));
 		track.play();
-		lin = new short[REAL_BUFFER_SIZE];
-		lin2 = new short[REAL_BUFFER_SIZE];
-		user = 0; //number of samples written
-		server = 0; // number of samples played
-		lserver = 0; // last number of samples played
-		luser = -sampling_rate; // last number of samples written
-		cnt = 0;
-		codecCtx = codec.initDecoder(); 
-		System.gc();
-		println("DEBUG: rtpStreamReceiver session launch");
-		running = true;
-		AppCallerThread appCall = rtpSession.getAppCallerThrd();
-		RTPReceiverThread recv = rtpSession.getRTPRecvThrd();
-		DataFrame frame = null;
-		recv.init();
+		if (Receiver.headset > 0 && Receiver.oRingtone != null) {
+			ToneGenerator tg2 = new ToneGenerator(AudioManager.STREAM_RING,(int)(ToneGenerator.MAX_VOLUME*2*org.sipdroid.sipua.ui.Settings.getEarGain()));
+			tg2.startTone(ToneGenerator.TONE_SUP_RINGTONE);
+			System.gc();
+			tg2.stopTone();
+		} else
+			System.gc();
 		while (running) {
-			recv.readPacketToBuffer();
-			frame = appCall.getNextDataFrame();
-			if (frame == null)
-				continue;
-			buffer = (frame.getPkt()[0]).getPayload();
-			if (timeout != 0) { //on ecrit du blanc sur l'audiotrack
-				user += track.write(lin,0,REAL_BUFFER_SIZE);
-				user += track.write(lin,0,REAL_BUFFER_SIZE);
+			if (Receiver.call_state == UserAgent.UA_STATE_HOLD) {
+				tg.stopTone();
+				track.pause();
+				while (running && Receiver.call_state == UserAgent.UA_STATE_HOLD) {
+					try {
+						sleep(1000);
+					} catch (InterruptedException e1) {
+					}
+				}
+				track.play();
+				System.gc();
+				timeout = 1;
+				seq = 0;
 			}
-			timeout = 0;
-			if (running) {
-
-				//println("seq " + seq + " frame seq " + (frame.getPkt()[0]).getSeqNumber());
-				if (seq == (frame.getPkt()[0]).getSeqNumber()) {
-					m++;
-					continue;
+			try {
+				rtp_socket.receive(rtp_packet);
+				if (timeout != 0) {
+					tg.stopTone();
+					track.pause();
+					user += track.write(lin2,0,BUFFER_SIZE);
+					user += track.write(lin2,0,BUFFER_SIZE);
+					track.play();
+					cnt += 2*BUFFER_SIZE;
+					empty();
+				}
+				timeout = 0;
+			} catch (IOException e) {
+				if (timeout == 0 && nodata) {
+					tg.startTone(ToneGenerator.TONE_SUP_RINGTONE);
+				}
+				rtp_socket.getDatagramSocket().disconnect();
+				if (++timeout > 22) {
+					Receiver.engine(Receiver.mContext).rejectcall();
+					break;
 				}
+			}
+			if (running && timeout == 0) {		
+				 gseq = rtp_packet.getSequenceNumber();
+				 if (seq == gseq) {
+					 m++;
+					 continue;
+				 }
+				 
+				 server = track.getPlaybackHeadPosition();
+				 headroom = user-server;
+				 
+				 if (headroom > 1500)
+					 cnt += len;
+				 else
+					 cnt = 0;
+				 
+				 if (lserver == server)
+					 cnt2++;
+				 else
+					 cnt2 = 0;
 
-				codec.decode(codecCtx, buffer, 12, codec_frame_size, lin, 0);
-				len = frame_size;
-
-				if (speakermode == AudioManager.MODE_NORMAL)
-					calc(lin,0,len);
-
-				server = track.getPlaybackHeadPosition(); // on récupère la position actuel de la tete de lecture
-				headroom = user-server; // on recalcule la différence entre la position de la tete de lecture et ce qu'on a écrit sur la piste
-				//println("headroom " + headroom + " user " + user + " server " + server);
-				if (headroom < 250 * codec_divider) { // si le headroom est trop petit, il faut rattraper le retard en écrivant du blanc/répétant ce qu'il y a à ecrire
-					todo = 625 * codec_divider - headroom;
-					//println("insert "+todo);
-					android.util.Log.d("RECV", "insert");
+				 if (cnt <= 500 || cnt2 >= 2 || headroom - 875 < len) {
+					 switch (rtp_packet.getPayloadType()) {
+					 case 0:
+						 len = rtp_packet.getPayloadLength();
+						 G711.ulaw2linear(buffer, lin, len);
+						 break;
+					 case 8:
+						 len = rtp_packet.getPayloadLength();
+						 G711.alaw2linear(buffer, lin, len);
+						 break;
+					 case 3:
+						 for (i = 12; i < 45; i++)
+							 buffer_gsm[i] = buffer[i];
+						 len = Codec.decode(buffer_gsm, lin, 0);
+						 break;
+					 }
+					 
+		 			 if (speakermode == AudioManager.MODE_NORMAL)
+		 				 calc(lin,0,len);
+				 }
+				 
+	 			 if (headroom < 250) { 
+					todo = 875 - headroom;
+					println("insert "+todo);
 					islate = true;
-					if (todo < len)
-						user += track.write(lin,0,todo); // on écrit le packet reçu tel quel
-					else
-						user += track.write(lin2,0,todo); // ecriture de blanc de taille 625 - headroom, avant l'écriture du packet
-				} else
+					user += track.write(lin2,0,todo);
+				 } else
 					islate = false;
 
-				if (headroom > 1000 * codec_divider) // si le headroom est trop grand, on calcule l'écart.
-					cnt += len; // on additione le nombre de sample ou il y a eu un headroom supérieur a 1000
-				else
-					cnt = 0;
-
-				if (lserver == server) // on compte le nombre de boucle que l'on a fait sans qu'aucun sample n'ai été joué.
-					cnt2++;
-				else
-					cnt2 = 0;
-
-				if (cnt > 1000 * codec_divider && cnt2 < 2) { // si la position de la tete de lecture n'a pas bougé durant 2 tours et que le nombre de sample ou le headroom a été supérieur à 1000 est > 1000
-					todo = headroom - 625 * codec_divider;
-					try {
-						//android.util.Log.d("RECV", "cut");
-						sleep(20);
-					} catch (InterruptedException e) {
-						// TODO Auto-generated catch block
-						e.printStackTrace();
-					}
-				}
-				user += track.write(lin,0,len);
-				m = 1;
-				seq = (frame.getPkt()[0]).getSeqNumber();
-				DataFramePool.getInstance().returnFrame(frame);
-				//println("headroom " + headroom + " user " + user + " server " + server + " luser " + luser + " lserver " + lserver);
-				if (user >= luser + sampling_rate) {
-					/*if (am.getMode() != speakermode) {
-						am.setMode(speakermode);
-						switch (speakermode) {
-						case AudioManager.MODE_IN_CALL:
-							am.setStreamVolume(AudioManager.STREAM_RING,(int)(
-									am.getStreamMaxVolume(AudioManager.STREAM_RING)*
-									com.mbdsys.sfrdroid.ui.Settings.getEarGain()), 0);
-							track.setStereoVolume(AudioTrack.getMaxVolume()*
-									com.mbdsys.sfrdroid.ui.Settings.getEarGain()
-									,AudioTrack.getMaxVolume()*
-									com.mbdsys.sfrdroid.ui.Settings.getEarGain());
-							//running = false;
-						case AudioManager.MODE_NORMAL:
-							track.setStereoVolume(AudioTrack.getMaxVolume(),AudioTrack.getMaxVolume());
-							//running = false;
-						}
-					}*/
-					luser = user;
-				}
-				lserver = server;
-				System.arraycopy(lin, 0, lin2, 0, REAL_BUFFER_SIZE);
+				 if (cnt > 500 && cnt2 < 2) {
+					 todo = headroom - 875;
+					 println("cut "+todo);
+					 if (todo < len)
+						 user += track.write(lin,todo,len-todo);
+				 } else
+					 user += track.write(lin,0,len);
+				 
+				 if (seq != 0) {
+					 getseq = gseq&0xff;
+					 expseq = ++seq&0xff;
+					 if (m == RtpStreamSender.m) vm = m;
+					 gap = (getseq - expseq) & 0xff;
+					 if (gap > 0) {
+						 if (gap > 100) gap = 1;
+						 loss += gap;
+						 lost += gap;
+						 good += gap - 1;
+					 } else {
+						 if (m < vm)
+							 loss++;
+						 if (islate)
+							 late++;
+					 }
+					 good++;
+					 if (good > 100) {
+						 good *= 0.99;
+						 lost *= 0.99;
+						 loss *= 0.99;
+						 late *= 0.99;
+					 }
+				 }
+				 m = 1;
+				 seq = gseq;
+				 
+				 if (user >= luser + 8000 && Receiver.call_state == UserAgent.UA_STATE_INCALL) {
+					 if (luser == -8000 || am.getMode() != speakermode) {
+						 saveVolume();
+						 setMode(speakermode);
+						 restoreVolume();
+					 }
+					 luser = user;
+				 }
+				 lserver = server;
 			}
 		}
 		track.stop();
-		ToneGenerator tg = new ToneGenerator(AudioManager.STREAM_RING,ToneGenerator.MAX_VOLUME/4*3);
+		saveVolume();
+		setStreamVolume(AudioManager.STREAM_MUSIC,oldvol,0);
+		restoreSettings();
+		setStreamVolume(AudioManager.STREAM_MUSIC,oldvol,0);
+		tg.stopTone();
+		tg = new ToneGenerator(AudioManager.STREAM_RING,ToneGenerator.MAX_VOLUME/4*3);
 		tg.startTone(ToneGenerator.TONE_PROP_PROMPT);
 		try {
-			Thread.sleep(500);
+			sleep(500);
 		} catch (InterruptedException e) {
 		}
 		tg.stopTone();
-		rtpSession = null;
-		track = null;
-		codec.cleanDecoder(codecCtx);
-		codec = null;
-		println("rtp receiver terminated");
+		
+		rtp_socket.close();
+		rtp_socket = null;
+
+		if (DEBUG)
+			println("rtp receiver terminated");
 	}
 
 	/** Debug output */
-	static int i = 0;
 	private static void println(String str) {
-		System.out.println("RtpStreamReceiver "+ i++ +": " + str);
+		if (!Sipdroid.release) System.out.println("RtpStreamReceiver: " + str);
 	}
 
 	public static int byte2int(byte b) { // return (b>=0)? b : -((b^0xFF)+1);
@@ -362,23 +488,4 @@
 	public static int byte2int(byte b1, byte b2) {
 		return (((b1 + 0x100) % 0x100) << 8) + (b2 + 0x100) % 0x100;
 	}
-
-	@Override
-	public int frameSize(int payloadType) {
-		// TODO Auto-generated method stub
-		return 0;
-	}
-
-	@Override
-	public void receiveData(DataFrame frame, Participant participant) {
-		// TODO Auto-generated method stub
-
-	}
-
-	@Override
-	public void userEvent(int type, Participant[] participant) {
-		// TODO Auto-generated method stub
-
-	}
-
 }