Index: pjproject/trunk/pjsip/src/pjsua/main.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsua/main.c	(revision 230)
+++ pjproject/trunk/pjsip/src/pjsua/main.c	(revision 236)
@@ -24,27 +24,84 @@
 
 /* Current dialog */
-static struct pjsua_inv_data *inv_session;
+static int current_acc;
+static int current_call = -1;
+
+
+/*
+ * Find next call.
+ */
+static pj_bool_t find_next_call(void)
+{
+    int i;
+
+    for (i=current_call+1; i<(int)pjsua.max_calls; ++i) {
+	if (pjsua.calls[i].inv != NULL) {
+	    current_call = i;
+	    return PJ_TRUE;
+	}
+    }
+
+    for (i=0; i<current_call; ++i) {
+	if (pjsua.calls[i].inv != NULL) {
+	    current_call = i;
+	    return PJ_TRUE;
+	}
+    }
+
+    current_call = -1;
+    return PJ_FALSE;
+}
+
+
+/*
+ * Find previous call.
+ */
+static pj_bool_t find_prev_call(void)
+{
+    int i;
+
+    for (i=current_call-1; i>=0; --i) {
+	if (pjsua.calls[i].inv != NULL) {
+	    current_call = i;
+	    return PJ_TRUE;
+	}
+    }
+
+    for (i=pjsua.max_calls-1; i>current_call; --i) {
+	if (pjsua.calls[i].inv != NULL) {
+	    current_call = i;
+	    return PJ_TRUE;
+	}
+    }
+
+    current_call = -1;
+    return PJ_FALSE;
+}
+
+
 
 /*
  * Notify UI when invite state has changed.
  */
-void pjsua_ui_inv_on_state_changed(pjsip_inv_session *inv, pjsip_event *e)
-{
+void pjsua_ui_inv_on_state_changed(int call_index, pjsip_event *e)
+{
+    pjsua_call *call = &pjsua.calls[call_index];
+
     PJ_UNUSED_ARG(e);
 
-    PJ_LOG(3,(THIS_FILE, "INVITE session state changed to %s", 
-	      pjsua_inv_state_names[inv->state]));
-
-    if (inv->state == PJSIP_INV_STATE_DISCONNECTED) {
-	if (inv == inv_session->inv) {
-	    inv_session = inv_session->next;
-	    if (inv_session == &pjsua.inv_list)
-		inv_session = pjsua.inv_list.next;
+    PJ_LOG(3,(THIS_FILE, "Call %d state changed to %s", 
+	      call_index,
+	      pjsua_inv_state_names[call->inv->state]));
+
+    if (call->inv->state == PJSIP_INV_STATE_DISCONNECTED) {
+	call->inv = NULL;
+	if ((int)call->index == current_call) {
+	    find_next_call();
 	}
 
     } else {
 
-	if (inv_session == &pjsua.inv_list || inv_session == NULL)
-	    inv_session = inv->mod_data[pjsua.mod.id];
+	if (call && current_call==-1)
+	    current_call = call->index;
 
     }
@@ -67,8 +124,8 @@
 static void print_buddy_list(void)
 {
-    unsigned i;
+    int i;
 
     puts("Buddy list:");
-    //puts("-------------------------------------------------------------------------------");
+
     if (pjsua.buddy_cnt == 0)
 	puts(" -none-");
@@ -94,24 +151,28 @@
 }
 
+
 /*
- * Show a bit of help.
- */
-static void keystroke_help(void)
+ * Print account status.
+ */
+static void print_acc_status(int acc_index)
 {
     char reg_status[128];
 
-    if (pjsua.regc == NULL) {
+    if (pjsua.acc[acc_index].regc == NULL) {
 	pj_ansi_strcpy(reg_status, " -not registered to server-");
-    } else if (pjsua.regc_last_err != PJ_SUCCESS) {
-	pj_strerror(pjsua.regc_last_err, reg_status, sizeof(reg_status));
-    } else if (pjsua.regc_last_code>=200 && pjsua.regc_last_code<=699) {
+
+    } else if (pjsua.acc[acc_index].reg_last_err != PJ_SUCCESS) {
+	pj_strerror(pjsua.acc[acc_index].reg_last_err, reg_status, sizeof(reg_status));
+
+    } else if (pjsua.acc[acc_index].reg_last_code>=200 && 
+	       pjsua.acc[acc_index].reg_last_code<=699) {
 
 	pjsip_regc_info info;
 
-	pjsip_regc_get_info(pjsua.regc, &info);
+	pjsip_regc_get_info(pjsua.acc[acc_index].regc, &info);
 
 	pj_snprintf(reg_status, sizeof(reg_status),
 		    "%s (%.*s;expires=%d)",
-		    pjsip_get_status_text(pjsua.regc_last_code)->ptr,
+		    pjsip_get_status_text(pjsua.acc[acc_index].reg_last_code)->ptr,
 		    (int)info.client_uri.slen,
 		    info.client_uri.ptr,
@@ -119,10 +180,25 @@
 
     } else {
-	pj_sprintf(reg_status, "in progress (%d)", pjsua.regc_last_code);
-    }
-
-    printf(">>>>\nRegistration status: %s\n", reg_status);
-    printf("Online status: %s\n", 
-	   (pjsua.online_status ? "Online" : "Invisible"));
+	pj_sprintf(reg_status, "in progress (%d)", 
+		   pjsua.acc[acc_index].reg_last_code);
+    }
+
+    printf("[%2d] Registration status: %s\n", acc_index, reg_status);
+    printf("     Online status: %s\n", 
+	   (pjsua.acc[acc_index].online_status ? "Online" : "Invisible"));
+}
+
+/*
+ * Show a bit of help.
+ */
+static void keystroke_help(void)
+{
+    int i;
+
+    printf(">>>>\n");
+
+    for (i=0; i<pjsua.acc_cnt; ++i)
+	print_acc_status(i);
+
     print_buddy_list();
     
@@ -135,5 +211,5 @@
     puts("|  h  Hangup call              |  u  Unsubscribe presence | ru  Unregister    |");
     puts("|  ]  Select next dialog       |  t  ToGgle Online status |  d  Dump status   |");
-    puts("|  [  Select previous dialog   |                          |                   |");
+    puts("|  [  Select previous dialog   |                          | dc  Dump config   |");
     puts("|                              +--------------------------+-------------------+");
     puts("|  H  Hold call                |     Conference Command   |                   |");
@@ -263,5 +339,5 @@
 {
     unsigned i, count;
-    pjmedia_conf_port_info info[16];
+    pjmedia_conf_port_info info[PJSUA_MAX_CALLS];
 
     printf("Conference ports:\n");
@@ -270,10 +346,10 @@
     pjmedia_conf_get_ports_info(pjsua.mconf, &count, info);
     for (i=0; i<count; ++i) {
-	char txlist[80];
-	unsigned j;
+	char txlist[PJSUA_MAX_CALLS*4+10];
+	int j;
 	pjmedia_conf_port_info *port_info = &info[i];	
 	
 	txlist[0] = '\0';
-	for (j=0; j<pjsua.max_ports; ++j) {
+	for (j=0; j<pjsua.max_calls+PJSUA_CONF_MORE_PORTS; ++j) {
 	    char s[10];
 	    if (port_info->listener[j]) {
@@ -310,6 +386,5 @@
 	case 'm':
 	    /* Make call! : */
-	    if (pj_list_size(&pjsua.inv_list))
-		printf("(You have %d calls)\n", pj_list_size(&pjsua.inv_list));
+	    printf("(You currently have %d calls)\n", pjsua.call_cnt);
 	    
 	    ui_input_url("Make call", buf, sizeof(buf), &result);
@@ -318,7 +393,9 @@
 		    puts("You can't do that with make call!");
 		else
-		    pjsua_invite(pjsua.buddies[result.nb_result].uri.ptr, NULL);
+		    pjsua_make_call( current_acc, 
+				     pjsua.buddies[result.nb_result].uri.ptr, 
+				     NULL);
 	    } else if (result.uri_result)
-		pjsua_invite(result.uri_result, NULL);
+		pjsua_make_call( current_acc, result.uri_result, NULL);
 	    
 	    break;
@@ -327,7 +404,7 @@
 	case 'a':
 
-	    if (inv_session == &pjsua.inv_list || 
-		inv_session->inv->role != PJSIP_ROLE_UAS ||
-		inv_session->inv->state >= PJSIP_INV_STATE_CONNECTING) 
+	    if (current_call == -1 || 
+		pjsua.calls[current_call].inv->role != PJSIP_ROLE_UAS ||
+		pjsua.calls[current_call].inv->state >= PJSIP_INV_STATE_CONNECTING)
 	    {
 		puts("No pending incoming call");
@@ -350,5 +427,5 @@
 		 * keyboard input.
 		 */
-		if (inv_session == &pjsua.inv_list) {
+		if (current_call == -1) {
 		    puts("Call has been disconnected");
 		    fflush(stdout);
@@ -356,8 +433,10 @@
 		}
 
-		status = pjsip_inv_answer(inv_session->inv, atoi(buf), 
+		status = pjsip_inv_answer(pjsua.calls[current_call].inv, 
+					  atoi(buf), 
 					  NULL, NULL, &tdata);
 		if (status == PJ_SUCCESS)
-		    status = pjsip_inv_send_msg(inv_session->inv, tdata, NULL);
+		    status = pjsip_inv_send_msg(pjsua.calls[current_call].inv,
+						tdata, NULL);
 
 		if (status != PJ_SUCCESS)
@@ -371,5 +450,5 @@
 	case 'h':
 
-	    if (inv_session == &pjsua.inv_list) {
+	    if (current_call == -1) {
 		puts("No current call");
 		fflush(stdout);
@@ -377,5 +456,5 @@
 
 	    } else {
-		pjsua_inv_hangup(inv_session, PJSIP_SC_DECLINE);
+		pjsua_call_hangup(current_call, PJSIP_SC_DECLINE);
 	    }
 	    break;
@@ -387,20 +466,17 @@
 	     */
 	    if (menuin[0] == ']') {
-		inv_session = inv_session->next;
-		if (inv_session == &pjsua.inv_list)
-		    inv_session = pjsua.inv_list.next;
+		find_next_call();
 
 	    } else {
-		inv_session = inv_session->prev;
-		if (inv_session == &pjsua.inv_list)
-		    inv_session = pjsua.inv_list.prev;
-	    }
-
-	    if (inv_session != &pjsua.inv_list) {
+		find_prev_call();
+	    }
+
+	    if (current_call != -1) {
 		char url[PJSIP_MAX_URL_SIZE];
 		int len;
-
-		len = pjsip_uri_print(0, inv_session->inv->dlg->remote.info->uri,
-				      url, sizeof(url)-1);
+		const pjsip_uri *u;
+
+		u = pjsua.calls[current_call].inv->dlg->remote.info->uri;
+		len = pjsip_uri_print(0, u, url, sizeof(url)-1);
 		if (len < 1) {
 		    pj_ansi_strcpy(url, "<uri is too long>");
@@ -420,7 +496,7 @@
 	     * Hold call.
 	     */
-	    if (inv_session != &pjsua.inv_list) {
+	    if (current_call != -1) {
 		
-		pjsua_inv_set_hold(inv_session);
+		pjsua_call_set_hold(current_call);
 
 	    } else {
@@ -433,7 +509,7 @@
 	     * Send re-INVITE (to release hold, etc).
 	     */
-	    if (inv_session != &pjsua.inv_list) {
+	    if (current_call != -1) {
 		
-		pjsua_inv_reinvite(inv_session);
+		pjsua_call_reinvite(current_call);
 
 	    } else {
@@ -446,10 +522,10 @@
 	     * Transfer call.
 	     */
-	    if (inv_session == &pjsua.inv_list) {
+	    if (current_call == -1) {
 		
 		PJ_LOG(3,(THIS_FILE, "No current call"));
 
 	    } else {
-		struct pjsua_inv_data *cur = inv_session;
+		int call = current_call;
 
 		ui_input_url("Transfer to URL", buf, sizeof(buf), &result);
@@ -457,5 +533,5 @@
 		/* Check if call is still there. */
 
-		if (cur != inv_session) {
+		if (call != current_call) {
 		    puts("Call has been disconnected");
 		    continue;
@@ -466,9 +542,9 @@
 			puts("You can't do that with transfer call!");
 		    else
-			pjsua_inv_xfer_call( inv_session,
-					     pjsua.buddies[result.nb_result].uri.ptr);
+			pjsua_call_xfer( current_call,
+					 pjsua.buddies[result.nb_result].uri.ptr);
 
 		} else if (result.uri_result) {
-		    pjsua_inv_xfer_call( inv_session, result.uri_result);
+		    pjsua_call_xfer( current_call, result.uri_result);
 		}
 	    }
@@ -479,9 +555,9 @@
 	     * Send DTMF strings.
 	     */
-	    if (inv_session == &pjsua.inv_list) {
+	    if (current_call == -1) {
 		
 		PJ_LOG(3,(THIS_FILE, "No current call"));
 
-	    } else if (inv_session->session == NULL) {
+	    } else if (pjsua.calls[current_call].session == NULL) {
 
 		PJ_LOG(3,(THIS_FILE, "Media is not established yet!"));
@@ -489,5 +565,5 @@
 	    } else {
 		pj_str_t digits;
-		struct pjsua_inv_data *cur = inv_session;
+		int call = current_call;
 		pj_status_t status;
 
@@ -498,5 +574,5 @@
 		}
 
-		if (cur != inv_session) {
+		if (call != current_call) {
 		    puts("Call has been disconnected");
 		    continue;
@@ -504,5 +580,5 @@
 
 		digits = pj_str(buf);
-		status = pjmedia_session_dial_dtmf(inv_session->session, 0, 
+		status = pjmedia_session_dial_dtmf(pjsua.calls[current_call].session, 0, 
 						   &digits);
 		if (status != PJ_SUCCESS) {
@@ -522,5 +598,5 @@
 	    if (result.nb_result != NO_NB) {
 		if (result.nb_result == -1) {
-		    unsigned i;
+		    int i;
 		    for (i=0; i<pjsua.buddy_cnt; ++i)
 			pjsua.buddies[i].monitor = (menuin[0]=='s');
@@ -529,5 +605,5 @@
 		}
 
-		pjsua_pres_refresh();
+		pjsua_pres_refresh(current_acc);
 
 	    } else if (result.uri_result) {
@@ -544,5 +620,5 @@
 		 * Re-Register.
 		 */
-		pjsua_regc_update(PJ_TRUE);
+		pjsua_regc_update(current_acc, PJ_TRUE);
 		break;
 	    case 'u':
@@ -550,5 +626,5 @@
 		 * Unregister
 		 */
-		pjsua_regc_update(PJ_FALSE);
+		pjsua_regc_update(current_acc, PJ_FALSE);
 		break;
 	    }
@@ -556,6 +632,7 @@
 	    
 	case 't':
-	    pjsua.online_status = !pjsua.online_status;
-	    pjsua_pres_refresh();
+	    pjsua.acc[current_acc].online_status = 
+		!pjsua.acc[current_acc].online_status;
+	    pjsua_pres_refresh(current_acc);
 	    break;
 
@@ -607,5 +684,18 @@
 
 	case 'd':
-	    pjsua_dump();
+	    if (menuin[1] == 'c') {
+		char settings[2000];
+		int len;
+
+		len = pjsua_dump_settings(settings, sizeof(settings));
+		if (len < 1)
+		    PJ_LOG(3,(THIS_FILE, "Error: not enough buffer"));
+		else
+		    PJ_LOG(3,(THIS_FILE, 
+			      "Dumping configuration (%d bytes):\n%s\n",
+			      len, settings));
+	    } else {
+		pjsua_dump();
+	    }
 	    break;
 
@@ -766,5 +856,4 @@
 
     /* Init default settings. */
-
     pjsua_default();
 
@@ -772,5 +861,4 @@
     /* Initialize pjsua (to create pool etc).
      */
-
     if (pjsua_init() != PJ_SUCCESS)
 	return 1;
@@ -778,5 +866,4 @@
 
     /* Parse command line arguments: */
-
     if (pjsua_parse_args(argc, argv) != PJ_SUCCESS)
 	return 1;
@@ -784,5 +871,4 @@
 
     /* Init logging: */
-
     app_logging_init();
 
@@ -791,10 +877,8 @@
      * messages.
      */
-
     pjsip_endpt_register_module(pjsua.endpt, &console_msg_logger);
 
 
     /* Start pjsua! */
-
     if (pjsua_start() != PJ_SUCCESS) {
 
@@ -805,25 +889,16 @@
 
     /* Sleep for a while, let any messages get printed to console: */
-
     pj_thread_sleep(500);
 
 
-    /* No current call initially: */
-
-    inv_session = &pjsua.inv_list;
-
-
     /* Start UI console main loop: */
-
     ui_console_main();
 
 
     /* Destroy pjsua: */
-
     pjsua_destroy();
 
 
     /* Close logging: */
-
     app_logging_shutdown();
 
