Index: /pjproject/trunk/pjlib/src/pj/config.c
===================================================================
--- /pjproject/trunk/pjlib/src/pj/config.c	(revision 222)
+++ /pjproject/trunk/pjlib/src/pj/config.c	(revision 223)
@@ -22,5 +22,5 @@
 
 static const char *id = "config.c";
-const char *PJ_VERSION = "0.5.1.1";
+const char *PJ_VERSION = "0.5.1.2";
 
 PJ_DEF(void) pj_dump_config(void)
Index: /pjproject/trunk/pjmedia/src/pjmedia/conference.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia/conference.c	(revision 222)
+++ /pjproject/trunk/pjmedia/src/pjmedia/conference.c	(revision 223)
@@ -54,4 +54,5 @@
     pjmedia_port_op	 rx_setting;	/**< Can we receive from this port  */
     pjmedia_port_op	 tx_setting;	/**< Can we transmit to this port   */
+    int			 listener_cnt;	/**< Number of listeners.	    */
     pj_bool_t		*listeners;	/**< Array of listeners.	    */
     pjmedia_vad		*vad;		/**< VAD for this port.		    */
@@ -468,4 +469,5 @@
 	src_port->listeners[sink_slot] = 1;
 	++conf->connect_cnt;
+	++src_port->listener_cnt;
 
 	if (conf->connect_cnt == 1)
@@ -506,4 +508,5 @@
 	src_port->listeners[sink_slot] = 0;
 	--conf->connect_cnt;
+	--src_port->listener_cnt;
 
 	PJ_LOG(4,(THIS_FILE,"Port %.*s stop transmitting to port %.*s",
@@ -557,4 +560,5 @@
 	if (conf_port->listeners[port] != 0) {
 	    --conf->connect_cnt;
+	    --conf_port->listener_cnt;
 	    conf_port->listeners[port] = 0;
 	}
@@ -564,6 +568,8 @@
     conf_port = conf->ports[port];
     for (i=0; i<conf->max_ports; ++i) {
-	if (conf_port->listeners[i])
+	if (conf_port->listeners[i]) {
 	    --conf->connect_cnt;
+	    --conf_port->listener_cnt;
+	}
     }
 
@@ -694,12 +700,15 @@
 
 	/* Get frame from this port. 
-	 * If port has rx_buffer, then get the frame from the rx_buffer
-	 * instead.
+	 * If port has rx_buffer (e.g. sound port), then get the frame 
+	 * from the rx_buffer instead.
 	 */
-	if (i==0/*conf_port->cur_rx_buf*/) {
+	if (i==0) {
 	    pj_int16_t *rx_buf;
 
-	    if (conf_port->rx_read == conf_port->rx_write)
-		conf_port->rx_read = (conf_port->rx_write+RX_BUF_COUNT-RX_BUF_COUNT/2) % RX_BUF_COUNT;
+	    if (conf_port->rx_read == conf_port->rx_write) {
+		conf_port->rx_read = 
+		    (conf_port->rx_write+RX_BUF_COUNT-RX_BUF_COUNT/2) % 
+			RX_BUF_COUNT;
+	    }
 
 	    rx_buf = conf_port->rx_buf[conf_port->rx_read];
@@ -708,4 +717,5 @@
 	    }
 	    conf_port->rx_read = (conf_port->rx_read+1) % RX_BUF_COUNT;
+
 	} else {
 	    pjmedia_frame frame;
@@ -715,8 +725,15 @@
 	    frame.size = size;
 	    pjmedia_port_get_frame(conf_port->port, &frame);
+
+	    if (frame.type == PJMEDIA_FRAME_TYPE_NONE)
+		continue;
 	}
 
 	/* Skip (after receiving the frame) if this port is muted. */
 	if (conf_port->rx_setting == PJMEDIA_PORT_MUTE)
+	    continue;
+
+	/* Also skip if this port doesn't have listeners. */
+	if (conf_port->listener_cnt == 0)
 	    continue;
 
@@ -728,8 +745,8 @@
 
 	/* Skip if we don't have signal. */
-	if (silence) {
-	    TRACE_(("sil:%d ", i));
-	    continue;
-	}
+	//if (silence) {
+	//    TRACE_(("sil:%d ", i));
+	//    continue;
+	//}
 
 	/* Convert the buffer to unsigned value */
@@ -743,5 +760,5 @@
 	    unsigned k;
 
-	    if (conf_port->listeners[j] == 0)
+	    if (listener == 0)
 		continue;
 
@@ -768,4 +785,18 @@
 	if (!conf_port)
 	    continue;
+
+	if (conf_port->tx_setting == PJMEDIA_PORT_MUTE) {
+	    frame.type = PJMEDIA_FRAME_TYPE_NONE;
+	    frame.buf = NULL;
+	    frame.size = 0;
+	    
+	    if (conf_port->port)
+		pjmedia_port_put_frame(conf_port->port, &frame);
+
+	    continue;
+
+	} else if (conf_port->tx_setting != PJMEDIA_PORT_ENABLE) {
+	    continue;
+	}
 
 	//
@@ -780,8 +811,5 @@
 			conf_port->tx_buf2 : conf_port->tx_buf1);
 
-	if (!conf_port->sources) {
-	    for (j=0; j<conf->samples_per_frame; ++j)
-		target_buf[j] = 0;
-	} else {
+	if (conf_port->sources) {
 	    for (j=0; j<conf->samples_per_frame; ++j) {
 		target_buf[j] = unsigned2pcm(conf_port->sum_buf[j] / conf_port->sources);
@@ -792,9 +820,10 @@
 	conf_port->cur_tx_buf = target_buf;
 
-	if (conf_port->tx_setting != PJMEDIA_PORT_ENABLE)
-	    continue;
-
 	pj_memset(&frame, 0, sizeof(frame));
-	frame.type = PJMEDIA_FRAME_TYPE_AUDIO;
+	if (conf_port->sources)
+	    frame.type = PJMEDIA_FRAME_TYPE_AUDIO;
+	else
+	    frame.type = PJMEDIA_FRAME_TYPE_NONE;
+
 	frame.buf = conf_port->cur_tx_buf;
 	frame.size = conf->samples_per_frame * conf->bits_per_sample / 8;
Index: /pjproject/trunk/pjmedia/src/pjmedia/rtp.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia/rtp.c	(revision 222)
+++ /pjproject/trunk/pjmedia/src/pjmedia/rtp.c	(revision 223)
@@ -93,7 +93,15 @@
 	      ses, pt, m, payload_len, ts_len));
 
+    /* Update timestamp */
+    ses->out_hdr.ts = pj_htonl(pj_ntohl(ses->out_hdr.ts)+ts_len);
+
+    /* If payload_len is zero, bail out.
+     * This is a clock frame; we're not really transmitting anything.
+     */
+    if (payload_len == 0)
+	return PJ_SUCCESS;
+
     /* Update session. */
     ses->out_extseq++;
-    ses->out_hdr.ts = pj_htonl(pj_ntohl(ses->out_hdr.ts)+ts_len);
 
     /* Create outgoing header. */
Index: /pjproject/trunk/pjmedia/src/pjmedia/stream.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia/stream.c	(revision 222)
+++ /pjproject/trunk/pjmedia/src/pjmedia/stream.c	(revision 223)
@@ -279,5 +279,5 @@
 					 &rtphdrlen);
 
-    } else {
+    } else if (frame->type != PJMEDIA_FRAME_TYPE_NONE) {
 	unsigned max_size;
 
@@ -297,4 +297,14 @@
 					 (const void**)&rtphdr, 
 					 &rtphdrlen);
+    } else {
+
+	/* Just update RTP session's timestamp. */
+	status = pjmedia_rtp_encode_rtp( &channel->rtp, 
+					 0, 0, 
+					 0, ts_len, 
+					 (const void**)&rtphdr, 
+					 &rtphdrlen);
+	return PJ_SUCCESS;
+
     }
 
Index: /pjproject/trunk/pjsip/include/pjsip-ua/sip_inv.h
===================================================================
--- /pjproject/trunk/pjsip/include/pjsip-ua/sip_inv.h	(revision 222)
+++ /pjproject/trunk/pjsip/include/pjsip-ua/sip_inv.h	(revision 223)
@@ -349,4 +349,16 @@
 				       pjsip_tx_data **p_tdata );
 
+
+/**
+ * Create the initial response message for the incoming INVITE request in
+ * rdata with  status code st_code and optional status text st_text. Use
+ * #pjsip_answer() to create subsequent response message.
+ */
+PJ_DECL(pj_status_t) pjsip_inv_initial_answer(	pjsip_inv_session *inv,
+						pjsip_rx_data *rdata,
+						int st_code,
+						const pj_str_t *st_text,
+						const pjmedia_sdp_session *sdp,
+						pjsip_tx_data **p_tdata);
 
 /**
Index: /pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c	(revision 222)
+++ /pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c	(revision 223)
@@ -880,9 +880,13 @@
 		     PJ_EINVALIDOP);
 
+    /* Lock dialog. */
+    pjsip_dlg_inc_lock(inv->dlg);
+
     /* Create the INVITE request. */
     status = pjsip_dlg_create_request(inv->dlg, &pjsip_invite_method, -1,
 				      &tdata);
     if (status != PJ_SUCCESS)
-	return status;
+	goto on_return;
+
 
     /* If this is the first INVITE, then copy the headers from inv_hdr.
@@ -921,5 +925,5 @@
 	status = pjmedia_sdp_neg_get_neg_local(inv->neg, &offer);
 	if (status != PJ_SUCCESS)
-	    return status;
+	    goto on_return;
 
 	tdata->msg->body = create_sdp_body(tdata->pool, offer);
@@ -946,5 +950,8 @@
     *p_tdata = tdata;
 
-    return PJ_SUCCESS;
+
+on_return:
+    pjsip_dlg_dec_lock(inv->dlg);
+    return status;
 }
 
@@ -1105,75 +1112,9 @@
 static pj_status_t process_answer( pjsip_inv_session *inv,
 				   int st_code,
-				   pjsip_tx_data *tdata )
+				   pjsip_tx_data *tdata,
+				   const pjmedia_sdp_session *local_sdp)
 {
     pj_status_t status;
     pjmedia_sdp_session *sdp = NULL;
-
-    /* Include SDP for 18x and 2xx response. 
-     * Also if SDP negotiator is ready, start negotiation.
-     */
-    if (st_code/10 == 18 || st_code/10 == 20) {
-
-	pjmedia_sdp_neg_state neg_state;
-
-	neg_state = inv->neg ? pjmedia_sdp_neg_get_state(inv->neg) :
-		    PJMEDIA_SDP_NEG_STATE_NULL;
-
-	if (neg_state == PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER) {
-
-	    status = pjmedia_sdp_neg_get_neg_local(inv->neg, &sdp);
-
-	} else if (neg_state == PJMEDIA_SDP_NEG_STATE_WAIT_NEGO &&
-		   pjmedia_sdp_neg_has_local_answer(inv->neg) )
-	{
-
-	    status = inv_negotiate_sdp(inv);
-	    if (status != PJ_SUCCESS)
-		return status;
-	    
-	    status = pjmedia_sdp_neg_get_active_local(inv->neg, &sdp);
-	}
-
-    }
-
-
-
-    /* Include SDP when it's available.
-     * Subsequent response will include this SDP.
-     */
-    if (sdp) {
-	tdata->msg->body = create_sdp_body(tdata->pool, sdp);
-    }
-
-    /* Remove message body if this is a non-2xx final response */
-    if (st_code >= 300)
-	tdata->msg->body = NULL;
-
-
-    return PJ_SUCCESS;
-}
-
-
-/*
- * Answer initial INVITE
- * Re-INVITE will be answered automatically, and will not use this function.
- */ 
-PJ_DEF(pj_status_t) pjsip_inv_answer(	pjsip_inv_session *inv,
-					int st_code,
-					const pj_str_t *st_text,
-					const pjmedia_sdp_session *local_sdp,
-					pjsip_tx_data **p_tdata )
-{
-    pjsip_tx_data *last_res;
-    pj_status_t status;
-
-    /* Verify arguments. */
-    PJ_ASSERT_RETURN(inv && p_tdata, PJ_EINVAL);
-
-    /* Must have INVITE transaction. */
-    PJ_ASSERT_RETURN(inv->invite_tsx, PJ_EBUG);
-
-    /* INVITE transaction MUST have transmitted a response (e.g. 100) */
-    PJ_ASSERT_RETURN(inv->invite_tsx->last_tx, PJ_EINVALIDOP);
 
     /* If local_sdp is specified, then we MUST NOT have answered the
@@ -1199,8 +1140,110 @@
 	if (status != PJ_SUCCESS)
 	    return status;
-    }
-
-
-
+
+    }
+
+
+     /* If SDP negotiator is ready, start negotiation. */
+    if (st_code/100==2 || (st_code/10==18 && st_code!=180)) {
+
+	pjmedia_sdp_neg_state neg_state;
+
+	/* Start nego when appropriate. */
+	neg_state = inv->neg ? pjmedia_sdp_neg_get_state(inv->neg) :
+		    PJMEDIA_SDP_NEG_STATE_NULL;
+
+	if (neg_state == PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER) {
+
+	    status = pjmedia_sdp_neg_get_neg_local(inv->neg, &sdp);
+
+	} else if (neg_state == PJMEDIA_SDP_NEG_STATE_WAIT_NEGO &&
+		   pjmedia_sdp_neg_has_local_answer(inv->neg) )
+	{
+
+	    status = inv_negotiate_sdp(inv);
+	    if (status != PJ_SUCCESS)
+		return status;
+	    
+	    status = pjmedia_sdp_neg_get_active_local(inv->neg, &sdp);
+	}
+    }
+
+    /* Include SDP when it's available for 2xx and 18x (but not 180) response.
+     * Subsequent response will include this SDP.
+     */
+    if (sdp) {
+	tdata->msg->body = create_sdp_body(tdata->pool, sdp);
+    }
+
+
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * Create first response to INVITE
+ */
+PJ_DEF(pj_status_t) pjsip_inv_initial_answer(	pjsip_inv_session *inv,
+						pjsip_rx_data *rdata,
+						int st_code,
+						const pj_str_t *st_text,
+						const pjmedia_sdp_session *sdp,
+						pjsip_tx_data **p_tdata)
+{
+    pjsip_tx_data *tdata;
+    pj_status_t status;
+
+    /* Verify arguments. */
+    PJ_ASSERT_RETURN(inv && p_tdata, PJ_EINVAL);
+
+    /* Must have INVITE transaction. */
+    PJ_ASSERT_RETURN(inv->invite_tsx, PJ_EBUG);
+
+    pjsip_dlg_inc_lock(inv->dlg);
+
+    /* Create response */
+    status = pjsip_dlg_create_response(inv->dlg, rdata, st_code, st_text,
+				       &tdata);
+    if (status != PJ_SUCCESS)
+	goto on_return;
+
+    /* Process SDP in answer */
+    status = process_answer(inv, st_code, tdata, sdp);
+    if (status != PJ_SUCCESS) {
+	pjsip_tx_data_dec_ref(tdata);
+	goto on_return;
+    }
+
+    *p_tdata = tdata;
+
+on_return:
+    pjsip_dlg_dec_lock(inv->dlg);
+    return status;
+}
+
+
+/*
+ * Answer initial INVITE
+ * Re-INVITE will be answered automatically, and will not use this function.
+ */ 
+PJ_DEF(pj_status_t) pjsip_inv_answer(	pjsip_inv_session *inv,
+					int st_code,
+					const pj_str_t *st_text,
+					const pjmedia_sdp_session *local_sdp,
+					pjsip_tx_data **p_tdata )
+{
+    pjsip_tx_data *last_res;
+    pj_status_t status;
+
+    /* Verify arguments. */
+    PJ_ASSERT_RETURN(inv && p_tdata, PJ_EINVAL);
+
+    /* Must have INVITE transaction. */
+    PJ_ASSERT_RETURN(inv->invite_tsx, PJ_EBUG);
+
+    /* INVITE transaction MUST have transmitted a response (e.g. 100) */
+    PJ_ASSERT_RETURN(inv->invite_tsx->last_tx, PJ_EINVALIDOP);
+
+    pjsip_dlg_inc_lock(inv->dlg);
 
     /* Modify last response. */
@@ -1208,16 +1251,20 @@
     status = pjsip_dlg_modify_response(inv->dlg, last_res, st_code, st_text);
     if (status != PJ_SUCCESS)
-	return status;
+	goto on_return;
 
 
     /* Process SDP in answer */
-    status = process_answer(inv, st_code, last_res);
-    if (status != PJ_SUCCESS)
-	return status;
+    status = process_answer(inv, st_code, last_res, local_sdp);
+    if (status != PJ_SUCCESS) {
+	pjsip_tx_data_dec_ref(last_res);
+	goto on_return;
+    }
 
 
     *p_tdata = last_res;
 
-    return PJ_SUCCESS;
+on_return:
+    pjsip_dlg_dec_lock(inv->dlg);
+    return status;
 }
 
@@ -1467,6 +1514,6 @@
 	 * request.
 	 */
-	PJ_ASSERT_RETURN((cseq=pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CSEQ, NULL)) != NULL &&
-			 (cseq->cseq == inv->invite_tsx->cseq),
+	PJ_ASSERT_RETURN((cseq=pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CSEQ, NULL))!=NULL
+			  && (cseq->cseq == inv->invite_tsx->cseq),
 			 PJ_EINVALIDOP);
 
@@ -1625,9 +1672,9 @@
     if (tsx->method.id == PJSIP_INVITE_METHOD) {
 
+	/* Keep the initial INVITE transaction. */
+	if (inv->invite_tsx == NULL)
+	    inv->invite_tsx = tsx;
+
 	if (dlg->role == PJSIP_ROLE_UAC) {
-
-	    /* Keep the initial INVITE transaction. */
-	    if (inv->invite_tsx == NULL)
-		inv->invite_tsx = tsx;
 
 	    switch (tsx->state) {
@@ -1636,5 +1683,5 @@
 		break;
 	    default:
-		pj_assert(!"Unexpected state");
+		inv_on_state_calling(inv, e);
 		break;
 	    }
@@ -1651,5 +1698,6 @@
 		break;
 	    default:
-		pj_assert(!"Unexpected state");
+		inv_on_state_incoming(inv, e);
+		break;
 	    }
 	}
@@ -1675,4 +1723,8 @@
 
 	switch (tsx->state) {
+
+	case PJSIP_TSX_STATE_CALLING:
+	    inv_set_state(inv, PJSIP_INV_STATE_CALLING, e);
+	    break;
 
 	case PJSIP_TSX_STATE_PROCEEDING:
@@ -1807,4 +1859,8 @@
 	switch (tsx->state) {
 
+	case PJSIP_TSX_STATE_TRYING:
+	    inv_set_state(inv, PJSIP_INV_STATE_INCOMING, e);
+	    break;
+
 	case PJSIP_TSX_STATE_PROCEEDING:
 	    /*
@@ -2130,5 +2186,5 @@
 
 	    /* Process SDP in the answer */
-	    status = process_answer(inv, 200, tdata);
+	    status = process_answer(inv, 200, tdata, NULL);
 	    if (status != PJ_SUCCESS)
 		return;
Index: /pjproject/trunk/pjsip/src/pjsua/pjsua.h
===================================================================
--- /pjproject/trunk/pjsip/src/pjsua/pjsua.h	(revision 222)
+++ /pjproject/trunk/pjsip/src/pjsua/pjsua.h	(revision 223)
@@ -122,4 +122,8 @@
     unsigned	     wav_slot;	    /**< WAV player slot in bridge	*/
 
+    /* User Agent behaviour: */
+
+    int		     auto_answer;   /**< Automatically answer in calls.	*/
+
 
     /* Since we support simultaneous calls, we need to have multiple
@@ -179,5 +183,5 @@
 
 
-    /* Misc: */
+    /* Logging: */
     
     int		     log_level;	    /**< Logging verbosity.		*/
Index: /pjproject/trunk/pjsip/src/pjsua/pjsua_inv.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsua/pjsua_inv.c	(revision 222)
+++ /pjproject/trunk/pjsip/src/pjsua/pjsua_inv.c	(revision 223)
@@ -279,7 +279,11 @@
 
 
-    /* Answer with 100 (using the dialog, not invite): */
-
-    status = pjsip_dlg_create_response(dlg, rdata, 100, NULL, &response);
+    /* Must answer with some response to initial INVITE.
+     * If auto-answer flag is set, send 200 straight away, otherwise send 100.
+     */
+    
+    status = pjsip_inv_initial_answer(inv, rdata, 
+				      (pjsua.auto_answer ? 200 : 100), 
+				      NULL, NULL, &response);
     if (status != PJ_SUCCESS) {
 	
@@ -294,19 +298,30 @@
 
     } else {
-	status = pjsip_dlg_send_response(dlg, pjsip_rdata_get_tsx(rdata), 
-					 response);
+	status = pjsip_inv_send_msg(inv, response, NULL);
 	if (status != PJ_SUCCESS)
 	    pjsua_perror(THIS_FILE, "Unable to send 100 response", status);
     }
 
-    PJ_LOG(3,(THIS_FILE,
-	      "\nIncoming call!!\n"
-	      "From: %.*s\n"
-	      "To:   %.*s\n"
-	      "(press 'a' to answer, 'h' to decline)",
-	      (int)dlg->remote.info_str.slen,
-	      dlg->remote.info_str.ptr,
-	      (int)dlg->local.info_str.slen,
-	      dlg->local.info_str.ptr));
+    if (pjsua.auto_answer < 200) {
+	PJ_LOG(3,(THIS_FILE,
+		  "\nIncoming call!!\n"
+		  "From: %.*s\n"
+		  "To:   %.*s\n"
+		  "(press 'a' to answer, 'h' to decline)",
+		  (int)dlg->remote.info_str.slen,
+		  dlg->remote.info_str.ptr,
+		  (int)dlg->local.info_str.slen,
+		  dlg->local.info_str.ptr));
+    } else {
+	PJ_LOG(3,(THIS_FILE,
+		  "Call From:%.*s To:%.*s was answered with %d (%s)",
+		  (int)dlg->remote.info_str.slen,
+		  dlg->remote.info_str.ptr,
+		  (int)dlg->local.info_str.slen,
+		  dlg->local.info_str.ptr,
+		  pjsua.auto_answer,
+		  pjsip_get_status_text(pjsua.auto_answer)->ptr ));
+    }
+
     /* This INVITE request has been handled. */
     return PJ_TRUE;
@@ -767,9 +782,21 @@
     }
 
-    /* Connect new call to the sound device port (port zero) in the
-     * main conference bridge.
-     */
-    pjmedia_conf_connect_port( pjsua.mconf, 0, inv_data->conf_slot);
-    pjmedia_conf_connect_port( pjsua.mconf, inv_data->conf_slot, 0);
+    /* If auto-play is configured, connect the call to the file player 
+     * port 
+     */
+    if (pjsua.wav_file && inv->role == PJSIP_ROLE_UAS) {
+
+	pjmedia_conf_connect_port( pjsua.mconf, pjsua.wav_slot, 
+				   inv_data->conf_slot);
+
+    } else {
+
+	/* Connect new call to the sound device port (port zero) in the
+	 * main conference bridge.
+	 */
+	pjmedia_conf_connect_port( pjsua.mconf, 0, inv_data->conf_slot);
+	pjmedia_conf_connect_port( pjsua.mconf, inv_data->conf_slot, 0);
+    }
+
 
     /* Done. */
Index: /pjproject/trunk/pjsip/src/pjsua/pjsua_opt.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsua/pjsua_opt.c	(revision 222)
+++ /pjproject/trunk/pjsip/src/pjsua/pjsua_opt.c	(revision 223)
@@ -42,33 +42,17 @@
 {
     puts("Usage:");
-    puts("  pjsua [options] [sip-url]");
+    puts("  pjsua [options]");
     puts("");
     puts("  [sip-url]   Default URL to invite.");
     puts("");
     puts("General options:");
+    puts("  --help              Display this help screen");
+    puts("  --version           Display version info");
+    puts("");
+    puts("Logging options:");
     puts("  --config-file=file  Read the config/arguments from file.");
     puts("  --log-file=fname    Log to filename (default stderr)");
     puts("  --log-level=N       Set log max level to N (0(none) to 6(trace))");
     puts("  --app-log-level=N   Set log max level for stdout display to N");
-    puts("  --help              Display this help screen");
-    puts("  --version           Display version info");
-    puts("");
-    puts("Media options:");
-    puts("  --null-audio        Use NULL audio device");
-    puts("  --wav-file=file     Play WAV file in conference bridge");
-    puts("");
-    //puts("");
-    //puts("User Agent options:");
-    //puts("  --auto-answer=sec   Auto-answer all incoming calls after sec seconds.");
-    //puts("  --auto-hangup=sec   Auto-hangup all calls after sec seconds.");
-    puts("");
-    puts("SIP options:");
-    puts("  --local-port=port   Set TCP/UDP port");
-    puts("  --id=url            Set the URL of local ID (used in From header)");
-    puts("  --contact=url       Override the Contact information");
-    puts("  --proxy=url         Set the URL of proxy server");
-    puts("  --outbound=url      Set the URL of outbound proxy server");
-    puts("  --registrar=url     Set the URL of registrar server");
-    puts("  --reg-timeout=secs  Set registration interval to secs (default 3600)");
     puts("");
     puts("Authentication options:");
@@ -77,12 +61,29 @@
     puts("  --password=string   Set authentication password");
     puts("");
-    puts("STUN options (all must be specified):");
+    puts("SIP options:");
+    puts("  --id=url            Set the URL of local ID (used in From header)");
+    puts("  --contact=url       Override the Contact information");
+    puts("  --proxy=url         Set the URL of proxy server");
+    //puts("  --outbound=url      Set the URL of outbound proxy server");
+    puts("");
+    puts("Registration Options:");
+    puts("  --registrar=url     Set the URL of registrar server");
+    puts("  --reg-timeout=secs  Set registration interval to secs (default 3600)");
+    puts("");
+    puts("Transport Options:");
+    puts("  --local-port=port   Set TCP/UDP port");
     puts("  --use-stun1=host[:port]");
     puts("  --use-stun2=host[:port]  Use STUN and set host name and port of STUN servers");
     puts("");
-    puts("SIMPLE options (may be specified more than once):");
+    puts("Media Options:");
+    puts("  --null-audio        Use NULL audio device");
+    //puts("  --wav-file=file     Play WAV file in conference bridge");
+    puts("");
+    puts("Buddy List (can be more than one):");
     puts("  --add-buddy url     Add the specified URL to the buddy list.");
-    //puts("  --offer-x-ms-msg    Offer \"x-ms-message\" in outgoing INVITE");
-    //puts("  --no-presence	Do not subscribe presence of buddies");
+    puts("");
+    puts("User Agent options:");
+    puts("  --auto-answer=code  Automatically answer incoming calls with code (e.g. 200)");
+    puts("  --auto-play=file    Automatically play WAVE file to incoming calls");
     puts("");
     fflush(stdout);
@@ -199,5 +200,5 @@
 	   OPT_USE_STUN1, OPT_USE_STUN2, 
 	   OPT_ADD_BUDDY, OPT_OFFER_X_MS_MSG, OPT_NO_PRESENCE,
-	   OPT_AUTO_ANSWER, OPT_AUTO_HANGUP, OPT_WAV_FILE};
+	   OPT_AUTO_ANSWER, OPT_AUTO_HANGUP, OPT_AUTO_PLAY};
     struct option long_options[] = {
 	{ "config-file",1, 0, OPT_CONFIG_FILE},
@@ -225,5 +226,5 @@
 	{ "auto-answer",1, 0, OPT_AUTO_ANSWER},
 	{ "auto-hangup",1, 0, OPT_AUTO_HANGUP},
-	{ "wav-file",  1, 0, OPT_WAV_FILE},
+	{ "auto-play",  1, 0, OPT_AUTO_PLAY},
 	{ NULL, 0, 0, 0}
     };
@@ -410,6 +411,14 @@
 	    break;
 
-	case OPT_WAV_FILE:
+	case OPT_AUTO_PLAY:
 	    pjsua.wav_file = optarg;
+	    break;
+
+	case OPT_AUTO_ANSWER:
+	    pjsua.auto_answer = atoi(optarg);
+	    if (pjsua.auto_answer < 100 || pjsua.auto_answer > 699) {
+		puts("Error: invalid code in --auto-answer (expecting 100-699");
+		return -1;
+	    }
 	    break;
 	}
