Index: /pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c
===================================================================
--- /pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c	(revision 2037)
+++ /pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c	(revision 2038)
@@ -87,4 +87,6 @@
     pjsua_conf_port_id	    wav_port;
     pj_bool_t		    auto_play;
+    pj_bool_t		    auto_play_hangup;
+    pj_timer_entry	    auto_hangup_timer;
     pj_bool_t		    auto_loop;
     pj_bool_t		    auto_conf;
@@ -445,5 +447,5 @@
 	   OPT_NAMESERVER, OPT_STUN_DOMAIN, OPT_STUN_SRV,
 	   OPT_ADD_BUDDY, OPT_OFFER_X_MS_MSG, OPT_NO_PRESENCE,
-	   OPT_AUTO_ANSWER, OPT_AUTO_HANGUP, OPT_AUTO_PLAY, OPT_AUTO_LOOP,
+	   OPT_AUTO_ANSWER, OPT_AUTO_PLAY, OPT_AUTO_PLAY_HANGUP, OPT_AUTO_LOOP,
 	   OPT_AUTO_CONF, OPT_CLOCK_RATE, OPT_SND_CLOCK_RATE, OPT_STEREO,
 	   OPT_USE_ICE, OPT_USE_SRTP, OPT_SRTP_SECURE,
@@ -502,6 +504,6 @@
 	{ "no-presence", 0, 0, OPT_NO_PRESENCE},
 	{ "auto-answer",1, 0, OPT_AUTO_ANSWER},
-	{ "auto-hangup",1, 0, OPT_AUTO_HANGUP},
 	{ "auto-play",  0, 0, OPT_AUTO_PLAY},
+	{ "auto-play-hangup",0, 0, OPT_AUTO_PLAY_HANGUP},
 	{ "auto-rec",   0, 0, OPT_AUTO_REC},
 	{ "auto-loop",  0, 0, OPT_AUTO_LOOP},
@@ -856,4 +858,8 @@
 	    break;
 
+	case OPT_AUTO_PLAY_HANGUP:
+	    cfg->auto_play_hangup = 1;
+	    break;
+
 	case OPT_AUTO_REC:
 	    cfg->auto_rec = 1;
@@ -1913,4 +1919,11 @@
 	    pjsip_endpt_cancel_timer(endpt, &cd->timer);
 	}
+
+	/* Rewind play file when hangup automatically, 
+	 * since file is not looped
+	 */
+	if (app_config.auto_play_hangup)
+	    pjsua_player_set_pos(app_config.wav_id, 0);
+
 
 	PJ_LOG(3,(THIS_FILE, "Call %d is DISCONNECTED [reason=%d (%s)]", 
@@ -2117,5 +2130,7 @@
 
 	/* Stream a file, if desired */
-	if (app_config.auto_play && app_config.wav_port != PJSUA_INVALID_ID) {
+	if ((app_config.auto_play || app_config.auto_play_hangup) && 
+	    app_config.wav_port != PJSUA_INVALID_ID)
+	{
 	    pjsua_conf_connect(app_config.wav_port, call_info.conf_slot);
 	    connect_sound = PJ_FALSE;
@@ -2388,4 +2403,42 @@
 }
 
+/* Playfile done notification, set timer to hangup calls */
+pj_status_t on_playfile_done(pjmedia_port *port, void *usr_data)
+{
+    pj_time_val delay;
+
+    PJ_UNUSED_ARG(port);
+    PJ_UNUSED_ARG(usr_data);
+
+    /* Just rewind WAV when it is played outside of call */
+    if (pjsua_call_get_count() == 0) {
+	pjsua_player_set_pos(app_config.wav_id, 0);
+	return PJ_SUCCESS;
+    }
+
+    /* Timer is already active */
+    if (app_config.auto_hangup_timer.id == 1)
+	return PJ_SUCCESS;
+
+    app_config.auto_hangup_timer.id = 1;
+    delay.sec = 0;
+    delay.msec = 200; /* Give 200 ms before hangup */
+    pjsip_endpt_schedule_timer(pjsua_get_pjsip_endpt(), 
+			       &app_config.auto_hangup_timer, 
+			       &delay);
+
+    return PJ_SUCCESS;
+}
+
+/* Auto hangup timer callback */
+static void hangup_timeout_callback(pj_timer_heap_t *timer_heap,
+				    struct pj_timer_entry *entry)
+{
+    PJ_UNUSED_ARG(timer_heap);
+    PJ_UNUSED_ARG(entry);
+
+    app_config.auto_hangup_timer.id = 0;
+    pjsua_call_hangup_all();
+}
 
 /*
@@ -3761,6 +3814,10 @@
     for (i=0; i<app_config.wav_count; ++i) {
 	pjsua_player_id wav_id;
-
-	status = pjsua_player_create(&app_config.wav_files[i], 0, 
+	unsigned play_options = 0;
+
+	if (app_config.auto_play_hangup)
+	    play_options |= PJMEDIA_FILE_NO_LOOP;
+
+	status = pjsua_player_create(&app_config.wav_files[i], play_options, 
 				     &wav_id);
 	if (status != PJ_SUCCESS)
@@ -3770,4 +3827,16 @@
 	    app_config.wav_id = wav_id;
 	    app_config.wav_port = pjsua_player_get_conf_port(app_config.wav_id);
+	    if (app_config.auto_play_hangup) {
+		pjmedia_port *port;
+
+		pjsua_player_get_port(app_config.wav_id, &port);
+		status = pjmedia_wav_player_set_eof_cb(port, NULL, 
+						       &on_playfile_done);
+		if (status != PJ_SUCCESS)
+		    goto on_error;
+
+		pj_timer_entry_init(&app_config.auto_hangup_timer, 0, NULL, 
+				    &hangup_timeout_callback);
+	    }
 	}
     }
Index: /pjproject/trunk/pjsip-apps/src/test-pjsua/mod_pesq.py
===================================================================
--- /pjproject/trunk/pjsip-apps/src/test-pjsua/mod_pesq.py	(revision 2038)
+++ /pjproject/trunk/pjsip-apps/src/test-pjsua/mod_pesq.py	(revision 2038)
@@ -0,0 +1,130 @@
+# $Id$
+
+# Quality test of media calls.
+# - UA1 calls UA2
+# - UA1 plays a file until finished to be streamed to UA2
+# - UA2 records from stream
+# - Apply PESQ to played file (reference) and recorded file (degraded)
+#
+# File should be:
+# - naming: xxxxxx.CLOCK_RATE.wav, e.g: test1.8.wav
+# - clock-rate of those files can only be 8khz or 16khz
+
+import time
+import imp
+import sys
+import re
+import subprocess
+import inc_const as const
+
+from inc_cfg import *
+
+# Load configuration
+cfg_file = imp.load_source("cfg_file", sys.argv[2])
+
+# PESQ configs
+# PESQ_THRESHOLD specifies the minimum acceptable PESQ MOS value, so test can be declared successful
+PESQ = "tools/pesq.exe"
+PESQ_THRESHOLD = 1.0
+
+# UserData
+class mod_pesq_user_data:
+	# Sample rate option for PESQ
+	pesq_sample_rate_opt = ""
+	# Input/Reference filename
+	input_filename = ""
+	# Output/Degraded filename
+	output_filename = ""
+
+# Test body function
+def test_func(t, user_data):
+	# module debugging purpose
+	#user_data.pesq_sample_rate_opt = "+16000"
+	#user_data.input_filename = "wavs/input.16.wav"
+	#user_data.output_filename = "wavs/tmp.16.wav"
+	#return
+
+	ua1 = t.process[0]
+	ua2 = t.process[1]
+
+	# Get conference clock rate of UA2 for PESQ sample rate option
+	ua2.send("cl")
+	clock_rate_line = ua2.expect("Port \#00\[\d+KHz")
+	if (clock_rate_line == None):
+		raise TestError("Failed getting")
+	clock_rate = re.match("Port \#00\[(\d+)KHz", clock_rate_line).group(1)
+	user_data.pesq_sample_rate_opt = "+" + clock_rate + "000"
+
+	# Get input file name
+	ua1.sync_stdout()
+	ua1.send("dc")
+	line = ua1.expect(const.MEDIA_PLAY_FILE)
+	user_data.input_filename = re.compile(const.MEDIA_PLAY_FILE).match(line).group(1)
+
+	# Get output file name
+	ua2.sync_stdout()
+	ua2.send("dc")
+	line = ua2.expect(const.MEDIA_REC_FILE)
+	user_data.output_filename = re.compile(const.MEDIA_REC_FILE).match(line).group(1)
+
+	# Find appropriate clock rate for the input file
+	clock_rate = re.compile(".+(\.\d+\.wav)$").match(user_data.output_filename)
+	if (clock_rate==None):
+		raise TestError("Cannot compare input & output, incorrect output filename format")
+	user_data.input_filename = re.sub("\.\d+\.wav$", clock_rate.group(1), user_data.input_filename)
+
+	time.sleep(1)
+	ua1.sync_stdout()
+	ua2.sync_stdout()
+
+	# UA1 making call
+	ua1.send("m")
+	ua1.send(t.inst_params[1].uri)
+	ua1.expect(const.STATE_CALLING)
+	
+	# Auto answer, auto play, auto hangup
+	# Just wait for call disconnected
+
+	if ua1.expect(const.STATE_CONFIRMED, False)==None:
+		raise TestError("Call failed")
+	ua2.expect(const.STATE_CONFIRMED)
+
+	while True:
+		line = ua2.proc.stdout.readline()
+		if line == "":
+			raise TestError(ua2.name + ": Premature EOF")
+		# Search for disconnected text
+		if re.search(const.STATE_DISCONNECTED, line) != None:
+			break
+	
+
+# Post body function
+def post_func(t, user_data):
+	endpt = t.process[0]
+
+	# Execute PESQ
+	fullcmd = PESQ + " " + user_data.pesq_sample_rate_opt + " " + user_data.input_filename + " " + user_data.output_filename
+	endpt.trace("Popen " + fullcmd)
+	pesq_proc = subprocess.Popen(fullcmd, stdout=subprocess.PIPE, universal_newlines=True)
+	pesq_out  = pesq_proc.communicate()
+
+	# Parse ouput
+	mo_pesq_out = re.compile("Prediction\s+:\s+PESQ_MOS\s+=\s+(.+)\s*").search(pesq_out[0])
+	if (mo_pesq_out == None):
+		raise TestError("Failed to fetch PESQ result")
+
+	# Evaluate the similarity value
+	pesq_res = mo_pesq_out.group(1)
+	if (pesq_res >= PESQ_THRESHOLD):
+		endpt.trace("Success, PESQ result=" + pesq_res)
+	else:
+		endpt.trace("Failed, PESQ result=" + pesq_res)
+		raise TestError("WAV seems to be degraded badly")
+
+
+# Here where it all comes together
+test = cfg_file.test_param
+test.test_func = test_func
+test.post_func = post_func
+test.user_data = mod_pesq_user_data()
+
Index: /pjproject/trunk/pjsip-apps/src/test-pjsua/scripts-pesq/100_defaults.py
===================================================================
--- /pjproject/trunk/pjsip-apps/src/test-pjsua/scripts-pesq/100_defaults.py	(revision 2038)
+++ /pjproject/trunk/pjsip-apps/src/test-pjsua/scripts-pesq/100_defaults.py	(revision 2038)
@@ -0,0 +1,12 @@
+# $Id$
+#
+from inc_cfg import *
+
+# Simple call
+test_param = TestParam(
+		"PESQ",
+		[
+			InstanceParam("UA1", "--null-audio --max-calls=1 --play-file wavs/input.16.wav --auto-play-hangup"),
+			InstanceParam("UA2", "--null-audio --max-calls=1 --rec-file  wavs/tmp.16.wav --clock-rate 16000 --auto-answer 200 --auto-rec")
+		]
+		)
