Initial work on pjsua ActiveX component

git-svn-id: https://svn.pjsip.org/repos/pjproject/trunk@487 74dad513-b988-da41-8d7b-12977e46ad98
diff --git a/pjsip/src/pjsua-lib/pjsua_console_app.c b/pjsip/src/pjsua-lib/pjsua_console_app.c
index 62069b9..58f64c7 100644
--- a/pjsip/src/pjsua-lib/pjsua_console_app.c
+++ b/pjsip/src/pjsua-lib/pjsua_console_app.c
@@ -781,7 +781,7 @@
 		    pjsua_buddy_subscribe_pres(result.nb_result-1, (menuin[0]=='s'));
 		}
 
-		pjsua_pres_refresh(current_acc);
+		pjsua_pres_refresh();
 
 	    } else if (result.uri_result) {
 		puts("Sorry, can only subscribe to buddy's presence, "
@@ -814,7 +814,7 @@
 	    printf("Setting %s online status to %s\n",
 		   acc_info.acc_id.ptr,
 		   (acc_info.online_status?"online":"offline"));
-	    pjsua_pres_refresh(current_acc);
+	    pjsua_pres_refresh();
 	    break;
 
 	case 'c':
@@ -971,59 +971,6 @@
 
 
 /*****************************************************************************
- * Console application custom logging:
- */
-
-
-static FILE *log_file;
-
-
-static void app_log_writer(int level, const char *buffer, int len)
-{
-    /* Write to both stdout and file. */
-
-    if (level <= (int)pjsua_get_config()->app_log_level)
-	pj_log_write(level, buffer, len);
-
-    if (log_file) {
-	fwrite(buffer, len, 1, log_file);
-	fflush(log_file);
-    }
-}
-
-
-pj_status_t pjsua_console_app_logging_init(const pjsua_config *cfg)
-{
-    /* Redirect log function to ours */
-
-    pj_log_set_log_func( &app_log_writer );
-
-    /* If output log file is desired, create the file: */
-
-    if (cfg->log_filename.slen) {
-	log_file = fopen(cfg->log_filename.ptr, "wt");
-	if (log_file == NULL) {
-	    PJ_LOG(1,(THIS_FILE, "Unable to open log file %s", 
-		      cfg->log_filename.ptr));   
-	    return -1;
-	}
-    }
-
-    return PJ_SUCCESS;
-}
-
-
-void pjsua_console_app_logging_shutdown(void)
-{
-    /* Close logging file, if any: */
-
-    if (log_file) {
-	fclose(log_file);
-	log_file = NULL;
-    }
-}
-
-/*****************************************************************************
  * Error display:
  */
 
diff --git a/pjsip/src/pjsua-lib/pjsua_core.c b/pjsip/src/pjsua-lib/pjsua_core.c
index 3ec5947..3f63ce8 100644
--- a/pjsip/src/pjsua-lib/pjsua_core.c
+++ b/pjsip/src/pjsua-lib/pjsua_core.c
@@ -51,6 +51,8 @@
     pj_memset(cfg, 0, sizeof(pjsua_config));
 
     cfg->thread_cnt = 1;
+    cfg->media_has_ioqueue = 1;
+    cfg->media_thread_cnt = 1;
     cfg->udp_port = 5060;
     cfg->start_rtp_port = 4000;
     cfg->max_calls = 4;
@@ -246,6 +248,25 @@
     return 0;
 }
 
+/**
+ * Poll pjsua.
+ */
+PJ_DECL(int) pjsua_handle_events(unsigned msec_timeout)
+{
+    unsigned count = 0;
+    pj_time_val tv;
+    pj_status_t status;
+
+    tv.sec = 0;
+    tv.msec = msec_timeout;
+    pj_time_val_normalize(&tv);
+
+    status = pjsip_endpt_handle_events2(pjsua.endpt, &tv, &count);
+    if (status != PJ_SUCCESS)
+	return -status;
+
+    return count;
+}
 
 
 #define pjsua_has_stun()    (pjsua.config.stun_port1 && \
@@ -504,7 +525,9 @@
 
     /* Must create media endpoint too */
     status = pjmedia_endpt_create(&pjsua.cp.factory, 
-				  pjsip_endpt_get_ioqueue(pjsua.endpt), 0,
+				  pjsua.config.media_has_ioqueue? NULL :
+				       pjsip_endpt_get_ioqueue(pjsua.endpt), 
+				  pjsua.config.media_thread_cnt,
 				  &pjsua.med_endpt);
     if (status != PJ_SUCCESS) {
 	pjsua_perror(THIS_FILE, 
@@ -754,6 +777,57 @@
 }
 
 
+/*****************************************************************************
+ * Console application custom logging:
+ */
+
+
+static void log_writer(int level, const char *buffer, int len)
+{
+    /* Write to both stdout and file. */
+
+    if (level <= (int)pjsua.config.app_log_level)
+	pj_log_write(level, buffer, len);
+
+    if (pjsua.log_file) {
+	fwrite(buffer, len, 1, pjsua.log_file);
+	fflush(pjsua.log_file);
+    }
+}
+
+
+static pj_status_t logging_init()
+{
+    /* Redirect log function to ours */
+
+    pj_log_set_log_func( &log_writer );
+
+    /* If output log file is desired, create the file: */
+
+    if (pjsua.config.log_filename.slen) {
+	pjsua.log_file = fopen(pjsua.config.log_filename.ptr, "wt");
+	if (pjsua.log_file == NULL) {
+	    PJ_LOG(1,(THIS_FILE, "Unable to open log file %s", 
+		      pjsua.config.log_filename.ptr));   
+	    return -1;
+	}
+    }
+
+    return PJ_SUCCESS;
+}
+
+
+static void logging_shutdown(void)
+{
+    /* Close logging file, if any: */
+
+    if (pjsua.log_file) {
+	fclose(pjsua.log_file);
+	pjsua.log_file = NULL;
+    }
+}
+
+
 /*
  * Initialize pjsua application.
  * This will initialize all libraries, create endpoint instance, and register
@@ -807,6 +881,10 @@
     pj_log_set_level(pjsua.config.log_level);
     pj_log_set_decor(pjsua.config.log_decor);
 
+    status = logging_init();
+    if (status != PJ_SUCCESS)
+	goto on_error;
+
 
     /* Create SIP UDP socket */
     if (pjsua.config.udp_port) {
@@ -853,7 +931,7 @@
 	    goto on_error;
 	}
 	status = pjmedia_transport_udp_attach(pjsua.med_endpt, NULL,
-					      &pjsua.calls[i].skinfo,
+					      &pjsua.calls[i].skinfo, 0,
 					      &pjsua.calls[i].med_tp);
     }
 
@@ -1368,7 +1446,7 @@
 /**
  * Get conference port associated with player.
  */
-PJ_DEF(unsigned) pjsua_player_get_conf_port(pjsua_player_id id)
+PJ_DEF(int) pjsua_player_get_conf_port(pjsua_player_id id)
 {
     PJ_ASSERT_RETURN(id>=0 && id < PJ_ARRAY_SIZE(pjsua.player), PJ_EINVAL);
     return pjsua.player[id].slot;
@@ -1452,7 +1530,7 @@
 /**
  * Get conference port associated with recorder.
  */
-PJ_DEF(unsigned) pjsua_recorder_get_conf_port(pjsua_recorder_id id)
+PJ_DEF(int) pjsua_recorder_get_conf_port(pjsua_recorder_id id)
 {
     PJ_ASSERT_RETURN(id>=0 && id < PJ_ARRAY_SIZE(pjsua.recorder), PJ_EINVAL);
     return pjsua.recorder[id].slot;
@@ -1521,19 +1599,6 @@
     /* Signal threads to quit: */
     pjsua.quit_flag = 1;
 
-    /* Terminate all calls. */
-    pjsua_call_hangup_all();
-
-    /* Terminate all presence subscriptions. */
-    pjsua_pres_shutdown();
-
-    /* Unregister, if required: */
-    for (i=0; i<(int)pjsua.config.acc_cnt; ++i) {
-	if (pjsua.acc[i].regc) {
-	    pjsua_acc_set_registration(i, PJ_FALSE);
-	}
-    }
-
     /* Wait worker threads to quit: */
     for (i=0; i<(int)pjsua.config.thread_cnt; ++i) {
 	
@@ -1544,9 +1609,22 @@
 	}
     }
 
-
-    /* Wait for some time to allow unregistration to complete: */
+    
     if (pjsua.endpt) {
+	/* Terminate all calls. */
+	pjsua_call_hangup_all();
+
+	/* Terminate all presence subscriptions. */
+	pjsua_pres_shutdown();
+
+	/* Unregister, if required: */
+	for (i=0; i<(int)pjsua.config.acc_cnt; ++i) {
+	    if (pjsua.acc[i].regc) {
+		pjsua_acc_set_registration(i, PJ_FALSE);
+	    }
+	}
+
+	/* Wait for some time to allow unregistration to complete: */
 	PJ_LOG(4,(THIS_FILE, "Shutting down..."));
 	busy_sleep(1000);
     }
@@ -1629,6 +1707,11 @@
     pj_caching_pool_destroy(&pjsua.cp);
 
 
+    PJ_LOG(4,(THIS_FILE, "PJSUA destroyed..."));
+
+    /* End logging */
+    logging_shutdown();
+
     /* Done. */
 
     return PJ_SUCCESS;
diff --git a/pjsip/src/pjsua-lib/pjsua_imp.h b/pjsip/src/pjsua-lib/pjsua_imp.h
index 208c999..ec1918d 100644
--- a/pjsip/src/pjsua-lib/pjsua_imp.h
+++ b/pjsip/src/pjsua-lib/pjsua_imp.h
@@ -126,6 +126,9 @@
     /* Config: */
     pjsua_config    config;	    /**< PJSUA configs			*/
 
+    /* Log file: */
+    FILE	   *log_file;	    /**< Log file.			*/
+
     /* Application callback
     : */
     pjsua_callback  cb;		    /**< Application callback.		*/
diff --git a/pjsip/src/pjsua-lib/pjsua_pres.c b/pjsip/src/pjsua-lib/pjsua_pres.c
index fe6eedc..c76d3cb 100644
--- a/pjsip/src/pjsua-lib/pjsua_pres.c
+++ b/pjsip/src/pjsua-lib/pjsua_pres.c
@@ -471,6 +471,7 @@
 	info->status_text = pj_str("Offline");
     }
 
+    info->acc_index = buddy->acc_index;
     return PJ_SUCCESS;
 }
 
@@ -549,10 +550,14 @@
 /*
  * Refresh presence
  */
-PJ_DEF(void) pjsua_pres_refresh(int acc_index)
+PJ_DEF(void) pjsua_pres_refresh()
 {
+    unsigned i;
+
     refresh_client_subscription();
-    refresh_server_subscription(acc_index);
+
+    for (i=0; i<PJ_ARRAY_SIZE(pjsua.acc); ++i)
+	refresh_server_subscription(i);
 }
 
 
@@ -572,9 +577,7 @@
 	pjsua.buddies[i].monitor = 0;
     }
 
-    for (acc_index=0; acc_index<(int)pjsua.config.acc_cnt; ++acc_index) {
-	pjsua_pres_refresh(acc_index);
-    }
+    pjsua_pres_refresh();
 }
 
 /*
diff --git a/pjsip/src/pjsua-lib/pjsua_reg.c b/pjsip/src/pjsua-lib/pjsua_reg.c
index 3774740..f85bcd7 100644
--- a/pjsip/src/pjsua-lib/pjsua_reg.c
+++ b/pjsip/src/pjsua-lib/pjsua_reg.c
@@ -132,7 +132,7 @@
 /*
  * Update registration. If renew is false, then unregistration will be performed.
  */
-PJ_DECL(void) pjsua_acc_set_registration(unsigned acc_index, pj_bool_t renew)
+PJ_DECL(pj_status_t) pjsua_acc_set_registration(unsigned acc_index, pj_bool_t renew)
 {
     pj_status_t status = 0;
     pjsip_tx_data *tdata = 0;
@@ -143,11 +143,11 @@
 	    if (status != PJ_SUCCESS) {
 		pjsua_perror(THIS_FILE, "Unable to create registration", 
 			     status);
-		return;
+		return PJ_EINVALIDOP;
 	    }
 	}
 	if (!pjsua.acc[acc_index].regc)
-	    return;
+	    return PJ_EINVALIDOP;
 
 	status = pjsip_regc_register(pjsua.acc[acc_index].regc, 1, 
 				     &tdata);
@@ -155,7 +155,7 @@
     } else {
 	if (pjsua.acc[acc_index].regc == NULL) {
 	    PJ_LOG(3,(THIS_FILE, "Currently not registered"));
-	    return;
+	    return PJ_EINVALIDOP;
 	}
 	status = pjsip_regc_unregister(pjsua.acc[acc_index].regc, &tdata);
     }
@@ -170,6 +170,8 @@
 	PJ_LOG(3,(THIS_FILE, "%s sent",
 	         (renew? "Registration" : "Unregistration")));
     }
+
+    return status;
 }
 
 /*
diff --git a/pjsip/src/pjsua-lib/pjsua_settings.c b/pjsip/src/pjsua-lib/pjsua_settings.c
index b0cd855..be61535 100644
--- a/pjsip/src/pjsua-lib/pjsua_settings.c
+++ b/pjsip/src/pjsua-lib/pjsua_settings.c
@@ -685,9 +685,13 @@
     return buf;
 }
 
-static void dump_media_session(pjmedia_session *session)
+static void dump_media_session(const char *indent, 
+			       char *buf, unsigned maxlen,
+			       pjmedia_session *session)
 {
     unsigned i;
+    char *p = buf, *end = buf+maxlen;
+    int len;
     pjmedia_session_info info;
 
     pjmedia_session_get_info(session, &info);
@@ -715,15 +719,22 @@
 	    dir = "inactive";
 
 	
-	PJ_LOG(3,(THIS_FILE, 
-		  "%s#%d %.*s @%dKHz, %s, peer=%s:%d",
-		  "               ",
-		  i,
+	len = pj_ansi_snprintf(buf, end-p, 
+		  "%s  #%d %.*s @%dKHz, %s, peer=%s:%d",
+		  indent, i,
 		  info.stream_info[i].fmt.encoding_name.slen,
 		  info.stream_info[i].fmt.encoding_name.ptr,
 		  info.stream_info[i].fmt.clock_rate / 1000,
 		  dir,
-		  rem_addr, rem_port));
+		  rem_addr, rem_port);
+	if (len < 1 || len > end-p) {
+	    *p = '\0';
+	    return;
+	}
+
+	p += len;
+	*p++ = '\n';
+	*p = '\0';
 
 	if (stat.rx.update_cnt == 0)
 	    strcpy(last_update, "never");
@@ -737,39 +748,48 @@
 		    now.msec);
 	}
 
-	PJ_LOG(3,(THIS_FILE, 
-	       "                  RX pt=%d, stat last update: %s\n"
-	       "                     total %spkt %sB (%sB +IP hdr)%s\n"
-	       "                     pkt loss=%d (%3.1f%%), dup=%d (%3.1f%%), reorder=%d (%3.1f%%)%s\n"
-	       "                           (msec)    min     avg     max     last\n"
-	       "                     loss period: %7.3f %7.3f %7.3f %7.3f%s\n"
-	       "                     jitter     : %7.3f %7.3f %7.3f %7.3f%s",
-	       info.stream_info[i].fmt.pt,
+	len = pj_ansi_snprintf(p, end-p,
+	       "%s     RX pt=%d, stat last update: %s\n"
+	       "%s        total %spkt %sB (%sB +IP hdr)\n"
+	       "%s        pkt loss=%d (%3.1f%%), dup=%d (%3.1f%%), reorder=%d (%3.1f%%)\n"
+	       "%s              (msec)    min     avg     max     last\n"
+	       "%s        loss period: %7.3f %7.3f %7.3f %7.3f\n"
+	       "%s        jitter     : %7.3f %7.3f %7.3f %7.3f%s",
+	       indent, info.stream_info[i].fmt.pt,
 	       last_update,
+	       indent,
 	       good_number(packets, stat.rx.pkt),
 	       good_number(bytes, stat.rx.bytes),
 	       good_number(ipbytes, stat.rx.bytes + stat.rx.pkt * 32),
-	       "",
+	       indent,
 	       stat.rx.loss,
 	       stat.rx.loss * 100.0 / stat.rx.pkt,
 	       stat.rx.dup, 
 	       stat.rx.dup * 100.0 / stat.rx.pkt,
 	       stat.rx.reorder, 
 	       stat.rx.reorder * 100.0 / stat.rx.pkt,
-	       "",
+	       indent, indent,
 	       stat.rx.loss_period.min / 1000.0, 
 	       stat.rx.loss_period.avg / 1000.0, 
 	       stat.rx.loss_period.max / 1000.0,
 	       stat.rx.loss_period.last / 1000.0,
-	       "",
+	       indent,
 	       stat.rx.jitter.min / 1000.0,
 	       stat.rx.jitter.avg / 1000.0,
 	       stat.rx.jitter.max / 1000.0,
 	       stat.rx.jitter.last / 1000.0,
 	       ""
-	       ));
+	       );
 
+	if (len < 1 || len > end-p) {
+	    *p = '\0';
+	    return;
+	}
 
+	p += len;
+	*p++ = '\n';
+	*p = '\0';
+	
 	if (stat.tx.update_cnt == 0)
 	    strcpy(last_update, "never");
 	else {
@@ -782,60 +802,152 @@
 		    now.msec);
 	}
 
-	PJ_LOG(3,(THIS_FILE,
-	       "                  TX pt=%d, ptime=%dms, stat last update: %s\n"
-	       "                     total %spkt %sB (%sB +IP hdr)%s\n"
-	       "                     pkt loss=%d (%3.1f%%), dup=%d (%3.1f%%), reorder=%d (%3.1f%%)%s\n"
-	       "                           (msec)    min     avg     max     last\n"
-	       "                     loss period: %7.3f %7.3f %7.3f %7.3f%s\n"
-	       "                     jitter     : %7.3f %7.3f %7.3f %7.3f%s",
+	len = pj_ansi_snprintf(p, end-p,
+	       "%s     TX pt=%d, ptime=%dms, stat last update: %s\n"
+	       "%s        total %spkt %sB (%sB +IP hdr)\n"
+	       "%s        pkt loss=%d (%3.1f%%), dup=%d (%3.1f%%), reorder=%d (%3.1f%%)\n"
+	       "%s              (msec)    min     avg     max     last\n"
+	       "%s        loss period: %7.3f %7.3f %7.3f %7.3f\n"
+	       "%s        jitter     : %7.3f %7.3f %7.3f %7.3f%s",
+	       indent,
 	       info.stream_info[i].tx_pt,
 	       info.stream_info[i].param->info.frm_ptime *
 		info.stream_info[i].param->setting.frm_per_pkt,
 	       last_update,
+
+	       indent,
 	       good_number(packets, stat.tx.pkt),
 	       good_number(bytes, stat.tx.bytes),
 	       good_number(ipbytes, stat.tx.bytes + stat.tx.pkt * 32),
-	       "",
+
+	       indent,
 	       stat.tx.loss,
 	       stat.tx.loss * 100.0 / stat.tx.pkt,
 	       stat.tx.dup, 
 	       stat.tx.dup * 100.0 / stat.tx.pkt,
 	       stat.tx.reorder, 
 	       stat.tx.reorder * 100.0 / stat.tx.pkt,
-	       "",
+
+	       indent, indent,
 	       stat.tx.loss_period.min / 1000.0, 
 	       stat.tx.loss_period.avg / 1000.0, 
 	       stat.tx.loss_period.max / 1000.0,
 	       stat.tx.loss_period.last / 1000.0,
-	       "",
+	       indent,
 	       stat.tx.jitter.min / 1000.0,
 	       stat.tx.jitter.avg / 1000.0,
 	       stat.tx.jitter.max / 1000.0,
 	       stat.tx.jitter.last / 1000.0,
 	       ""
-	       ));
+	       );
 
+	if (len < 1 || len > end-p) {
+	    *p = '\0';
+	    return;
+	}
 
-	PJ_LOG(3,(THIS_FILE,
-	       "                 RTT msec       : %7.3f %7.3f %7.3f %7.3f%s", 
+	p += len;
+	*p++ = '\n';
+	*p = '\0';
+
+	len = pj_ansi_snprintf(p, end-p,
+	       "%s    RTT msec       : %7.3f %7.3f %7.3f %7.3f", 
+	       indent,
 	       stat.rtt.min / 1000.0,
 	       stat.rtt.avg / 1000.0,
 	       stat.rtt.max / 1000.0,
-	       stat.rtt.last / 1000.0,
-	       ""
-	       ));
+	       stat.rtt.last / 1000.0
+	       );
+	if (len < 1 || len > end-p) {
+	    *p = '\0';
+	    return;
+	}
 
+	p += len;
+	*p++ = '\n';
+	*p = '\0';
     }
 }
 
+PJ_DEF(void) pjsua_dump_call(int call_index, int with_media, 
+			     char *buffer, unsigned maxlen,
+			     const char *indent)
+{
+    pjsua_call *call = &pjsua.calls[call_index];
+    pj_time_val duration, res_delay, con_delay;
+    char tmp[128];
+    char *p, *end;
+    int len;
+
+    *buffer = '\0';
+    p = buffer;
+    end = buffer + maxlen;
+    len = 0;
+
+    PJ_ASSERT_ON_FAIL(call_index >= 0 && 
+		      call_index < PJ_ARRAY_SIZE(pjsua.calls), return);
+
+    if (call->inv == NULL)
+	return;
+
+    print_call(indent, call_index, tmp, sizeof(tmp));
+    
+    len = pj_ansi_strlen(tmp);
+    pj_ansi_strcpy(buffer, tmp);
+
+    p += len;
+    *p++ = '\r';
+    *p++ = '\n';
+
+    /* Calculate call duration */
+    if (call->inv->state >= PJSIP_INV_STATE_CONFIRMED) {
+	pj_gettimeofday(&duration);
+	PJ_TIME_VAL_SUB(duration, call->conn_time);
+	con_delay = call->conn_time;
+	PJ_TIME_VAL_SUB(con_delay, call->start_time);
+    } else {
+	duration.sec = duration.msec = 0;
+	con_delay.sec = con_delay.msec = 0;
+    }
+
+    /* Calculate first response delay */
+    if (call->inv->state >= PJSIP_INV_STATE_EARLY) {
+	res_delay = call->res_time;
+	PJ_TIME_VAL_SUB(res_delay, call->start_time);
+    } else {
+	res_delay.sec = res_delay.msec = 0;
+    }
+
+    /* Print duration */
+    len = pj_ansi_snprintf(p, end-p, 
+		           "%s  Call time: %02dh:%02dm:%02ds, "
+		           "1st res in %d ms, conn in %dms",
+			   indent,
+		           (duration.sec / 3600),
+		           ((duration.sec % 3600)/60),
+		           (duration.sec % 60),
+		           PJ_TIME_VAL_MSEC(res_delay), 
+		           PJ_TIME_VAL_MSEC(con_delay));
+    
+    if (len > 0 && len < end-p) {
+	p += len;
+	*p++ = '\n';
+	*p = '\0';
+    }
+
+    /* Dump session statistics */
+    if (with_media && call->session)
+	dump_media_session(indent, p, end-p, call->session);
+
+}
+
 /*
  * Dump application states.
  */
 PJ_DEF(void) pjsua_dump(pj_bool_t detail)
 {
-    char buf[128];
     unsigned old_decor;
+    char buf[1024];
 
     PJ_LOG(3,(THIS_FILE, "Start dumping application states:"));
 
@@ -862,48 +974,10 @@
 	unsigned i;
 
 	for (i=0; i<pjsua.config.max_calls; ++i) {
-
-	    pjsua_call *call = &pjsua.calls[i];
-	    pj_time_val duration, res_delay, con_delay;
-
-	    if (call->inv == NULL)
-		continue;
-
-	    print_call("  ", i, buf, sizeof(buf));
-	    PJ_LOG(3,(THIS_FILE, "%s", buf));
-
-	    /* Calculate call duration */
-	    if (call->inv->state >= PJSIP_INV_STATE_CONFIRMED) {
-		pj_gettimeofday(&duration);
-		PJ_TIME_VAL_SUB(duration, call->conn_time);
-		con_delay = call->conn_time;
-		PJ_TIME_VAL_SUB(con_delay, call->start_time);
-	    } else {
-		duration.sec = duration.msec = 0;
-		con_delay.sec = con_delay.msec = 0;
+	    if (pjsua.calls[i].inv) {
+		pjsua_dump_call(i, detail, buf, sizeof(buf), "  ");
+		PJ_LOG(3,(THIS_FILE, "%s", buf));
 	    }
-
-	    /* Calculate first response delay */
-	    if (call->inv->state >= PJSIP_INV_STATE_EARLY) {
-		res_delay = call->res_time;
-		PJ_TIME_VAL_SUB(res_delay, call->start_time);
-	    } else {
-		res_delay.sec = res_delay.msec = 0;
-	    }
-
-	    /* Print duration */
-	    PJ_LOG(3,(THIS_FILE, 
-		      "               Call time: %02dh:%02dm:%02ds, "
-		      "1st res in %d ms, conn in %dms",
-		      (duration.sec / 3600),
-		      ((duration.sec % 3600)/60),
-		      (duration.sec % 60),
-		      PJ_TIME_VAL_MSEC(res_delay), 
-		      PJ_TIME_VAL_MSEC(con_delay)));
-
-	    /* Dump session statistics */
-	    if (call->session)
-		dump_media_session(call->session);
 	}
     }
 
@@ -924,7 +998,7 @@
     int argc = 3;
     char *argv[4] = { "pjsua", "--config-file", NULL, NULL};
 
-    argv[3] = (char*)filename;
+    argv[2] = (char*)filename;
     return pjsua_parse_args(argc, argv, cfg);
 }
 
@@ -1103,12 +1177,16 @@
 
 
     /* Encoding quality and complexity */
-    pj_ansi_sprintf(line, "--quality %d\n",
-		    config->quality);
-    pj_strcat2(&cfg, line);
-    pj_ansi_sprintf(line, "--complexity %d\n",
-		    config->complexity);
-    pj_strcat2(&cfg, line);
+    if (config->quality > 0) {
+	pj_ansi_sprintf(line, "--quality %d\n",
+			config->quality);
+	pj_strcat2(&cfg, line);
+    }
+    if (config->complexity > 0) {
+	pj_ansi_sprintf(line, "--complexity %d\n",
+			config->complexity);
+	pj_strcat2(&cfg, line);
+    }
 
     /* ptime */
     if (config->ptime) {