Index: /pjproject/branches/projects/jni/pjlib/include/pj/compat/cc_dummy.h
===================================================================
--- /pjproject/branches/projects/jni/pjlib/include/pj/compat/cc_dummy.h	(revision 4541)
+++ /pjproject/branches/projects/jni/pjlib/include/pj/compat/cc_dummy.h	(revision 4541)
@@ -0,0 +1,58 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#ifndef __PJ_COMPAT_CC_DUMMY_H__
+#define __PJ_COMPAT_CC_DUMMY_H__
+
+/**
+ * @file cc_gcc.h
+ * @brief Describes GCC compiler specifics.
+ */
+
+#define PJ_CC_NAME		"dummy"
+#define PJ_CC_VER_1		1
+#define PJ_CC_VER_2		0
+#define PJ_CC_VER_3		0
+
+
+
+#define PJ_THREAD_FUNC	
+#define PJ_NORETURN		
+
+#define PJ_HAS_INT64		1
+
+typedef long long		pj_int64_t;
+typedef unsigned long long	pj_uint64_t;
+#define PJ_INLINE_SPECIFIER	static inline
+#define PJ_ATTR_NORETURN	
+
+#define PJ_INT64(val)		val
+#define PJ_UINT64(val)		val
+#define PJ_INT64_FMT		"L"
+
+
+#define PJ_HAS_BZERO		0
+
+#define PJ_UNREACHED(x)	    	
+
+#define PJ_ALIGN_DATA(declaration, alignment)
+
+
+#endif	/* __PJ_COMPAT_CC_DUMMY_H__ */
+
Index: /pjproject/branches/projects/jni/pjlib/include/pj/config.h
===================================================================
--- /pjproject/branches/projects/jni/pjlib/include/pj/config.h	(revision 4540)
+++ /pjproject/branches/projects/jni/pjlib/include/pj/config.h	(revision 4541)
@@ -42,4 +42,6 @@
 #elif defined(__ARMCC__)
 #  include <pj/compat/cc_armcc.h>
+#elif defined(CC_DUMMY)
+#  include <pj/compat/cc_dummy.h>
 #else
 #  error "Unknown compiler."
Index: /pjproject/branches/projects/jni/pjsip-apps/src/jni/Makefile
===================================================================
--- /pjproject/branches/projects/jni/pjsip-apps/src/jni/Makefile	(revision 4541)
+++ /pjproject/branches/projects/jni/pjsip-apps/src/jni/Makefile	(revision 4541)
@@ -0,0 +1,86 @@
+# $Id$
+
+# Get PJ build settings
+include ../../../build.mak
+include $(PJDIR)/build/common.mak
+
+# Env settings, e.g: path to SWIG, JDK, java(.exe), javac(.exe)
+MY_SWIG		 = swig
+MY_JDK		 = /c/Program\ Files\ \(x86\)/Java/jdk1.7.0_21
+MY_JAVA		 = $(MY_JDK)/bin/java.exe
+MY_JAVAC	 = $(MY_JDK)/bin/javac.exe
+MY_JNI_CFLAGS	 = -I$(MY_JDK)/include -I$(MY_JDK)/include/win32 -I.
+MY_JNI_LDFLAGS	 = -L$(MY_JDK)/lib -Wl,--kill-at
+
+# Choose C or C++ SWIG wrapper target, just for dev purpose.
+# Note that C target doesn't support callback, and C++ target doesn't support nested class/struct.
+SWIG_CPP_TARGET = 0
+
+# Build settings
+MY_CFLAGS	 = $(PJ_CFLAGS) $(MY_JNI_CFLAGS)
+MY_LDFLAGS	 = $(PJ_LDFLAGS) $(PJ_LDLIBS) $(MY_JNI_LDFLAGS)
+
+# Output/intermediate path settings
+MY_PACKAGE	 = org.pjsip.pjsua
+MY_OUT_DIR	 = output
+MY_SWIG_IF	 = $(MY_OUT_DIR)/pjsua.i
+MY_SWIG_FLAG	 = -Wall
+MY_SWIG_WRAPPER	 = $(MY_OUT_DIR)/pjsua_wrap
+MY_CALLBACKS	 = callbacks
+MY_PACKAGE_SRC	 = $(MY_OUT_DIR)/src/$(subst .,/,$(MY_PACKAGE))
+MY_PACKAGE_BIN	 = $(MY_OUT_DIR)/bin
+MY_JNI_LIB       = $(MY_PACKAGE_BIN)/pjsua.dll
+
+# Adjust setting for C/C++
+ifeq ($(SWIG_CPP_TARGET),1)
+MY_CC		 = $(PJ_CXX)
+MY_LDFLAGS	+= -static-libstdc++
+MY_SWIG_FLAG    += -c++ -debug-tmsearch -debug-tmused
+else
+MY_CC		 = $(PJ_CC)
+MY_SWIG_FLAG    += -debug-tmsearch -debug-tmused
+endif
+
+all: $(MY_JNI_LIB) java
+
+clean:
+	rm -rf $(MY_OUT_DIR)
+
+$(MY_SWIG_IF): header.i $(MY_SWIG_IF).tmp
+	cat header.i > $(MY_SWIG_IF)
+	cat $(MY_SWIG_IF).tmp >> $(MY_SWIG_IF)
+
+$(MY_SWIG_IF).tmp: swig_gen.py
+	@mkdir -p $(MY_OUT_DIR)
+	python swig_gen.py > $(MY_SWIG_IF).tmp
+
+$(MY_SWIG_WRAPPER).c: $(MY_SWIG_IF) $(MY_CALLBACKS).h $(MY_CALLBACKS).cpp $(MY_CALLBACKS).i
+	# Cleanup java outdir first, to remove any old/deprecated java files
+	rm -rf $(MY_PACKAGE_SRC)
+	@mkdir -p $(MY_PACKAGE_SRC)
+	$(MY_SWIG) $(MY_SWIG_FLAG) -o $(MY_SWIG_WRAPPER).c -package $(MY_PACKAGE) \
+		-outdir $(MY_PACKAGE_SRC) -java $(MY_SWIG_IF) > $(MY_SWIG_WRAPPER)-tm.txt
+	$(MY_SWIG) -c++ $(MY_SWIG_FLAG) -o $(MY_SWIG_WRAPPER)2.c -package $(MY_PACKAGE) \
+		-outdir $(MY_PACKAGE_SRC) -java $(MY_CALLBACKS).i > $(MY_SWIG_WRAPPER)2-tm.txt
+
+$(MY_SWIG_WRAPPER).o: $(MY_SWIG_WRAPPER).c
+	$(MY_CC) -c $(MY_CFLAGS) $(MY_SWIG_WRAPPER).c -o $(MY_SWIG_WRAPPER).o
+	$(PJ_CXX) -c $(MY_CFLAGS) $(MY_SWIG_WRAPPER)2.c -o $(MY_SWIG_WRAPPER)2.o
+	
+$(MY_OUT_DIR)/$(MY_CALLBACKS).o: $(MY_CALLBACKS).cpp $(MY_CALLBACKS).h
+	$(PJ_CXX) -c $(MY_CFLAGS) $(MY_CALLBACKS).cpp -o $(MY_OUT_DIR)/$(MY_CALLBACKS).o
+
+$(MY_JNI_LIB): $(MY_SWIG_WRAPPER).o $(MY_OUT_DIR)/$(MY_CALLBACKS).o
+	@mkdir -p $(MY_PACKAGE_BIN)
+	$(PJ_CXX) -shared -o $(MY_JNI_LIB) $(MY_SWIG_WRAPPER).o $(MY_OUT_DIR)/$(MY_CALLBACKS).o \
+		$(MY_SWIG_WRAPPER)2.o $(MY_LDFLAGS) -static-libstdc++
+
+java: hello.java
+	@mkdir -p $(MY_PACKAGE_BIN)
+	$(MY_JAVAC) -d $(MY_PACKAGE_BIN) $(MY_PACKAGE_SRC)/*.java
+	$(MY_JAVAC) -d $(MY_PACKAGE_BIN) -classpath "$(MY_PACKAGE_BIN)" hello.java
+
+test: $(MY_PACKAGE_BIN)/hello.class
+	# Need to specify classpath and library path, alternatively, they can be set via
+	# CLASSPATH and java.library.path env settings
+	$(MY_JAVA) -cp $(MY_PACKAGE_BIN) -Djava.library.path="$(MY_PACKAGE_BIN)" hello
Index: /pjproject/branches/projects/jni/pjsip-apps/src/jni/callbacks.cpp
===================================================================
--- /pjproject/branches/projects/jni/pjsip-apps/src/jni/callbacks.cpp	(revision 4541)
+++ /pjproject/branches/projects/jni/pjsip-apps/src/jni/callbacks.cpp	(revision 4541)
@@ -0,0 +1,20 @@
+#include "callbacks.h"
+
+static PjsuaCallback* cb = NULL;
+
+void setPjsuaCallback(PjsuaCallback* callback) {
+	cb = callback;
+}
+
+static void on_call_media_state_wrapper(pjsua_call_id call_id) {
+	cb->on_call_media_state(call_id);
+}
+
+static pjsua_callback my_cb_proxy = {
+	NULL,
+	NULL,
+	NULL,
+	&on_call_media_state_wrapper
+};
+
+pjsua_callback* PJSUA_CALLBACK_PROXY = &my_cb_proxy;
Index: /pjproject/branches/projects/jni/pjsip-apps/src/jni/callbacks.h
===================================================================
--- /pjproject/branches/projects/jni/pjsip-apps/src/jni/callbacks.h	(revision 4541)
+++ /pjproject/branches/projects/jni/pjsip-apps/src/jni/callbacks.h	(revision 4541)
@@ -0,0 +1,11 @@
+#include <pjsua-lib/pjsua.h>
+
+class PjsuaCallback {
+public:
+    virtual void on_call_media_state (pjsua_call_id call_id) {}
+    virtual ~PjsuaCallback() {}
+};
+
+extern "C" {
+void setPjsuaCallback(PjsuaCallback* callback);
+}
Index: /pjproject/branches/projects/jni/pjsip-apps/src/jni/callbacks.i
===================================================================
--- /pjproject/branches/projects/jni/pjsip-apps/src/jni/callbacks.i	(revision 4541)
+++ /pjproject/branches/projects/jni/pjsip-apps/src/jni/callbacks.i	(revision 4541)
@@ -0,0 +1,14 @@
+%module (directors="1") pjsua_cb
+
+#pragma SWIG nowarn=312		/* nested struct/class/union */
+
+%header %{
+    #include <pjsua-lib/pjsua.h>
+    #include "callbacks.h"
+%}
+
+# Get pjsua definitions
+%import "output/pjsua.i"
+
+%feature("director") PjsuaCallback;
+%include "callbacks.h"
Index: /pjproject/branches/projects/jni/pjsip-apps/src/jni/header.i
===================================================================
--- /pjproject/branches/projects/jni/pjsip-apps/src/jni/header.i	(revision 4541)
+++ /pjproject/branches/projects/jni/pjsip-apps/src/jni/header.i	(revision 4541)
@@ -0,0 +1,116 @@
+%module pjsua
+
+%include "typemaps.i"
+%include "enums.swg"
+%include "arrays_java.i"
+
+%header %{
+    #include <pjsua-lib/pjsua.h>
+    extern pjsua_callback* PJSUA_CALLBACK_PROXY;
+%}
+
+/* 'void *' shall be handled as byte arrays */
+%typemap(jni)		 void * "void *"
+%typemap(jtype) 	 void * "byte[]"
+%typemap(jstype) 	 void * "byte[]"
+%typemap(javain) 	 void * "$javainput"
+%typemap(javadirectorin) void * "$jniinput"
+%typemap(in) 		 void * { $1 = $input; }
+%typemap(out) 		 void * { $result = $1; }
+%typemap(javaout)	 void * { return $jnicall; }
+
+/* Apply output args */
+%apply unsigned	*INOUT  { unsigned *count };
+%apply unsigned *OUTPUT { unsigned *tx_level };
+%apply unsigned *OUTPUT { unsigned *rx_level };
+%apply unsigned *OUTPUT { unsigned *p_tail_ms };
+%apply int 	*OUTPUT { pjsua_acc_id *p_acc_id };
+%apply int 	*OUTPUT { pjsua_call_id *p_call_id };
+%apply int	*OUTPUT { pjsua_transport_id *p_id };
+%apply int	*OUTPUT { pjsua_recorder_id *p_id };
+%apply int 	*OUTPUT { pjsua_player_id *p_id };
+%apply int 	*OUTPUT { pjsua_buddy_id *p_buddy_id };
+%apply int 	*OUTPUT { pjsua_conf_port_id *p_id };
+%apply int 	*OUTPUT { int *capture_dev };
+%apply int 	*OUTPUT { int *playback_dev };
+%apply int 	*OUTPUT { pj_stun_nat_type * };
+%apply int[ANY] 	{ pjmedia_format_id dec_fmt_id[8] };
+
+/* Array of pj_str_t */
+JAVA_ARRAYSOFCLASSES(pj_str_t)
+#ifndef __cplusplus
+    /* On C target, pj_str_t::cArrayWrap/Unwrap Java code are missing, this somehow 'fixes' it. */
+    JAVA_ARRAYSOFCLASSES(struct pj_str_t)
+#endif
+
+/* Array of pj_ssl_cipher in pjsip_tls_setting. Warning: this breaks JAVA_ARRAYS_TYPEMAPS(int)! */
+%typemap(out) int[] %{$result = SWIG_JavaArrayOutInt(jenv, (int*)$1, arg1->ciphers_num); %}
+%apply int[] { pj_ssl_cipher* };
+%ignore pjsip_tls_setting::ciphers;
+%ignore pjsip_tls_setting::ciphers_num;
+%extend pjsip_tls_setting {
+    void setCiphers(pj_ssl_cipher *ciphers, int num) {
+        int i;
+	$self->ciphers = (pj_ssl_cipher*)calloc(num, sizeof(pj_ssl_cipher));
+	for (i=0; i<num; ++i) $self->ciphers[i] = ciphers[i];
+	$self->ciphers_num = num;
+    }
+    pj_ssl_cipher* getCiphers() {
+	return $self->ciphers;
+    }
+};
+
+
+/* C++ SWIG target doesn't support nested class (C version does though).
+ * This is minimal workaround, ignore nested class as if it is not there.
+ * TODO: proper workaround will be moving out inner classes to global scope.
+ */
+#ifdef __cplusplus
+    %nestedworkaround pjmedia_codec_fmtp::param;
+    %nestedworkaround pjsip_cred_info::ext;
+    %nestedworkaround pjsip_event::body;
+#endif
+
+/* Typemaps for marshalling pjmedia_port ** */
+%typemap(jni) pjmedia_port **p_port "jobject"
+%typemap(jtype) pjmedia_port **p_port "pjmedia_port"
+%typemap(jstype) pjmedia_port **p_port "pjmedia_port"
+
+/* Typemaps for pjmedia_port ** as a parameter output type */
+%typemap(in) pjmedia_port **p_port (pjmedia_port *ppMediaPort = 0) %{ $1 = &ppMediaPort; %}
+%typemap(argout) pjmedia_port **p_port {
+  // Give Java proxy the C pointer (of newly created object)
+  jclass clazz = JCALL1(FindClass, jenv, "org/pjsip/pjsua/pjmedia_port");
+  jfieldID fid = JCALL3(GetFieldID, jenv, clazz, "swigCPtr", "J");
+  jlong cPtr = 0;
+  *(pjmedia_port **)&cPtr = *$1;
+  JCALL3(SetLongField, jenv, $input, fid, cPtr);
+}
+%typemap(javain) pjmedia_port **p_port "$javainput"
+
+
+/* Strip "pjsua_" prefix from pjsua functions, for better compatibility with 
+ * pjsip-jni & csipsimple.
+ */
+%rename("%(strip:[pjsua_])s", %$isfunction) "";
+
+/* Automatically init pjsua_config::cb to cb proxy via pjsua_config_default() */
+/* 1. Hide 'cb' from 'pjsua_config' */
+%ignore pjsua_config::cb;
+/* 2. Ignore original pjsua_config_default() */
+%ignore pjsua_config_default;
+/* 3. Optional, put back "pjsua_" prefix, if stripping is not preferred */
+//%rename(pjsua_config_default) config_default;
+/* 4. Put custom implementation */
+%inline %{
+    void config_default(pjsua_config *cfg) {
+        pjsua_config_default(cfg);
+	cfg->cb = *PJSUA_CALLBACK_PROXY;
+    }
+%}
+
+/* Global constants */
+#define PJ_SUCCESS  0
+#define PJ_TRUE     1
+#define PJ_FALSE    0
+
Index: /pjproject/branches/projects/jni/pjsip-apps/src/jni/hello.java
===================================================================
--- /pjproject/branches/projects/jni/pjsip-apps/src/jni/hello.java	(revision 4541)
+++ /pjproject/branches/projects/jni/pjsip-apps/src/jni/hello.java	(revision 4541)
@@ -0,0 +1,140 @@
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import org.pjsip.pjsua.pjsua;
+import org.pjsip.pjsua.pjsua_acc_config;
+import org.pjsip.pjsua.pjsua_call_info;
+import org.pjsip.pjsua.pjsua_call_media_status;
+import org.pjsip.pjsua.pjsua_config;
+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;
+import org.pjsip.pjsua.pjsua_cb;
+
+class MyPjsuaCallback extends PjsuaCallback {
+	@Override
+	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());
+	    }
+	}
+}
+
+public class hello {
+	static {
+		System.loadLibrary("pjsua");
+	}
+
+	protected static void pj_error_exit(String message, int status) {
+		pjsua.perror("hello", message, status);
+		pjsua.destroy();
+		System.exit(status);
+	}
+
+	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];
+		int[] acc_id = new int[1];
+		int[] call_id = new int[1];
+		int status;
+
+		/* Say hello first */
+		System.out.println("Hello, World");
+
+		/* Create pjsua */
+		{
+			status = pjsua.create();
+			if (status != pjsua.PJ_SUCCESS) {
+				System.out.println("Error creating pjsua: " + status);
+				System.exit(status);
+			}
+		}
+		
+		/* Init pjsua */
+		{
+			pjsua_config cfg = new pjsua_config();
+			pjsua.config_default(cfg);
+			/* Setup callback for callback proxy */
+			pjsua_cb.setPjsuaCallback(new MyPjsuaCallback());
+			status = pjsua.init(cfg, null, null);
+			if (status != pjsua.PJ_SUCCESS) {
+				pj_error_exit("Error inintializing pjsua", status);
+			}
+		}
+		
+		/* Add SIP UDP transport */
+		{
+			pjsua_transport_config cfg = new pjsua_transport_config();
+			pjsua.transport_config_default(cfg);
+			cfg.setPort(6000);
+			status = pjsua.transport_create(pjsip_transport_type_e.PJSIP_TRANSPORT_UDP, cfg, tp_id);
+			if (status != pjsua.PJ_SUCCESS) {
+				pj_error_exit("Error creating transport", status);
+			}
+		}
+		
+		/* Add local account */
+		{
+			status = pjsua.acc_add_local(tp_id[0], pjsua.PJ_TRUE, acc_id);
+			if (status != pjsua.PJ_SUCCESS) {
+				pj_error_exit("Error creating local UDP account", status);
+			}
+		}
+		
+		/* Start pjsua */
+		{
+			status = pjsua.start();
+			if (status != pjsua.PJ_SUCCESS) {
+				pj_error_exit("Error starting pjsua", status);
+			}
+		}
+		
+		/* 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, null, null, call_id);
+			if (status != pjsua.PJ_SUCCESS) {
+				pj_error_exit("Error making call", status);
+			}
+		}
+		
+		/* Wait until user press "q" to quit. */
+		for (;;) {
+			String userInput;
+			BufferedReader inBuffReader = new BufferedReader(new InputStreamReader(System.in));
+			try {
+				userInput = inBuffReader.readLine();
+			} catch (IOException e) {
+				System.out.println("Error in readLine(): " + e);
+				break;
+			}
+			
+			System.out.println("Press 'h' to hangup all calls, 'q' to quit");
+			
+			if (userInput.equals("q"))
+				break;
+
+			if (userInput.equals("h"))
+				pjsua.call_hangup_all();
+		}
+
+		/* Finally, destroy pjsua */
+		{
+			pjsua.destroy();
+		}
+		
+	}
+}
Index: /pjproject/branches/projects/jni/pjsip-apps/src/jni/swig_gen.py
===================================================================
--- /pjproject/branches/projects/jni/pjsip-apps/src/jni/swig_gen.py	(revision 4541)
+++ /pjproject/branches/projects/jni/pjsip-apps/src/jni/swig_gen.py	(revision 4541)
@@ -0,0 +1,208 @@
+# $Id$
+
+#!/usr/bin/python
+
+# import re
+import sys #, os, traceback
+from collections import OrderedDict
+from pycparser import parse_file, c_ast, c_generator
+
+# Settings.
+PJ_ROOT_PATH = "../../../"
+SOURCE_PATH  = PJ_ROOT_PATH + "pjsip/include/pjsua-lib/pjsua.h"
+#SOURCE_PATH  = PJ_ROOT_PATH + "pjlib-util/include/pjlib-util/scanner.h"
+#SOURCE_PATH  = PJ_ROOT_PATH + "pjlib/include/pj/types.h"
+
+# CPP (C preprocessor) settings, CPP is needed by pycparser.
+CPP_PATH     = 'C:/devs/bin/cpp.exe' if sys.platform == 'win32' else 'cpp'
+CPP_CFLAGS   = [
+	r'-DPJ_AUTOCONF',
+	r'-DCC_DUMMY',
+	r'-Djmp_buf=int',
+	r'-IC:/devs/tools/pycparser/utils/fake_libc_include',
+	"-I" + PJ_ROOT_PATH + "pjlib/include",
+	"-I" + PJ_ROOT_PATH + "pjlib-util/include",
+	"-I" + PJ_ROOT_PATH + "pjnath/include",
+	"-I" + PJ_ROOT_PATH + "pjmedia/include",
+	"-I" + PJ_ROOT_PATH + "pjsip/include"
+	]
+
+# Any type/func names without this prefix will be excluded from the generated SWIG interface,
+# e.g: int, void.
+BASE_PREFIX = 'pj'
+
+# Any type/func names with this prefix will be treated as part of main module, i.e: they will
+# always be included in the generated SWIG interface, and will be used as starting point in
+# tracing dependencies (e.g: as struct pjsua_acc_config is part of main module, any types used
+# in its struct member, such as pj_str_t, pjsip_hdr, pj_bool_t, etc, will be included too).
+MODULE_PREFIX = 'pjsua_'
+#MODULE_PREFIX = 'pj'
+
+# If true, video related declarations (anything has '_vid_') will be removed, as long as not
+# used by main module (e.g: pjmedia_vid_dev_index type is used by pjsua_acc_config, so it won't
+# be removed).
+NO_VIDEO = True
+
+FORCE_STRUCT_AS_OPAQUE = [
+	'pj_pool_t',
+	'pj_stun_msg',
+	'pj_pool_factory',
+	'pjsip_hdr_vptr',
+	'pjsip_tpfactory',
+	'pjsip_transport',
+	'pjsip_tx_data_op_key',
+	'pjsip_rx_data_op_key',
+	'pjsip_module',
+	'pjmedia_port',
+	'pjmedia_transport',
+	'pjsua_media_transport',
+	'pjsua_callback'
+]
+
+FORCE_EXPORT = [
+	#'pj_str' # plain export result doesn't work!
+]
+
+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 ' '.join(n.names)
+
+    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
+	
+    # 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
+
+# MAIN		
+ast = parse_file(SOURCE_PATH, use_cpp=True, cpp_path=CPP_PATH, cpp_args=CPP_CFLAGS)
+#ast.show(attrnames=True, nodenames=True)
+#exit(0)
+
+mygen = MyGen(ast)
+
+#print 'Found ' + str(len(mygen.nodes)) + ' nodes:'
+#for a, b in mygen.nodes.items():
+#   print a + ':' + str(len(b))
+
+#print '\n\nFound ' + str(len(mygen.deps)) + ' dependencies:'
+#for d in mygen.deps:
+#   print d
+
+s = mygen.go()
+print s
Index: /pjproject/branches/projects/jni/pjsip/src/pjsua-lib/pjsua_core.c
===================================================================
--- /pjproject/branches/projects/jni/pjsip/src/pjsua-lib/pjsua_core.c	(revision 4540)
+++ /pjproject/branches/projects/jni/pjsip/src/pjsua-lib/pjsua_core.c	(revision 4541)
@@ -833,4 +833,8 @@
     }
 
+    /* Initialize SIP message logging, if not yet */
+    if (pjsua_var.log_cfg.msg_logging && pjsua_msg_logger.id < 0)
+	pjsip_endpt_register_module(pjsua_var.endpt, &pjsua_msg_logger);
+
 #if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \
     PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT != 0
