Index: pjproject/branches/projects/jni/pjsip-apps/src/jni/Makefile
===================================================================
--- pjproject/branches/projects/jni/pjsip-apps/src/jni/Makefile	(revision 4556)
+++ pjproject/branches/projects/jni/pjsip-apps/src/jni/Makefile	(revision 4557)
@@ -21,5 +21,5 @@
 MY_OUT_DIR	 = output
 MY_SWIG_IF	 = $(MY_OUT_DIR)/pjsua.i
-MY_SWIG_FLAG	 = -c++ -I$(MY_OUT_DIR) # -Wall
+MY_SWIG_FLAG	 = -c++ -I$(MY_OUT_DIR) # -debug-tmsearch -debug-tmused # -Wall
 MY_SWIG_WRAPPER	 = $(MY_OUT_DIR)/pjsua_wrap
 MY_PACKAGE_SRC	 = $(MY_OUT_DIR)/src/$(subst .,/,$(MY_PACKAGE))
Index: pjproject/branches/projects/jni/pjsip-apps/src/jni/callbacks.i
===================================================================
--- pjproject/branches/projects/jni/pjsip-apps/src/jni/callbacks.i	(revision 4556)
+++ pjproject/branches/projects/jni/pjsip-apps/src/jni/callbacks.i	(revision 4557)
@@ -6,4 +6,5 @@
 
 %feature("director") PjsuaCallback;
+%ignore pjsua_callback;
 %ignore pjsua_config::cb;
 %extend pjsua_config {
Index: pjproject/branches/projects/jni/pjsip-apps/src/jni/header.i
===================================================================
--- pjproject/branches/projects/jni/pjsip-apps/src/jni/header.i	(revision 4556)
+++ pjproject/branches/projects/jni/pjsip-apps/src/jni/header.i	(revision 4557)
@@ -16,22 +16,29 @@
 
 /* Map 'void *' simply as long, app can use this "long" as index of its real user data */
-%apply long { void * };
+%apply long long { void * };
 
 /* Handle void *[ANY], e.g: pjsip_tx_data::mod_data, pjsip_transaction::mod_data */
 //%ignore pjsip_tx_data::mod_data;
 //%ignore pjsip_transaction::mod_data;
-%apply long[ANY] { void *[ANY] };
+%apply long long[ANY]   { void *[ANY] };
 
 /* Map "int*" & "unsigned*" as input & output */
 %apply unsigned	*INOUT  { unsigned * };
-%apply int	*INOUT  { int * };
+%apply int      *INOUT  { int * };
 
 /* Map the following args as input & output */
-%apply int 	*INOUT	{ pj_stun_nat_type * };
-%apply int 	*INOUT	{ pjsip_status_code * };
-%apply int[ANY] 	{ pjmedia_format_id dec_fmt_id[ANY] };
+%apply int      *INOUT	{ pj_stun_nat_type * };
+%apply int      *INOUT	{ pjsip_status_code * };
+%apply int[ANY]         { pjmedia_format_id dec_fmt_id[ANY] };
+%apply pj_str_t *INOUT  { pj_str_t *p_contact };
 
-/* Handle array of pj_str_t */
-JAVA_ARRAYSOFCLASSES(pj_str_t)
+/* Handle members typed array of pj_str_t */
+MY_JAVA_MEMBER_ARRAY_OF_STR(pjsua_config, nameserver, nameserver_count)
+MY_JAVA_MEMBER_ARRAY_OF_STR(pjsua_config, outbound_proxy, outbound_proxy_cnt)
+MY_JAVA_MEMBER_ARRAY_OF_STR(pjsua_config, stun_srv, stun_srv_cnt)
+MY_JAVA_MEMBER_ARRAY_OF_STR(pjsua_acc_config, proxy, proxy_cnt)
+MY_JAVA_MEMBER_ARRAY_OF_STR(pjsua_config, stun_srv, stun_srv_cnt)
+MY_JAVA_MEMBER_ARRAY_OF_STR(pjsua_config, stun_srv, stun_srv_cnt)
+MY_JAVA_MEMBER_ARRAY_OF_STR(pjsip_generic_array_hdr, values, count)
 
 /* Handle pointer-to-pointer-to-object as input & output */
Index: pjproject/branches/projects/jni/pjsip-apps/src/jni/hello.java
===================================================================
--- pjproject/branches/projects/jni/pjsip-apps/src/jni/hello.java	(revision 4556)
+++ pjproject/branches/projects/jni/pjsip-apps/src/jni/hello.java	(revision 4557)
@@ -4,4 +4,9 @@
 import java.io.InputStreamReader;
 import java.io.IOException;
+
+import org.pjsip.pjsua.pj_pool_t;
+import org.pjsip.pjsua.pjsip_rx_data;
+import org.pjsip.pjsua.pjsip_transport_type_e;
+
 import org.pjsip.pjsua.pjsua;
 import org.pjsip.pjsua.pjsua_acc_config;
@@ -11,6 +16,4 @@
 import org.pjsip.pjsua.pjsua_logging_config;
 import org.pjsip.pjsua.pjsua_transport_config;
-import org.pjsip.pjsua.pjsip_transport_type_e;
-import org.pjsip.pjsua.pj_str_t;
 import org.pjsip.pjsua.PjsuaCallback;
 
@@ -19,11 +22,26 @@
 	public void on_call_media_state(int call_id)
 	{
-	    System.out.println("======== Call media started (call id: " + call_id + ")");
-	    pjsua_call_info info = new pjsua_call_info();
-	    pjsua.call_get_info(call_id, info);
-	    if (info.getMedia_status() == pjsua_call_media_status.PJSUA_CALL_MEDIA_ACTIVE) {
-		pjsua.conf_connect(info.getConf_slot(), 0);
-		pjsua.conf_connect(0, info.getConf_slot());
-	    }
+		System.out.println("======== Call media started (call id: " + call_id + ")");
+		pjsua_call_info info = new pjsua_call_info();
+		pjsua.call_get_info(call_id, info);
+		if (info.getMedia_status() == pjsua_call_media_status.PJSUA_CALL_MEDIA_ACTIVE) {
+			pjsua.conf_connect(info.getConf_slot(), 0);
+			pjsua.conf_connect(0, info.getConf_slot());
+		}
+	}
+	@Override
+	public void on_pager(int call_id, String from, String to, String contact, String mime_type, String body)
+	{
+		System.out.println("======== Incoming pager (call id: " + call_id + ")");
+		System.out.println("From     : " + from);
+		System.out.println("To       : " + to);
+		System.out.println("Contact  : " + contact);
+		System.out.println("Mimetype : " + mime_type);
+		System.out.println("Body     : " + body);
+	}
+	@Override
+	public void on_incoming_call(int acc_id, int call_id, pjsip_rx_data rdata) {
+		/* Auto answer */
+		pjsua.call_answer(call_id, 200, null, null);
 	}
 }
@@ -40,11 +58,4 @@
 	}
 
-	protected static pj_str_t pj_str(String st) {
-		pj_str_t st_ = new pj_str_t();
-		st_.setPtr(st);
-		st_.setSlen(st.length());
-		return st_;
-	}
-	
 	public static void main(String[] args) {
 		int[] tp_id = new int[1];
@@ -105,7 +116,6 @@
 		
 		/* Make call to the URL. */
-		{
-			pj_str_t call_target = pj_str("sip:localhost");
-			status = pjsua.call_make_call(acc_id[0], call_target, null, 0, null, call_id);
+		if (false) {
+			status = pjsua.call_make_call(acc_id[0], "sip:localhost", null, 0, null, call_id);
 			if (status != pjsua.PJ_SUCCESS) {
 				pj_error_exit("Error making call", status);
@@ -117,4 +127,7 @@
 			String userInput;
 			BufferedReader inBuffReader = new BufferedReader(new InputStreamReader(System.in));
+
+			System.out.println("Press 'h' to hangup all calls, 'q' to quit");
+
 			try {
 				userInput = inBuffReader.readLine();
@@ -124,11 +137,18 @@
 			}
 			
-			System.out.println("Press 'h' to hangup all calls, 'q' to quit");
-			
-			if (userInput.equals("q"))
+			if (userInput.equals("q")) {
 				break;
-
-			if (userInput.equals("h"))
+			} else if (userInput.equals("h")) {
 				pjsua.call_hangup_all();
+			} else if (userInput.equals("c")) {
+				/* Test string as output param, it is wrapped as string array */
+				String[] contact = new String[1];
+				pj_pool_t my_pool = pjsua.pool_create("hello", 256, 256);
+				
+				pjsua.acc_create_uac_contact(my_pool, contact, 0, "sip:localhost");
+				System.out.println("Test create contact: " + contact[0]);
+				
+				pjsua.pj_pool_release(my_pool);
+			}
 		}
 
Index: pjproject/branches/projects/jni/pjsip-apps/src/jni/my_typemaps.i
===================================================================
--- pjproject/branches/projects/jni/pjsip-apps/src/jni/my_typemaps.i	(revision 4556)
+++ pjproject/branches/projects/jni/pjsip-apps/src/jni/my_typemaps.i	(revision 4557)
@@ -4,37 +4,217 @@
 %include "typemaps.i"
 
-/* Add director typemaps for "int *INOUT" */
+/* Auto destroy JNI object, useful for director */
+%inline %{
+class LocalRefGuard {
+    JNIEnv* jenv;
+    jobject jobj;
+public:
+    LocalRefGuard(JNIEnv* jenv_, jobject jobj_) : jenv(jenv_), jobj(jobj_) {}
+    ~LocalRefGuard() { if (jobj) jenv->DeleteLocalRef(jobj); }
+};
+%}
+
+/*
+ * Add director typemaps for "int *INOUT"
+ */
 %typemap(javadirectorin) int *INOUT "$jniinput"
 %typemap(directorin, descriptor="[I") int *INOUT %{
   $input = jenv->NewIntArray(1);
+  LocalRefGuard g_$input(jenv, $input);
   jenv->SetIntArrayRegion($input, 0, 1, (jint*)$1);
 %}
 %typemap(directorout) int *INOUT %{
-  jint* tmp$result = jenv->GetIntArrayElements($input, 0);
-  *$result = tmp$result[0];
-  jenv->ReleaseIntArrayElements($input, tmp$result, JNI_ABORT);
+  jint tmp$result;
+  jenv->GetIntArrayRegion($input, 0, 1, &tmp$result);
+  *$result = ($*1_ltype)tmp$result;
 %}
 %typemap(directorargout) int *INOUT %{
-  jint* tmp$1 = jenv->GetIntArrayElements($input, 0);
-  *$1 = ($*1_ltype) tmp$1[0];
-  jenv->ReleaseIntArrayElements($input, tmp$1, JNI_ABORT);
-%}
-
-/* Add director typemaps for "unsigned *INOUT" */
+  jint tmp$1;
+  jenv->GetIntArrayRegion($input, 0, 1, &tmp$1);
+  *$1 = ($*1_ltype)tmp$1;
+%}
+
+/*
+ * Add director typemaps for "unsigned *INOUT"
+ */
 %typemap(javadirectorin) unsigned *INOUT "$jniinput"
 %typemap(directorin, descriptor="[I") unsigned *INOUT %{
   $input = jenv->NewLongArray(1);
+  LocalRefGuard g_$input(jenv, $input);
   jenv->SetLongArrayRegion($input, 0, 1, (jlong*)$1);
 %}
 %typemap(directorout) unsigned *INOUT %{
-  jlong* tmp$result = jenv->GetLongArrayElements($input, 0);
-  *$result = tmp$result[0];
-  jenv->ReleaseLongArrayElements($input, tmp$result, JNI_ABORT);
+  jlong tmp$result;
+  jenv->GetLongArrayRegion($input, 0, 1, &tmp$result);
+  *$result = ($*1_ltype)tmp$result;
 %}
 %typemap(directorargout) unsigned *INOUT %{
-  jlong* tmp$1 = jenv->GetLongArrayElements($input, 0);
-  *$1 = ($*1_ltype) tmp$1[0];
-  jenv->ReleaseLongArrayElements($input, tmp$1, JNI_ABORT);
-%}
+  jlong tmp$1;
+  jenv->GetLongArrayRegion($input, 0, 1, &tmp$1);
+  *$1 = ($*1_ltype)tmp$1;
+%}
+
+/*
+ * Map pj_str_t to java String
+ */
+%ignore pj_str_t;
+%typemap(jni)             pj_str_t* "jstring"
+%typemap(jtype)           pj_str_t* "String"
+%typemap(jstype)          pj_str_t* "String"
+%typemap(javain)          pj_str_t* "$javainput"
+%typemap(javaout)         pj_str_t* { return $jnicall; }
+%typemap(javadirectorin)  pj_str_t* "$jniinput"
+%typemap(javadirectorout) pj_str_t* "$javacall"
+
+%typemap(in)              pj_str_t* (pj_str_t str_tmp, char* str_ptr=NULL) %{
+  $1 = &str_tmp;
+  if(!$input) pj_strset($1, NULL, 0);
+  else {
+    str_ptr = (char*)jenv->GetStringUTFChars($input, 0);
+    pj_size_t str_len = jenv->GetStringUTFLength($input);
+    if (!str_ptr || !str_len) pj_strset($1, NULL, 0);
+    else pj_strset($1, str_ptr, str_len);
+  }
+%}
+
+%typemap(freearg)         pj_str_t* %{
+  if ($input)
+    jenv->ReleaseStringUTFChars($input, str_ptr$argnum);
+%}
+
+%typemap(memberin)        pj_str_t %{
+  if ($1.ptr) free($1.ptr);
+  if ($input->ptr) {
+    $1.ptr = (char*)malloc($input->slen);				/* <-- will leak! */
+    memcpy($1.ptr, $input->ptr, $input->slen);
+    $1.slen = $input->slen;
+  }
+%}
+
+%typemap(out)             pj_str_t* %{
+  char *$1_ptr = (char*)malloc($1->slen+1);
+  memcpy($1_ptr, $1->ptr, $1->slen);
+  $1_ptr[$1->slen] = '\0';
+  $result = jenv->NewStringUTF($1_ptr);
+  free($1_ptr);
+%}
+
+%typemap(directorin,descriptor="Ljava/lang/String;") pj_str_t* %{
+  char *$input_ptr = (char*)malloc($1->slen+1);
+  memcpy($input_ptr, $1->ptr, $1->slen);
+  $input_ptr[$1->slen] = '\0';
+  $input = jenv->NewStringUTF($input_ptr);
+  LocalRefGuard g_$input(jenv, $input);
+  free($input_ptr);
+%}
+
+/*
+ * Map pj_str_t[ANY] to java String[]
+ */
+%typemap(jni)     pj_str_t[ANY] "jobjectArray"
+%typemap(jtype)	  pj_str_t[ANY] "String[]"
+%typemap(jstype)  pj_str_t[ANY] "String[]"
+%typemap(javain)  pj_str_t[ANY] "$javainput"
+%typemap(javaout) pj_str_t[ANY] { return $jnicall; }
+%typemap(in)      pj_str_t[ANY] %{
+  int $1_len = jenv->GetArrayLength($input);
+  char** $1_tmpstr = new char*[$1_len];
+  jstring* $1_tmp = new jstring[$1_len];
+  $1 = new pj_str_t[$1_len];
+  int $1_ii;
+  for ($1_ii = 0; $1_ii<$1_len; $1_ii++) {
+    $1_tmp[$1_ii] = (jstring)jenv->GetObjectArrayElement($input, $1_ii);
+    if ($1_tmp[$1_ii]) {
+      $1[$1_ii].ptr = $1_tmpstr[$1_ii] = (char*)jenv->GetStringUTFChars($1_tmp[$1_ii], 0);
+      $1[$1_ii].slen = jenv->GetStringUTFLength($1_tmp[$1_ii]);
+    } else {
+      pj_strset(&$1[$1_ii], NULL, 0);
+    }
+    jenv->DeleteLocalRef($1_tmp[$1_ii]); /* is this ok here? */
+  }
+%}
+
+%typemap(freearg) pj_str_t[ANY] %{
+  for ($1_ii=0; $1_ii<$1_len; $1_ii++)
+    if ($1_tmp[$1_ii]) jenv->ReleaseStringUTFChars($1_tmp[$1_ii], $1_tmpstr[$1_ii]);
+  delete [] $1;
+  delete [] $1_tmp;
+  delete [] $1_tmpstr;
+%}
+
+/* 
+ * Handle setter/getter of a struct member with type of 'array of pj_str_t'.
+ */
+%define MY_JAVA_MEMBER_ARRAY_OF_STR(CLASS_NAME, NAME, COUNT_NAME)
+
+%ignore CLASS_NAME::COUNT_NAME;
+
+%typemap(memberin)	pj_str_t NAME[ANY], pj_str_t NAME[] {
+  int i;
+  for (i=0; i<arg1->COUNT_NAME; ++i)
+    if ($1[i].ptr) free($1[i].ptr);
+  
+  arg1->COUNT_NAME = $input_len;
+  for (i=0; i<arg1->COUNT_NAME; ++i) {
+    if ($input->ptr) {
+      $1[i].ptr = (char*)malloc($input->slen);				/* <-- will leak! */
+      memcpy($1[i].ptr, $input->ptr, $input->slen);
+      $1[i].slen = $input->slen;
+    }
+  }
+}
+
+%typemap(out) 		pj_str_t NAME[ANY] {
+  int i;
+  jstring temp_string;
+  const jclass clazz = jenv->FindClass("java/lang/String");
+
+  $result = jenv->NewObjectArray(arg1->COUNT_NAME, clazz, NULL);
+  for (i=0; i<arg1->COUNT_NAME; i++) {
+    temp_string = jenv->NewStringUTF($1[i].ptr);
+    jenv->SetObjectArrayElement($result, i, temp_string);
+    jenv->DeleteLocalRef(temp_string);
+  }
+}
+
+%enddef
+
+/*
+ * pj_str_t *INOUT, string as input and output param, handled as single element array.
+ */
+%apply pj_str_t[ANY] { pj_str_t *INOUT };
+
+%typemap(argout) pj_str_t *INOUT {
+  char *$1_ptr = new char[$1[0].slen+1];
+  memcpy($1_ptr, $1[0].ptr, $1[0].slen);
+  $1_ptr[$1[0].slen] = '\0';
+  jstring temp_string = jenv->NewStringUTF($1_ptr);
+  jenv->SetObjectArrayElement($input, 0, temp_string);
+  delete [] $1_ptr;
+}
+
+%typemap(directorin,descriptor="[Ljava/lang/String;") pj_str_t *INOUT %{
+  jstring tmp_$input;
+  $input = jenv->NewObjectArray(1, jenv->FindClass("java/lang/String"), NULL);
+  LocalRefGuard g_$input(jenv, $input);
+  tmp_$input = jenv->NewStringUTF($1[0].ptr);
+  LocalRefGuard g_temp_$input(jenv, tmp_$input);
+  jenv->SetObjectArrayElement($input, 0, tmp_$input);
+%}
+
+%typemap(directorargout)  pj_str_t *INOUT {
+  if(!$input) pj_strset($1, NULL, 0);
+  else {
+    str_ptr = (char*)jenv->GetStringUTFChars($input, 0);
+    pj_size_t str_len = jenv->GetStringUTFLength($input);
+    if (!str_ptr || !str_len) pj_strset($1, NULL, 0);
+    else {
+      $1->ptr = (char*)malloc(str_len);					/* <-- will leak! */
+      memcpy($1->ptr, str_ptr, str_len);
+      $1->slen = str_len;
+    }
+  }
+}
+
 
 /* 
@@ -45,10 +225,10 @@
 %typemap(jtype)  TYPE **NAME "long"
 %typemap(jstype) TYPE **NAME "TYPE"
-%typemap(in) 	 TYPE **NAME (TYPE *temp = NULL) { temp = (TYPE*)$input; $1 = &temp; }
-%typemap(argout) TYPE **NAME "$input = (jlong)*$1;" 
+%typemap(in) 	 TYPE **NAME (TYPE *temp = NULL) "temp = (TYPE*)$input; $1 = &temp;"
+%typemap(argout) TYPE **NAME "$input = (jlong)*$1;"
 %typemap(directorin,descriptor="L$packagepath/TYPE;") TYPE **NAME "$input = (jlong)*$1;"
-%typemap(directorargout) TYPE **NAME " *$1 = (TYPE*)$input; "
-%typemap(javain) TYPE **NAME "TYPE.getCPtr($javainput)"
-%typemap(javadirectorin) TYPE **NAME "($jniinput == 0) ? null : new TYPE($jniinput, false)"
+%typemap(directorargout)  TYPE **NAME " *$1 = (TYPE*)$input; "
+%typemap(javain)	  TYPE **NAME "TYPE.getCPtr($javainput)"
+%typemap(javadirectorin)  TYPE **NAME "($jniinput == 0) ? null : new TYPE($jniinput, false)"
 %typemap(javadirectorout) TYPE **NAME "TYPE.getCPtr($javacall)"
 %enddef
@@ -57,39 +237,29 @@
 /* 
  * Generate setter/getter of a struct member typed of 'array of enum' with variable length.
- * Sample usage, given enum array member in this struct:
- * --
- *   struct pjsip_tls_setting {
- *     ..
- *     unsigned ciphers_num;
- *     pj_ssl_cipher *ciphers;
- *     ..
- *   };
- * --
- * apply:
- *   MY_JAVA_MEMBER_ARRAY_OF_ENUM(pjsip_tls_setting, pj_ssl_cipher, ciphers, ciphers_num)
  */
 %define MY_JAVA_MEMBER_ARRAY_OF_ENUM(CLASS_NAME, TYPE, NAME, COUNT_NAME)
 
-%apply ARRAYSOFENUMS[] { TYPE* };
-%typemap(out) TYPE* %{ $result = SWIG_JavaArrayOutInt(jenv, (int*)$1, arg1->COUNT_NAME); %}
-%ignore CLASS_NAME::NAME;
 %ignore CLASS_NAME::COUNT_NAME;
-%extend CLASS_NAME {
-    %rename ("%(lowercamelcase)s") set_##NAME;
-    %rename ("%(lowercamelcase)s") get_##NAME;
-    void set_##NAME(TYPE *NAME, int num) {
-        int i;
-	if ($self->NAME) free($self->NAME);
-	$self->NAME = (TYPE*)calloc(num, sizeof(TYPE));
-	for (i=0; i<num; ++i) $self->NAME[i] = NAME[i];
-	$self->COUNT_NAME = num;
-    }
-    TYPE* get_##NAME() {
-	return $self->NAME;
-    }
-    ~CLASS_NAME() {
-	if ($self->NAME) free($self->NAME);
-    }
-};
+%apply ARRAYSOFENUMS[] { TYPE* NAME };
+
+%typemap(in)       TYPE* NAME (jint *jarr) %{
+  int size$1 = jenv->GetArrayLength($input);
+  if (!SWIG_JavaArrayInInt(jenv, &jarr, (int **)&$1, $input)) return $null;
+%}
+
+%typemap(memberin) TYPE* NAME %{
+  if ($1) free($1);
+  arg1->COUNT_NAME = size$input;
+  $1 = (TYPE*)calloc(arg1->COUNT_NAME, sizeof(TYPE));			/* <-- will leak! */
+  for (size_t i = 0; i < (size_t)arg1->COUNT_NAME; i++)
+    $1[i] = $input[i];
+%}
+
+%typemap(out)      TYPE* NAME %{
+  $result = SWIG_JavaArrayOutInt(jenv, (int*)$1, arg1->COUNT_NAME);
+%}
+
+// Hack for avoiding leak, may not work when another macro defines class destructor too
+%extend CLASS_NAME { ~CLASS_NAME() { if ($self->NAME) free($self->NAME); } };
 
 %enddef
@@ -97,42 +267,37 @@
 
 /* 
- * Handle getter of a struct member with type of 'array of pointer to struct/class'.
- * Currently this is applicable for read-only member.
+ * Handle setter/getter of a struct member with type of 'array of pointer to struct/class'.
  */
 %define MY_JAVA_MEMBER_ARRAY_OF_POINTER(CLASS_NAME, TYPE, NAME, COUNT_NAME)
 
 %ignore CLASS_NAME::COUNT_NAME;
-%immutable CLASS_NAME::NAME;
-%typemap(jni) TYPE *[ANY] "jlongArray"
-%typemap(jtype) TYPE *[ANY] "long[]"
-%typemap(jstype) TYPE *[ANY] "TYPE[]"
-%typemap(javain) TYPE *[ANY] "TYPE.cArrayUnwrap($javainput)"
-%typemap(javaout) TYPE *[ANY] {return TYPE.cArrayWrap($jnicall, $owner);}
-
-// somehow "$result" is not preprocessed in "typemap(ret)", use 'jresult' directly then
-%typemap(ret) TYPE *[ANY] {
-  jlong *arr;
-  int i;
-  jresult = JCALL1(NewLongArray, jenv, arg1->COUNT_NAME);
-  if (!jresult) {
+%typemap(jni) 	   TYPE* NAME[ANY] "jlongArray"
+%typemap(jtype)    TYPE* NAME[ANY] "long[]"
+%typemap(jstype)   TYPE* NAME[ANY] "TYPE[]"
+%typemap(javain)   TYPE* NAME[ANY] "TYPE.cArrayUnwrap($javainput)"
+%typemap(javaout)  TYPE* NAME[ANY] {return TYPE.cArrayWrap($jnicall, $owner);}
+
+%typemap(in)       TYPE* NAME[ANY] (jlong *jarr) %{
+  if (!SWIG_JavaArrayInUlong(jenv, &jarr, (unsigned long**)&$1, $input))
     return $null;
-  }
-  arr = JCALL2(GetLongArrayElements, jenv, jresult, 0);
-  if (!arr) {
-    return $null;
-  }
-  for (i=0; i<arg1->COUNT_NAME; i++) {
-    arr[i] = 0;
-    *($1_ltype)&arr[i] = $1[i];
-  }
-  JCALL3(ReleaseLongArrayElements, jenv, jresult, arr, 0);
-}
+  arg1->COUNT_NAME = jenv->GetArrayLength($input);
+%}
+
+%typemap(freearg)  TYPE* NAME[ANY] %{ if ($1) delete [] $1; %}
+
+%typemap(memberin) TYPE* NAME[ANY] %{
+  for (size_t i = 0; i < (size_t)arg1->COUNT_NAME; i++) $1[i] = $input[i];
+%}
+
+%typemap(out)      TYPE* NAME[ANY] %{
+  $result = SWIG_JavaArrayOutUlong(jenv, (unsigned long*)$1, arg1->COUNT_NAME);
+%}
 
 %typemap(javacode) TYPE %{
   protected static long[] cArrayUnwrap($javaclassname[] arrayWrapper) {
-      long[] cArray = new long[arrayWrapper.length];
-      for (int i=0; i<arrayWrapper.length; i++)
-        cArray[i] = $javaclassname.getCPtr(arrayWrapper[i]);
-      return cArray;
+    long[] cArray = new long[arrayWrapper.length];
+    for (int i=0; i<arrayWrapper.length; i++)
+      cArray[i] = $javaclassname.getCPtr(arrayWrapper[i]);
+    return cArray;
   }
   protected static $javaclassname[] cArrayWrap(long[] cArray, boolean cMemoryOwn) {
Index: pjproject/branches/projects/jni/pjsip-apps/src/jni/swig_gen.py
===================================================================
--- pjproject/branches/projects/jni/pjsip-apps/src/jni/swig_gen.py	(revision 4556)
+++ pjproject/branches/projects/jni/pjsip-apps/src/jni/swig_gen.py	(revision 4557)
@@ -15,5 +15,5 @@
 
 # CPP (C preprocessor) settings, CPP is needed by pycparser.
-CPP_PATH     = 'C:/devs/bin/cpp.exe' if sys.platform == 'win32' else 'cpp'
+CPP_PATH	 = 'C:/devs/bin/cpp.exe' if sys.platform == 'win32' else 'cpp'
 CPP_CFLAGS   = [
 	r'-DPJ_AUTOCONF',
@@ -56,222 +56,217 @@
 	'pjmedia_port',
 	'pjmedia_transport',
-	'pjsua_media_transport',
-	'pjsua_callback',
-	'pjmedia_stream'
+	'pjsua_media_transport'
 ]
 
 FORCE_EXPORT = [
-	'pjsip_event',
-	'pjsip_transaction',
-	'pjmedia_sdp_session',
-	#'pj_str' # plain export result doesn't work!
+	'pj_pool_release'
 ]
 
 class MyGen(c_generator.CGenerator):
-    
-    def __init__(self, ast):
-        super(MyGen, self).__init__()
-        self.ast = ast
-        self.nodes = OrderedDict()
-	self.deps = list()
-	self.deps_pending = list()
-	self.deps_frozen = False
-
-	# Generate nodes map (name -> node instances)
-        for ext in self.ast.ext:
-	    name = self._get_node_name(ext)
-            if name and not name.startswith(BASE_PREFIX):
-	        continue
-	
-	    if name in self.nodes:
-	        self.nodes[name].append(ext)
-                # always put typedef later, swig issue
-	        if isinstance(self.nodes[name][0], c_ast.Typedef):
-		    self.nodes[name].reverse()
-	    else:
-	        self.nodes[name] = [ext]
-		
-        # Generate dependencies, they are all APIs to be exported
-        for name in self.nodes.keys():
-	    if (not name) or \
-	       ((name in FORCE_EXPORT or name.startswith(MODULE_PREFIX)) \
-	              and self._check_video(name)):
-	        self._add_dep(name)
-	self.deps_frozen = True
-	
-    # Override visit_IdentifierType() to collect "node name" and generate dependencies
-    # from this node's children
-    def visit_IdentifierType(self, n):
-	if not self.deps_frozen:
-	    for name in n.names: self._add_dep(name)
-	return super(MyGen, self).visit_IdentifierType(n)
-
-    def _check_video(self, name):
-	if NO_VIDEO and name and ((name.find('_vid_') > 0) or (name.find('_video_') > 0)):
-	    return False
-	return True
-    
-    def _get_node_name(self, node):
-        s = getattr(node, 'name', None)
-	if s:
-	    return s
-	if isinstance(node, c_ast.FuncDef):
-	    return self._get_node_name(node.decl)
-	ss = getattr(node, 'names', None)
-	if ss:
-	    s = ' '.join(ss)
-	    return s
-	if getattr(node, 'type', None):
-	    return self._get_node_name(node.type)
-	return s
-
-    # Trace node dependencies by recursively inspecting its children.
-    # The node itself and all its children will be listed in 'deps'.
-    def _add_dep(self, name):
-        if (name and not name.startswith(BASE_PREFIX)) or \
-	    name in self.deps or name in self.deps_pending:
-	    return
-	    
-	if name in FORCE_STRUCT_AS_OPAQUE and (not name == 'pjsua_callback'):
-	    self.deps.append(name)
-	    return
-	    
-	self.deps_pending.append(name)
-	for node in self.nodes[name]:
-	    self.visit(node)
-	if not self.deps_pending.pop() == name:
-	    print 'Error initializing dep!'
-	    sys.exit(1)
-	self.deps.append(name)
-    	
-    # Opaque struct is identified by empty struct member declaration.
-    def _is_struct_opaque(self, node):
-	if isinstance(node, c_ast.Typedef) and isinstance(node.type, c_ast.TypeDecl) and \
-	   isinstance(node.type.type, c_ast.Struct) and node.type.type.decls == None:
-	    return True
-	elif isinstance(node, c_ast.Decl) and isinstance(node.type, c_ast.Struct) and \
-	     node.type.decls == None:
-	    return True
-	return False
-
-    # Check if the specified struct name is opaque. If it is, declare as zero member and
-    # tell SWIG to omit ctor/dtor.
-    def _process_opaque_struct(self, name, code):
-        opaque = True
-	if not (name in FORCE_STRUCT_AS_OPAQUE):
-   	    for n in self.nodes[name]:
-		if not self._is_struct_opaque(n):
-		    opaque = False
-		    break
-	if opaque:
-	    s = '%nodefaultctor ' + name + '; %nodefaultdtor ' + name + ';\n'
-	    s += 'struct ' + name + ' {};\n'
-	    return s
-
-	# Remove "typedef struct/enum ..." without member decl (optional)
-	if name:
-	    code = code.replace('typedef struct '+name+' '+name+';\n', '', 1)
-	    code = code.replace('typedef enum '+name+' '+name+';\n', '', 1)
-	return code
-	
-    def _gen_pjsua_callback(self):
-	# init
-	cbclass  = ''
-	cbproxy = ''
-	cbdef = []
-
-        n = self.nodes['pjsua_callback'][0]
-	raw_lines = self._print_node(n).splitlines()
-	for idx, line in enumerate(raw_lines):
-	    if idx in [0, 1, len(raw_lines)-1]: continue
-	    fstrs = []
-	    # pointer to function type format
-	    m = re.match('\s+(.*)\(\*(.*)\)(\(.*\));', line)
-	    if m:
-		fstrs = [m.group(1).strip(), m.group(2), m.group(3)]
-	    else:
-	        # typedef'd format
-	        m = re.match('\s+(.*)\s+(.*);', line)
-		if (not m) or (not self.nodes.has_key(m.group(1))):
-		    cbdef.append('  NULL')
-		    continue
-		fstrs = ['', m.group(2), '']
-	        n = self.nodes[m.group(1)][0]
-		raw = self._print_node(n)
-		m = re.match('typedef\s+(.*)\(\*(.*)\)(\(.*\));', raw)
-		if not m:
-		    cbdef.append('  NULL')
-		    continue
-		fstrs[0] = m.group(1).strip()
-		fstrs[2] = m.group(3)
-	
-	    cbclass += '  virtual ' + ' '.join(fstrs)
-    	    if fstrs[0] == 'void':
-		cbclass += ' {}\n'
-	    elif fstrs[1] == 'on_create_media_transport':
-	        cbclass += ' { return base_tp; }\n'
-	    elif fstrs[1] == 'on_call_redirected':
-	        cbclass += ' { return PJSIP_REDIRECT_STOP; }\n'
-	    else:
-	        cbclass += ' { return 0; }\n'
-
-	    cbproxy += 'static ' + ' '.join(fstrs)
-	    params = re.findall('(\w+)[,\)]', fstrs[2])
-    	    if fstrs[0] == 'void':
-		cbproxy += ' { cb->'+fstrs[1]+'('+','.join(params)+'); }\n'
-	    else:
-	        cbproxy += ' { return cb->'+fstrs[1]+'('+','.join(params)+'); }\n'
-
-	    cbdef.append('  &' + fstrs[1])
-		
-	# trail	
-	
-        return [cbclass, cbproxy, ',\n'.join(cbdef)+'\n']
-    
-    # Generate code from the specified node.
-    def _print_node(self, node):
-        s = ''
-        if isinstance(node, c_ast.FuncDef):
-	    s = self.visit(node)
-        else:
-	    s = self.visit(node)
-	    if s: s += ';\n'
-	return s
-
-    def go(self):
-	s = ''
-	for name in self.deps:
-	    ss = ''
-	    for node in self.nodes[name]:
-	        ss += self._print_node(node)
-	    s += self._process_opaque_struct(name, ss)
-	return s
-	
-    def write_pjsua_callback(self, outdir):
-        cb = self._gen_pjsua_callback()
-	
-	fout = open(outdir+'/callbacks.h', 'w+')
-        fin  = open('callbacks.h.template', 'r')
-        for line in fin:
-	    if line.find(r'$PJSUA_CALLBACK_CLASS$') >= 0:
-		fout.write(cb[0])
-	    else:
-                fout.write(line)
-	fin.close()
-	fout.close()
-
-	fout = open(outdir+'/callbacks.c', 'w+')
-        fin  = open('callbacks.c.template', 'r')
-        for line in fin:
-	    if line.find(r'$PJSUA_CALLBACK_PROXY$') >= 0:
-		fout.write(cb[1])
-	    elif line.find(r'$PJSUA_CALLBACK_DEF$') >= 0:
-		fout.write(cb[2])
-	    else:
-                fout.write(line)
-	fin.close()
-	fout.close()
-
-# MAIN		
+	
+	def __init__(self, ast):
+		super(MyGen, self).__init__()
+		self.ast = ast
+		self.nodes = OrderedDict()
+		self.deps = list()
+		self.deps_pending = list()
+		self.deps_frozen = False
+
+		# Generate nodes map (name -> node instances)
+		for ext in self.ast.ext:
+			name = self._get_node_name(ext)
+			if name and not name.startswith(BASE_PREFIX):
+				continue
+		
+			if name in self.nodes:
+				self.nodes[name].append(ext)
+				# always put typedef later, swig issue
+				if isinstance(self.nodes[name][0], c_ast.Typedef):
+					self.nodes[name].reverse()
+			else:
+				self.nodes[name] = [ext]
+				
+		# Generate dependencies, they are all APIs to be exported
+		for name in self.nodes.keys():
+			if (not name) or \
+				((name in FORCE_EXPORT or name.startswith(MODULE_PREFIX)) \
+					  and self._check_video(name)):
+				self._add_dep(name)
+		self.deps_frozen = True
+	
+	# Override visit_IdentifierType() to collect "node name" and generate dependencies
+	# from this node's children
+	def visit_IdentifierType(self, n):
+		if not self.deps_frozen:
+			for name in n.names: self._add_dep(name)
+		return super(MyGen, self).visit_IdentifierType(n)
+
+	def _check_video(self, name):
+		if NO_VIDEO and name and ((name.find('_vid_') > 0) or (name.find('_video_') > 0)):
+			return False
+		return True
+	
+	def _get_node_name(self, node):
+		s = getattr(node, 'name', None)
+		if s:
+			return s
+		if isinstance(node, c_ast.FuncDef):
+			return self._get_node_name(node.decl)
+		ss = getattr(node, 'names', None)
+		if ss:
+			s = ' '.join(ss)
+			return s
+		if getattr(node, 'type', None):
+			return self._get_node_name(node.type)
+		return s
+
+	# Trace node dependencies by recursively inspecting its children.
+	# The node itself and all its children will be listed in 'deps'.
+	def _add_dep(self, name):
+		if (name and not name.startswith(BASE_PREFIX)) or \
+			name in self.deps or name in self.deps_pending:
+			return
+			
+		if name in FORCE_STRUCT_AS_OPAQUE:
+			self.deps.append(name)
+			return
+			
+		self.deps_pending.append(name)
+		for node in self.nodes[name]:
+			self.visit(node)
+		if not self.deps_pending.pop() == name:
+			print 'Error initializing dep!'
+			sys.exit(1)
+		self.deps.append(name)
+		
+	# Opaque struct is identified by empty struct member declaration.
+	def _is_struct_opaque(self, node):
+		if isinstance(node, c_ast.Typedef) and isinstance(node.type, c_ast.TypeDecl) and \
+		   isinstance(node.type.type, c_ast.Struct) and node.type.type.decls == None:
+			return True
+		elif isinstance(node, c_ast.Decl) and isinstance(node.type, c_ast.Struct) and \
+			 node.type.decls == None:
+			return True
+		return False
+
+	# Check if the specified struct name is opaque. If it is, declare as zero member and
+	# tell SWIG to omit ctor/dtor.
+	def _process_opaque_struct(self, name, code):
+		opaque = True
+		if not (name in FORCE_STRUCT_AS_OPAQUE):
+			for n in self.nodes[name]:
+				if not self._is_struct_opaque(n):
+					opaque = False
+					break
+		if opaque:
+			s = '%nodefaultctor ' + name + '; %nodefaultdtor ' + name + ';\n'
+			s += 'struct ' + name + ' {};\n'
+			return s
+
+		# Remove "typedef struct/enum ..." without member decl (optional)
+		if name:
+			code = code.replace('typedef struct '+name+' '+name+';\n', '', 1)
+			code = code.replace('typedef enum '+name+' '+name+';\n', '', 1)
+		return code
+	
+	def _gen_pjsua_callback(self):
+		# init
+		cbclass  = ''
+		cbproxy = ''
+		cbdef = []
+
+		n = self.nodes['pjsua_callback'][0]
+		raw_lines = self._print_node(n).splitlines()
+		for idx, line in enumerate(raw_lines):
+			if idx in [0, 1, len(raw_lines)-1]: continue
+			fstrs = []
+			# pointer to function type format
+			m = re.match('\s+(.*)\(\*(.*)\)(\(.*\));', line)
+			if m:
+				fstrs = [m.group(1).strip(), m.group(2), m.group(3)]
+			else:
+				# typedef'd format
+				m = re.match('\s+(.*)\s+(.*);', line)
+				if (not m) or (not self.nodes.has_key(m.group(1))):
+					cbdef.append('  NULL')
+					continue
+				fstrs = ['', m.group(2), '']
+				n = self.nodes[m.group(1)][0]
+				raw = self._print_node(n)
+				m = re.match('typedef\s+(.*)\(\*(.*)\)(\(.*\));', raw)
+				if not m:
+					cbdef.append('  NULL')
+					continue
+				fstrs[0] = m.group(1).strip()
+				fstrs[2] = m.group(3)
+		
+			cbclass += '  virtual ' + ' '.join(fstrs)
+			if fstrs[0] == 'void':
+				cbclass += ' {}\n'
+			elif fstrs[1] == 'on_create_media_transport':
+				cbclass += ' { return base_tp; }\n'
+			elif fstrs[1] == 'on_call_redirected':
+				cbclass += ' { return PJSIP_REDIRECT_STOP; }\n'
+			else:
+				cbclass += ' { return 0; }\n'
+
+			cbproxy += 'static ' + ' '.join(fstrs)
+			params = re.findall('(\w+)[,\)]', fstrs[2])
+			if fstrs[0] == 'void':
+				cbproxy += ' { cb->'+fstrs[1]+'('+','.join(params)+'); }\n'
+			else:
+				cbproxy += ' { return cb->'+fstrs[1]+'('+','.join(params)+'); }\n'
+
+			cbdef.append('  &' + fstrs[1])
+				
+		# trail	
+		
+		return [cbclass, cbproxy, ',\n'.join(cbdef)+'\n']
+	
+	# Generate code from the specified node.
+	def _print_node(self, node):
+		s = ''
+		if isinstance(node, c_ast.FuncDef):
+			s = self.visit(node)
+		else:
+			s = self.visit(node)
+			if s: s += ';\n'
+		return s
+
+	def go(self):
+		s = ''
+		for name in self.deps:
+			ss = ''
+			for node in self.nodes[name]:
+				ss += self._print_node(node)
+			s += self._process_opaque_struct(name, ss)
+		return s
+	
+	def write_pjsua_callback(self, outdir):
+		cb = self._gen_pjsua_callback()
+		
+		fout = open(outdir+'/callbacks.h', 'w+')
+		fin  = open('callbacks.h.template', 'r')
+		for line in fin:
+			if line.find(r'$PJSUA_CALLBACK_CLASS$') >= 0:
+				fout.write(cb[0])
+			else:
+				fout.write(line)
+		fin.close()
+		fout.close()
+
+		fout = open(outdir+'/callbacks.c', 'w+')
+		fin  = open('callbacks.c.template', 'r')
+		for line in fin:
+			if line.find(r'$PJSUA_CALLBACK_PROXY$') >= 0:
+				fout.write(cb[1])
+			elif line.find(r'$PJSUA_CALLBACK_DEF$') >= 0:
+				fout.write(cb[2])
+			else:
+				fout.write(line)
+		fin.close()
+		fout.close()
+
+# MAIN			
 ast = parse_file(SOURCE_PATH, use_cpp=True, cpp_path=CPP_PATH, cpp_args=CPP_CFLAGS)
 #ast.show(attrnames=True, nodenames=True)
Index: pjproject/branches/projects/jni/pjsip/include/pjsua-lib/pjsua.h
===================================================================
--- pjproject/branches/projects/jni/pjsip/include/pjsua-lib/pjsua.h	(revision 4556)
+++ pjproject/branches/projects/jni/pjsip/include/pjsua-lib/pjsua.h	(revision 4557)
@@ -3730,5 +3730,5 @@
  *
  * @param pool		Pool to allocate memory for the string.
- * @param contact	The string where the Contact will be stored.
+ * @param p_contact	The string where the Contact will be stored.
  * @param acc_id	Account ID.
  * @param uri		Destination URI of the request.
@@ -3737,5 +3737,5 @@
  */
 PJ_DECL(pj_status_t) pjsua_acc_create_uac_contact( pj_pool_t *pool,
-						   pj_str_t *contact,
+						   pj_str_t *p_contact,
 						   pjsua_acc_id acc_id,
 						   const pj_str_t *uri);
@@ -3748,5 +3748,5 @@
  *
  * @param pool		Pool to allocate memory for the string.
- * @param contact	The string where the Contact will be stored.
+ * @param p_contact	The string where the Contact will be stored.
  * @param acc_id	Account ID.
  * @param rdata		Incoming request.
@@ -3755,5 +3755,5 @@
  */
 PJ_DECL(pj_status_t) pjsua_acc_create_uas_contact( pj_pool_t *pool,
-						   pj_str_t *contact,
+						   pj_str_t *p_contact,
 						   pjsua_acc_id acc_id,
 						   pjsip_rx_data *rdata );
