Index: pjproject/trunk/pjsip-apps/build/activex-pjsua.dsp
===================================================================
--- pjproject/trunk/pjsip-apps/build/activex-pjsua.dsp	(revision 487)
+++ pjproject/trunk/pjsip-apps/build/activex-pjsua.dsp	(revision 487)
@@ -0,0 +1,346 @@
+# Microsoft Developer Studio Project File - Name="activex_pjsua" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=activex_pjsua - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "activex-pjsua.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "activex-pjsua.mak" CFG="activex_pjsua - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "activex_pjsua - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "activex_pjsua - Win32 Unicode Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "activex_pjsua - Win32 Release MinSize" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "activex_pjsua - Win32 Release MinDependency" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "activex_pjsua - Win32 Unicode Release MinSize" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "activex_pjsua - Win32 Unicode Release MinDependency" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "activex_pjsua - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "./output/activex-pjsua-i386-debug"
+# PROP BASE Intermediate_Dir "./output/activex-pjsua-i386-debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "./output/activex-pjsua-i386-debug"
+# PROP Intermediate_Dir "./output/activex-pjsua-i386-debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /Yu"stdafx.h" /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "_USRDLL" /D PJ_M_I386=1 /D PJ_WIN32=1 /FR /Yu"stdafx.h" /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
+# Begin Custom Build - Performing registration
+OutDir=.\./output/activex-pjsua-i386-debug
+TargetPath=.\output\activex-pjsua-i386-debug\activex-pjsua.dll
+InputPath=.\output\activex-pjsua-i386-debug\activex-pjsua.dll
+SOURCE="$(InputPath)"
+
+"$(OutDir)\regsvr32.trg" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	regsvr32 /s /c "$(TargetPath)" 
+	echo regsvr32 exec. time > "$(OutDir)\regsvr32.trg" 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "activex_pjsua - Win32 Unicode Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir ".\output\activex-pjsua-i386-unicode-debug"
+# PROP BASE Intermediate_Dir ".\output\activex-pjsua-i386-unicode-debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ".\output\activex-pjsua-i386-unicode-debug"
+# PROP Intermediate_Dir ".\output\activex-pjsua-i386-unicode-debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_USRDLL" /D "_UNICODE" /Yu"stdafx.h" /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /D "_DEBUG" /D "_UNICODE" /D "WIN32" /D "_WINDOWS" /D "_USRDLL" /D PJ_M_I386=1 /D PJ_WIN32=1 /Yu"stdafx.h" /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
+# Begin Custom Build - Performing registration
+OutDir=.\output\activex-pjsua-i386-unicode-debug
+TargetPath=.\output\activex-pjsua-i386-unicode-debug\activex-pjsua.dll
+InputPath=.\output\activex-pjsua-i386-unicode-debug\activex-pjsua.dll
+SOURCE="$(InputPath)"
+
+"$(OutDir)\regsvr32.trg" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	if "%OS%"=="" goto NOTNT 
+	if not "%OS%"=="Windows_NT" goto NOTNT 
+	regsvr32 /s /c "$(TargetPath)" 
+	echo regsvr32 exec. time > "$(OutDir)\regsvr32.trg" 
+	goto end 
+	:NOTNT 
+	echo Warning : Cannot register Unicode DLL on Windows 95 
+	:end 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "activex_pjsua - Win32 Release MinSize"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir ".\output\activex-pjsua-i386-ReleaseMinSize"
+# PROP BASE Intermediate_Dir ".\output\activex-pjsua-i386-ReleaseMinSize"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ".\output\activex-pjsua-i386-ReleaseMinSize"
+# PROP Intermediate_Dir ".\output\activex-pjsua-i386-ReleaseMinSize"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "_ATL_DLL" /D "_ATL_MIN_CRT" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /MT /W3 /O1 /D "NDEBUG" /D "_MBCS" /D "_ATL_DLL" /D "_ATL_MIN_CRT" /D "WIN32" /D "_WINDOWS" /D "_USRDLL" /D PJ_M_I386=1 /D PJ_WIN32=1 /Yu"stdafx.h" /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
+# ADD LINK32 dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
+# Begin Custom Build - Performing registration
+OutDir=.\output\activex-pjsua-i386-ReleaseMinSize
+TargetPath=.\output\activex-pjsua-i386-ReleaseMinSize\activex-pjsua.dll
+InputPath=.\output\activex-pjsua-i386-ReleaseMinSize\activex-pjsua.dll
+SOURCE="$(InputPath)"
+
+"$(OutDir)\regsvr32.trg" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	regsvr32 /s /c "$(TargetPath)" 
+	echo regsvr32 exec. time > "$(OutDir)\regsvr32.trg" 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "activex_pjsua - Win32 Release MinDependency"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir ".\output\activex-pjsua-i386-ReleaseMinDependency"
+# PROP BASE Intermediate_Dir ".\output\activex-pjsua-i386-ReleaseMinDependency"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ".\output\activex-pjsua-i386-ReleaseMinDependency"
+# PROP Intermediate_Dir ".\output\activex-pjsua-i386-ReleaseMinDependency"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "_ATL_STATIC_REGISTRY" /D "_ATL_MIN_CRT" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /MT /W3 /O1 /D "NDEBUG" /D "_MBCS" /D "_ATL_STATIC_REGISTRY" /D "_ATL_MIN_CRT" /D "WIN32" /D "_WINDOWS" /D "_USRDLL" /D PJ_M_I386=1 /D PJ_WIN32=1 /Yu"stdafx.h" /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
+# ADD LINK32 dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
+# Begin Custom Build - Performing registration
+OutDir=.\output\activex-pjsua-i386-ReleaseMinDependency
+TargetPath=.\output\activex-pjsua-i386-ReleaseMinDependency\activex-pjsua.dll
+InputPath=.\output\activex-pjsua-i386-ReleaseMinDependency\activex-pjsua.dll
+SOURCE="$(InputPath)"
+
+"$(OutDir)\regsvr32.trg" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	regsvr32 /s /c "$(TargetPath)" 
+	echo regsvr32 exec. time > "$(OutDir)\regsvr32.trg" 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "activex_pjsua - Win32 Unicode Release MinSize"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir ".\output\activex-pjsua-i386-ReleaseUMinSize"
+# PROP BASE Intermediate_Dir ".\output\activex-pjsua-i386-ReleaseUMinSize"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ".\output\activex-pjsua-i386-ReleaseUMinSize"
+# PROP Intermediate_Dir ".\output\activex-pjsua-i386-ReleaseUMinSize"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_USRDLL" /D "_UNICODE" /D "_ATL_DLL" /D "_ATL_MIN_CRT" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /MT /W3 /O1 /D "NDEBUG" /D "_UNICODE" /D "_ATL_DLL" /D "_ATL_MIN_CRT" /D "WIN32" /D "_WINDOWS" /D "_USRDLL" /D PJ_M_I386=1 /D PJ_WIN32=1 /Yu"stdafx.h" /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
+# ADD LINK32 dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
+# Begin Custom Build - Performing registration
+OutDir=.\output\activex-pjsua-i386-ReleaseUMinSize
+TargetPath=.\output\activex-pjsua-i386-ReleaseUMinSize\activex-pjsua.dll
+InputPath=.\output\activex-pjsua-i386-ReleaseUMinSize\activex-pjsua.dll
+SOURCE="$(InputPath)"
+
+"$(OutDir)\regsvr32.trg" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	if "%OS%"=="" goto NOTNT 
+	if not "%OS%"=="Windows_NT" goto NOTNT 
+	regsvr32 /s /c "$(TargetPath)" 
+	echo regsvr32 exec. time > "$(OutDir)\regsvr32.trg" 
+	goto end 
+	:NOTNT 
+	echo Warning : Cannot register Unicode DLL on Windows 95 
+	:end 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "activex_pjsua - Win32 Unicode Release MinDependency"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir ".\output\activex-pjsua-i386-ReleaseUMinDependency"
+# PROP BASE Intermediate_Dir ".\output\activex-pjsua-i386-ReleaseUMinDependency"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ".\output\activex-pjsua-i386-ReleaseUMinDependency"
+# PROP Intermediate_Dir ".\output\activex-pjsua-i386-ReleaseUMinDependency"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_USRDLL" /D "_UNICODE" /D "_ATL_STATIC_REGISTRY" /D "_ATL_MIN_CRT" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /MT /W3 /O1 /D "NDEBUG" /D "_UNICODE" /D "_ATL_STATIC_REGISTRY" /D "_ATL_MIN_CRT" /D "WIN32" /D "_WINDOWS" /D "_USRDLL" /D PJ_M_I386=1 /D PJ_WIN32=1 /Yu"stdafx.h" /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
+# ADD LINK32 dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
+# Begin Custom Build - Performing registration
+OutDir=.\output\activex-pjsua-i386-ReleaseUMinDependency
+TargetPath=.\output\activex-pjsua-i386-ReleaseUMinDependency\activex-pjsua.dll
+InputPath=.\output\activex-pjsua-i386-ReleaseUMinDependency\activex-pjsua.dll
+SOURCE="$(InputPath)"
+
+"$(OutDir)\regsvr32.trg" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	if "%OS%"=="" goto NOTNT 
+	if not "%OS%"=="Windows_NT" goto NOTNT 
+	regsvr32 /s /c "$(TargetPath)" 
+	echo regsvr32 exec. time > "$(OutDir)\regsvr32.trg" 
+	goto end 
+	:NOTNT 
+	echo Warning : Cannot register Unicode DLL on Windows 95 
+	:end 
+	
+# End Custom Build
+
+!ENDIF 
+
+# Begin Target
+
+# Name "activex_pjsua - Win32 Debug"
+# Name "activex_pjsua - Win32 Unicode Debug"
+# Name "activex_pjsua - Win32 Release MinSize"
+# Name "activex_pjsua - Win32 Release MinDependency"
+# Name "activex_pjsua - Win32 Unicode Release MinSize"
+# Name "activex_pjsua - Win32 Unicode Release MinDependency"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\src\activex-pjsua\activex-pjsua.cpp"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\activex-pjsua\activex-pjsua.def"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\activex-pjsua\activex-pjsua.idl"
+# ADD MTL /tlb "..\src\activex-pjsua\activex-pjsua.tlb" /h "../src/activex-pjsua/activex-pjsua.h" /iid "../src/activex-pjsua/activex-pjsua_i.c" /Oicf
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\activex-pjsua\activex-pjsua.rc"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\activex-pjsua\app.cpp"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\activex-pjsua\pjsua-structs.idl"
+# ADD MTL /h "../src/activex-pjsua/pjsua-structs.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\activex-pjsua\stdafx.cpp"
+# ADD CPP /Yc"stdafx.h"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE="..\src\activex-pjsua\activex-pjsua.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\activex-pjsua\activex-pjsuaCP.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\activex-pjsua\app.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\activex-pjsua\pjsua.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\activex-pjsua\resource.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\activex-pjsua\stdafx.h"
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# Begin Source File
+
+SOURCE="..\src\activex-pjsua\app.rgs"
+# End Source File
+# End Group
+# End Target
+# End Project
Index: pjproject/trunk/pjsip-apps/build/pjsip_apps.dsw
===================================================================
--- pjproject/trunk/pjsip-apps/build/pjsip_apps.dsw	(revision 486)
+++ pjproject/trunk/pjsip-apps/build/pjsip_apps.dsw	(revision 487)
@@ -4,4 +4,40 @@
 ###############################################################################
 
+Project: "activex_pjsua"=".\activex-pjsua.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name pjlib
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name pjlib_util
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name pjmedia
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name pjmedia_codec
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name pjsip_core
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name pjsip_simple
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name pjsip_ua
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name pjsua_lib
+    End Project Dependency
+}}}
+
+###############################################################################
+
 Project: "pjlib"="..\..\pjlib\build\pjlib.dsp" - Package Owner=<4>
 
Index: pjproject/trunk/pjsip-apps/src/activex-pjsua/activex-pjsua.cpp
===================================================================
--- pjproject/trunk/pjsip-apps/src/activex-pjsua/activex-pjsua.cpp	(revision 487)
+++ pjproject/trunk/pjsip-apps/src/activex-pjsua/activex-pjsua.cpp	(revision 487)
@@ -0,0 +1,72 @@
+// ActivePJSUA.cpp : Implementation of DLL Exports.
+
+
+// Note: Proxy/Stub Information
+//      To build a separate proxy/stub DLL, 
+//      run nmake -f ActivePJSUAps.mk in the project directory.
+
+#include "stdafx.h"
+#include "resource.h"
+#include <initguid.h>
+#include "activex-pjsua.h"
+
+#include "activex-pjsua_i.c"
+#include "app.h"
+
+
+CComModule _Module;
+
+BEGIN_OBJECT_MAP(ObjectMap)
+OBJECT_ENTRY(CLSID_App, CApp)
+END_OBJECT_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// DLL Entry Point
+
+extern "C"
+BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
+{
+    if (dwReason == DLL_PROCESS_ATTACH)
+    {
+        _Module.Init(ObjectMap, hInstance, &LIBID_ACTIVEPJSUALib);
+        DisableThreadLibraryCalls(hInstance);
+    }
+    else if (dwReason == DLL_PROCESS_DETACH)
+        _Module.Term();
+    return TRUE;    // ok
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Used to determine whether the DLL can be unloaded by OLE
+
+STDAPI DllCanUnloadNow(void)
+{
+    return (_Module.GetLockCount()==0) ? S_OK : S_FALSE;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Returns a class factory to create an object of the requested type
+
+STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
+{
+    return _Module.GetClassObject(rclsid, riid, ppv);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// DllRegisterServer - Adds entries to the system registry
+
+STDAPI DllRegisterServer(void)
+{
+    // registers object, typelib and all interfaces in typelib
+    return _Module.RegisterServer(TRUE);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// DllUnregisterServer - Removes entries from the system registry
+
+STDAPI DllUnregisterServer(void)
+{
+    return _Module.UnregisterServer(TRUE);
+}
+
+
Index: pjproject/trunk/pjsip-apps/src/activex-pjsua/activex-pjsua.def
===================================================================
--- pjproject/trunk/pjsip-apps/src/activex-pjsua/activex-pjsua.def	(revision 487)
+++ pjproject/trunk/pjsip-apps/src/activex-pjsua/activex-pjsua.def	(revision 487)
@@ -0,0 +1,9 @@
+; ActivePJSUA.def : Declares the module parameters.
+
+LIBRARY      "activex-pjsua.DLL"
+
+EXPORTS
+	DllCanUnloadNow     @1 PRIVATE
+	DllGetClassObject   @2 PRIVATE
+	DllRegisterServer   @3 PRIVATE
+	DllUnregisterServer	@4 PRIVATE
Index: pjproject/trunk/pjsip-apps/src/activex-pjsua/activex-pjsua.idl
===================================================================
--- pjproject/trunk/pjsip-apps/src/activex-pjsua/activex-pjsua.idl	(revision 487)
+++ pjproject/trunk/pjsip-apps/src/activex-pjsua/activex-pjsua.idl	(revision 487)
@@ -0,0 +1,112 @@
+// ActivePJSUA.idl : IDL source for ActivePJSUA.dll
+//
+
+// This file will be processed by the MIDL tool to
+// produce the type library (ActivePJSUA.tlb) and marshalling code.
+
+import "oaidl.idl";
+import "ocidl.idl";
+import "../src/activex-pjsua/pjsua-structs.idl";
+
+
+	[
+		object,
+		uuid(93462247-DA4E-4602-817B-26BA0C824E23),
+		dual,
+		helpstring("IApp Interface"),
+		pointer_default(unique)
+	]
+	interface IApp : IDispatch
+	{
+		[id(1), helpstring("method app_create")] HRESULT app_create([out,retval] Pj_Status *retStatus);
+		[id(2), helpstring("method app_default_config")] HRESULT app_default_config([out] Pjsua_Config *pConfig);
+		[id(3), helpstring("method app_test_config")] HRESULT app_test_config([in] Pjsua_Config *pConfig, [out,retval] BSTR *errmsg);
+		[id(4), helpstring("method app_init")] HRESULT app_init([in] Pjsua_Config *pConfig, [out,retval] Pj_Status *pStatus);
+		[id(5), helpstring("method app_start")] HRESULT app_start([out,retval] Pj_Status *retStatus);
+		[id(6), helpstring("method app_destroy")] HRESULT app_destroy([out,retval] Pj_Status *retStatus);
+		[id(7), helpstring("method call_get_max_count")] HRESULT call_get_max_count([out,retval] int *retCount);
+		[id(8), helpstring("method call_get_count")] HRESULT call_get_count([out,retval] int *retCount);
+		[id(9), helpstring("method call_is_active")] HRESULT call_is_active([in] int call_index, [out,retval] Pj_Bool *retVal);
+		[id(10), helpstring("method call_has_media")] HRESULT call_has_media([in] int call_index, [out,retval] Pj_Bool *pRet);
+		[id(11), helpstring("method call_get_info")] HRESULT call_get_info([in] int call_index, [out] Pjsua_Call_Info *pInfo, [out,retval] Pj_Status *pRet);
+		[id(12), helpstring("method call_make_call")] HRESULT call_make_call([in] int acc_index, [in,string] Pj_String dst_uri, [out] int *call_index, [out,retval] Pj_Status *pRet);
+		[id(13), helpstring("method call_answer")] HRESULT call_answer([in] int call_index, [in] int status_code, [out,retval] Pj_Status *pRet);
+		[id(14), helpstring("method call_hangup")] HRESULT call_hangup([in] int call_index, [out,retval] Pj_Status *pRet);
+		[id(15), helpstring("method call_set_hold")] HRESULT call_set_hold([in] int call_index, [out,retval] Pj_Status *pRet);
+		[id(16), helpstring("method call_release_hold")] HRESULT call_release_hold([in] int call_index, [out,retval] Pj_Status *pRet);
+		[id(17), helpstring("method call_xfer")] HRESULT call_xfer([in] int call_index, [in,string] Pj_String dst_uri, [out,retval] Pj_Status *pRet);
+		[id(18), helpstring("method call_dial_dtmf")] HRESULT call_dial_dtmf([in] int call_index, [in,string] Pj_String digits, [out,retval] Pj_Status *pRet);
+		[id(19), helpstring("method call_send_im")] HRESULT call_send_im([in] int call_index, [in,string] Pj_String text, [out,retval] Pj_Status *pRet);
+		[id(20), helpstring("method call_typing")] HRESULT call_typing([in] int call_index, [in] int is_typing, [out,retval] Pj_Status *pRet);
+		[id(21), helpstring("method call_hangup_all")] HRESULT call_hangup_all();
+		[id(22), helpstring("method acc_get_count")] HRESULT acc_get_count([out,retval] int *pCount);
+		[id(23), helpstring("method acc_get_info")] HRESULT acc_get_info([in] int acc_index, [out] Pjsua_Acc_Info *pInfo, [out,retval] Pj_Status *pRet);
+		[id(24), helpstring("method acc_add")] HRESULT acc_add([in] Pjsua_Acc_Config *pConfig, [out] int *pAcc_Index, [out,retval] Pj_Status *pRet);
+		[id(25), helpstring("method acc_set_online_status")] HRESULT acc_set_online_status([in] int acc_index, [in] int is_online, [out,retval] Pj_Status *pRet);
+		[id(26), helpstring("method acc_set_registration")] HRESULT acc_set_registration([in] int acc_index, [in] int reg_active, [out,retval] Pj_Status *pRet);
+		[id(27), helpstring("method buddy_get_count")] HRESULT buddy_get_count([out,retval] int *pCount);
+		[id(28), helpstring("method buddy_get_info")] HRESULT buddy_get_info([in] int buddy_index, [out] Pjsua_Buddy_Info *pInfo, [out,retval] Pj_Status *pRet);
+		[id(29), helpstring("method buddy_add")] HRESULT buddy_add([in,string] Pj_String uri, [out] int *pBuddy_Index, [out,retval] Pj_Status *pRet);
+		[id(30), helpstring("method buddy_subscribe_pres")] HRESULT buddy_subscribe_pres([in] int buddy_index, [in] int subscribe, [out,retval] Pj_Status *pRet);
+		[id(31), helpstring("method im_send_text")] HRESULT im_send_text([in] int acc_index, [in,string] Pj_String dst_uri, [in,string] Pj_String text, [out,retval] Pj_Status *pRet);
+		[id(32), helpstring("method im_typing")] HRESULT im_typing([in] int acc_index, [in,string] Pj_URI dst_uri, [in] int is_typing, [out,retval] Pj_Status *pRet);
+		[id(33), helpstring("method conf_connect")] HRESULT conf_connect([in] int src_port, [in] int sink_port, [out,retval] Pj_Status *pRet);
+		[id(34), helpstring("method conf_disconnect")] HRESULT conf_disconnect([in] int src_port, [in] int sink_port, [out,retval] Pj_Status *pRet);
+		[id(35), helpstring("method player_create")] HRESULT player_create([in,string] Pj_String filename, [out] int *pPlayer_Id, [out,retval] Pj_Status *pRet);
+		[id(36), helpstring("method player_get_conf_port")] HRESULT player_get_conf_port([in] int player_id, [out,retval] int *pPort);
+		[id(37), helpstring("method player_set_pos")] HRESULT player_set_pos([in] int player_id, [in] int sample_pos, [out,retval] Pj_Status *pRet);
+		[id(38), helpstring("method player_destroy")] HRESULT player_destroy([in] int player_id, [out,retval] Pj_Status *pRet);
+		[id(39), helpstring("method recorder_create")] HRESULT recorder_create([in,string] Pj_String filename, [out] int *pRecorder_Id, [out,retval] Pj_Status *pRet);
+		[id(40), helpstring("method recorder_get_conf_port")] HRESULT recorder_get_conf_port([in] int recorder_id, [out,retval] int *pPort);
+		[id(41), helpstring("method recorder_destroy")] HRESULT recorder_destroy([in] int recorder_id, [out,retval] Pj_Status *pRet);
+		[id(42), helpstring("method app_load_config")] HRESULT app_load_config([in,string] Pj_String filename, [out] Pjsua_Config *pConfig, [out,retval] Pj_Status *pRet);
+		[id(43), helpstring("method app_save_config")] HRESULT app_save_config([in,string] Pj_String filename, [in] Pjsua_Config *pConfig, [out,retval] Pj_Status *pRet);
+		[id(44), helpstring("method app_get_current_config")] HRESULT app_get_current_config([out,retval] Pjsua_Config *pConfig);
+		[id(45), helpstring("method app_get_error_msg")] HRESULT app_get_error_msg([in] Pj_Status status, [out,retval] BSTR *errmsg);
+		[id(46), helpstring("method app_verify_sip_url")] HRESULT app_verify_sip_url([in,string] Pj_String uri, [out,retval] Pj_Status *pRet);
+		[id(47), helpstring("method call_get_textstat")] HRESULT call_get_textstat([in] int call_index, [out,retval] BSTR *textstat);
+		[id(48), helpstring("method app_handle_events")] HRESULT app_handle_events([in] int msec_timeout, [out,retval] int *pEvCount);
+	};
+
+[
+	uuid(11E70413-8434-41B6-A5B6-F7DF79FEFC1A),
+	version(1.0),
+	helpstring("ActivePJSUA 1.0 Type Library")
+]
+library ACTIVEPJSUALib
+{
+	importlib("stdole32.tlb");
+	importlib("stdole2.tlb");
+
+	struct Pjsip_Cred_Info;
+	struct Pjsua_Acc_Config;
+	struct Pjsua_Config;
+	struct Pjsua_Call_Info;
+	struct Pjsua_Buddy_Info;
+	struct Pjsua_Acc_Info;
+
+	[
+	    uuid(DC91CBCE-4B9E-4369-80B9-39341EEFD814),
+	    helpstring("_IPjsuaEvents Interface")
+	]
+	dispinterface _IPjsuaEvents
+	{
+	    properties:
+	    methods:
+		[id(1), helpstring("method OnCallState")] void OnCallState([in] int call_index, [in] Pjsua_Call_Info *pInfo);
+		[id(2), helpstring("method OnRegState")] void OnRegState([in] int acc_index);
+		[id(3), helpstring("method OnBuddyState")] void OnBuddyState([in] int buddy_index);
+		[id(4), helpstring("method OnIncomingPager")] void OnIncomingPager([in] int call_index, [in] BSTR fromUri, [in] BSTR toURI, [in] BSTR pagerText);
+		[id(5), helpstring("method OnTypingIndication")] void OnTypingIndication([in] int call_index, [in] BSTR fromUri, [in] BSTR toURI, [in] int isTyping);
+	};
+
+	[
+		uuid(F89DA516-42E5-43A0-8EF7-A960BA386CAB),
+		helpstring("App Class")
+	]
+	coclass App
+	{
+		[default] interface IApp;
+		[default, source] dispinterface _IPjsuaEvents;
+	};
+};
Index: pjproject/trunk/pjsip-apps/src/activex-pjsua/activex-pjsua.rc
===================================================================
--- pjproject/trunk/pjsip-apps/src/activex-pjsua/activex-pjsua.rc	(revision 487)
+++ pjproject/trunk/pjsip-apps/src/activex-pjsua/activex-pjsua.rc	(revision 487)
@@ -0,0 +1,124 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "winres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE 
+BEGIN
+    "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE 
+BEGIN
+    "#include ""winres.h""\r\n"
+    "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE 
+BEGIN
+    "1 TYPELIB ""activex-pjsua.tlb""\r\n"
+    "\0"
+END
+
+#endif    // APSTUDIO_INVOKED
+
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,0,0,1
+ PRODUCTVERSION 1,0,0,1
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "040904B0"
+        BEGIN
+            VALUE "CompanyName", "\0"
+            VALUE "FileDescription", "ActivePJSUA Module\0"
+            VALUE "FileVersion", "1, 0, 0, 1\0"
+            VALUE "InternalName", "ActivePJSUA\0"
+            VALUE "LegalCopyright", "Copyright 2006\0"
+            VALUE "OriginalFilename", "ActivePJSUA.DLL\0"
+            VALUE "ProductName", "ActivePJSUA Module\0"
+            VALUE "ProductVersion", "1, 0, 0, 1\0"
+            VALUE "OLESelfRegister", "\0"
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x409, 1200
+    END
+END
+
+#endif    // !_MAC
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// REGISTRY
+//
+
+IDR_APP                 REGISTRY DISCARDABLE    "App.rgs"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE 
+BEGIN
+    IDS_PROJNAME            "ActivePJSUA"
+END
+
+#endif    // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+1 TYPELIB "activex-pjsua.tlb"
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // not APSTUDIO_INVOKED
+
Index: pjproject/trunk/pjsip-apps/src/activex-pjsua/activex-pjsuaCP.h
===================================================================
--- pjproject/trunk/pjsip-apps/src/activex-pjsua/activex-pjsuaCP.h	(revision 487)
+++ pjproject/trunk/pjsip-apps/src/activex-pjsua/activex-pjsuaCP.h	(revision 487)
@@ -0,0 +1,151 @@
+#ifndef _ACTIVEXPJSUACP_H_
+#define _ACTIVEXPJSUACP_H_
+
+//#import "C:\project\pjproject\pjsip-apps\src\activex-pjsua\activex-pjsua.tlb" raw_interfaces_only, raw_native_types, no_namespace, named_guids	//"Import typelib"
+template <class T>
+class CProxy_IPjsuaEvents : public IConnectionPointImpl<T, &DIID__IPjsuaEvents, CComDynamicUnkArray>
+{
+	//Warning this class may be recreated by the wizard.
+public:
+	VOID Fire_OnCallState(INT call_index, Pjsua_Call_Info * pInfo)
+	{
+		T* pT = static_cast<T*>(this);
+		int nConnectionIndex;
+		CComVariant* pvars = new CComVariant[2];
+		int nConnections = m_vec.GetSize();
+		HRESULT hr;
+		
+		IRecordInfo *pRI = NULL;
+		hr = GetRecordInfoFromGuids( LIBID_ACTIVEPJSUALib,
+					1, 0, 
+					0,
+					IID_Pjsua_Call_Info,
+					&pRI );
+		assert(SUCCEEDED(hr));
+
+		pvars[1] = call_index;
+
+		VARIANT v;
+		memset(&v, 0, sizeof(v));
+		v.vt = VT_RECORD;
+		v.pRecInfo = pRI;
+		v.pvRecord = pInfo;
+
+		pvars[0] = v;
+
+		for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++)
+		{
+			pT->Lock();
+			CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);
+			pT->Unlock();
+			IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p);
+			if (pDispatch != NULL)
+			{
+				
+				DISPPARAMS disp = { pvars, NULL, 2, 0 };
+				hr = pDispatch->Invoke(0x1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, NULL, NULL, NULL);
+			}
+		}
+		delete[] pvars;
+	
+	}
+	VOID Fire_OnRegState(INT acc_index)
+	{
+		T* pT = static_cast<T*>(this);
+		int nConnectionIndex;
+		CComVariant* pvars = new CComVariant[1];
+		int nConnections = m_vec.GetSize();
+		
+		for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++)
+		{
+			pT->Lock();
+			CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);
+			pT->Unlock();
+			IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p);
+			if (pDispatch != NULL)
+			{
+				pvars[0] = acc_index;
+				DISPPARAMS disp = { pvars, NULL, 1, 0 };
+				pDispatch->Invoke(0x2, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, NULL, NULL, NULL);
+			}
+		}
+		delete[] pvars;
+	
+	}
+	VOID Fire_OnBuddyState(INT buddy_index)
+	{
+		T* pT = static_cast<T*>(this);
+		int nConnectionIndex;
+		CComVariant* pvars = new CComVariant[1];
+		int nConnections = m_vec.GetSize();
+		
+		for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++)
+		{
+			pT->Lock();
+			CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);
+			pT->Unlock();
+			IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p);
+			if (pDispatch != NULL)
+			{
+				pvars[0] = buddy_index;
+				DISPPARAMS disp = { pvars, NULL, 1, 0 };
+				pDispatch->Invoke(0x3, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, NULL, NULL, NULL);
+			}
+		}
+		delete[] pvars;
+	
+	}
+	VOID Fire_OnIncomingPager(INT call_index, BSTR fromUri, BSTR toURI, BSTR pagerText)
+	{
+		T* pT = static_cast<T*>(this);
+		int nConnectionIndex;
+		CComVariant* pvars = new CComVariant[4];
+		int nConnections = m_vec.GetSize();
+		
+		for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++)
+		{
+			pT->Lock();
+			CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);
+			pT->Unlock();
+			IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p);
+			if (pDispatch != NULL)
+			{
+				pvars[3] = call_index;
+				pvars[2] = fromUri;
+				pvars[1] = toURI;
+				pvars[0] = pagerText;
+				DISPPARAMS disp = { pvars, NULL, 4, 0 };
+				pDispatch->Invoke(0x4, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, NULL, NULL, NULL);
+			}
+		}
+		delete[] pvars;
+	
+	}
+	VOID Fire_OnTypingIndication(INT call_index, BSTR fromUri, BSTR toURI, INT isTyping)
+	{
+		T* pT = static_cast<T*>(this);
+		int nConnectionIndex;
+		CComVariant* pvars = new CComVariant[4];
+		int nConnections = m_vec.GetSize();
+		
+		for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++)
+		{
+			pT->Lock();
+			CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);
+			pT->Unlock();
+			IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p);
+			if (pDispatch != NULL)
+			{
+				pvars[3] = call_index;
+				pvars[2] = fromUri;
+				pvars[1] = toURI;
+				pvars[0] = isTyping;
+				DISPPARAMS disp = { pvars, NULL, 4, 0 };
+				pDispatch->Invoke(0x5, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, NULL, NULL, NULL);
+			}
+		}
+		delete[] pvars;
+	
+	}
+};
+#endif
Index: pjproject/trunk/pjsip-apps/src/activex-pjsua/app.cpp
===================================================================
--- pjproject/trunk/pjsip-apps/src/activex-pjsua/app.cpp	(revision 487)
+++ pjproject/trunk/pjsip-apps/src/activex-pjsua/app.cpp	(revision 487)
@@ -0,0 +1,858 @@
+// App.cpp : Implementation of CApp
+#include "stdafx.h"
+#include <pj/types.h>
+#include <pjsua-lib/pjsua.h>
+#include "activex-pjsua.h"
+#include "app.h"
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CApp
+
+// {9CE3052A-7A32-4229-B31C-5E02E0667A77}
+static const GUID IID_Pjsip_Cred_Info = 
+{ 0x9ce3052a, 0x7a32, 0x4229, { 0xb3, 0x1c, 0x5e, 0x2, 0xe0, 0x66, 0x7a, 0x77 } };
+
+// {3B12B04F-6E48-46a7-B9E0-6C4BF1594A96}
+static const GUID IID_Pjsua_Acc_Config = 
+{ 0x3b12b04f, 0x6e48, 0x46a7, { 0xb9, 0xe0, 0x6c, 0x4b, 0xf1, 0x59, 0x4a, 0x96 } };
+
+// {E4B6573D-CF5E-484d-863F-ADAD5947FBE4}
+static const GUID IID_Pjsua_Config = 
+{ 0xe4b6573d, 0xcf5e, 0x484d, { 0x86, 0x3f, 0xad, 0xad, 0x59, 0x47, 0xfb, 0xe4 } };
+
+// {5043AC9E-A417-4f03-927E-D7AE52DDD064}
+static const GUID IID_Pjsua_Call_Info = 
+{ 0x5043ac9e, 0xa417, 0x4f03, { 0x92, 0x7e, 0xd7, 0xae, 0x52, 0xdd, 0xd0, 0x64 } };
+
+// {2729F0BC-8A5E-4f3f-BC29-C1740A86393A}
+static const GUID IID_Pjsua_Buddy_Info = 
+{ 0x2729f0bc, 0x8a5e, 0x4f3f, { 0xbc, 0x29, 0xc1, 0x74, 0xa, 0x86, 0x39, 0x3a } };
+
+// {8D345956-10B7-4450-8A06-A80D2F319EFD}
+static const GUID IID_Pjsua_Acc_Info = 
+{ 0x8d345956, 0x10b7, 0x4450, { 0x8a, 0x6, 0xa8, 0xd, 0x2f, 0x31, 0x9e, 0xfd } };
+
+#define SA_SIZE(lbound,ubound)	(ubound-lbound)
+
+
+class Temp_Pool
+{
+public:
+    Temp_Pool()
+    {
+	pool_ = pjsip_endpt_create_pool( pjsua_get_pjsip_endpt(), "ActivePJSUA",
+					 4000, 4000);
+    }
+    ~Temp_Pool()
+    {
+	pj_pool_release(pool_);
+    }
+
+    pj_pool_t *get_pool()
+    {
+	return pool_;
+    }
+
+private:
+    pj_pool_t *pool_;
+};
+
+static pj_str_t Pj_str(pj_pool_t *pool, Pj_String s)
+{
+    pj_str_t ret;
+    unsigned len;
+    
+    len = wcslen(s);
+    if (len) {
+	ret.ptr = (char*)pj_pool_alloc(pool, len+1);
+	ret.slen = len;
+	pj_unicode_to_ansi(s, len, ret.ptr, len+1);
+	ret.ptr[ret.slen] = '\0';
+    } else {
+	ret.ptr = NULL;
+	ret.slen = 0;
+    }
+
+    return ret;
+}
+
+BSTR str2bstr(const char *str, unsigned len)
+{
+    if (len == 0) {
+	return SysAllocString(L"");
+    } else {
+	OLECHAR *tmp;
+	BSTR result;
+	tmp = (OLECHAR*) malloc((len+1) * sizeof(OLECHAR));
+	pj_ansi_to_unicode(str, len, tmp, len+1);
+	result = SysAllocString(tmp);
+	free(tmp);
+	return result;
+    }
+}
+
+#define Cp(d,s)	Cp2(&d,s)
+static void Cp2(BSTR *dst, const pj_str_t *src)
+{
+    *dst = str2bstr(src->ptr, src->slen);
+}
+
+
+
+static void SafeStringArray2pjstrarray(pj_pool_t *pool,
+				       SAFEARRAY *sa, unsigned *count,
+				       pj_str_t a[])
+{
+    if (!sa)
+	*count = 0;
+    else {
+	HRESULT hr;
+	long lbound;
+	unsigned i;
+
+	hr = SafeArrayGetLBound(sa, 1, &lbound);
+	if (FAILED(hr))
+	    *count = 0;
+	else {
+	    *count = 0;
+	    for (i=0; i<sa->cbElements; ++i) {
+		BSTR str;
+		long rg = lbound + i;
+		hr = SafeArrayGetElement(sa, &rg, &str);
+		if (FAILED(hr))
+		    break;
+		a[*count] = Pj_str(pool, str);
+		*count = *count + 1;
+	    }
+	}
+    }
+}
+
+static void pjstrarray2SafeStringArray(unsigned count, const pj_str_t a[],
+				       SAFEARRAY **psa)
+{
+    unsigned i;
+    SAFEARRAY *sa;
+
+    sa = SafeArrayCreateVector( VT_BSTR, 0, count);
+
+    for (i=0; i<count; ++i) {
+	BSTR value;
+	Cp(value, &a[i]);
+	long rg = i;
+	SafeArrayPutElement(sa, &rg, value);
+    }
+
+    *psa = sa;
+}
+
+static void AccConfig2accconfig(pj_pool_t *pool,
+				Pjsua_Acc_Config *c1,
+				pjsua_acc_config *c2)
+{
+    pj_memset(c2, 0, sizeof(pjsua_acc_config));
+
+    c2->id = Pj_str(pool, c1->acc_uri);
+    c2->reg_uri = Pj_str(pool, c1->reg_uri);
+    c2->contact = Pj_str(pool, c1->contact_uri);
+    c2->proxy = Pj_str(pool, c1->proxy_uri);
+    c2->reg_timeout = c1->reg_timeout;
+
+    if (c1->cred_info == NULL) {
+	c2->cred_count = 0;
+    } else {
+	unsigned i;
+	long lbound;
+	HRESULT hr;
+
+	hr = SafeArrayGetLBound(c1->cred_info, 1, &lbound);
+	if (FAILED(hr)) {
+	    c2->cred_count = 0;
+	} else {
+	    c2->cred_count = 0;
+	    for (i=0; i<c1->cred_info->cbElements; ++i) {
+		Pjsip_Cred_Info cred_info;
+		long rg = lbound + i;
+		hr = SafeArrayGetElement(c1->cred_info, &rg, &cred_info);
+		if (FAILED(hr))
+		    break;
+		c2->cred_info[i].realm = Pj_str(pool, cred_info.realm);
+		c2->cred_info[i].scheme = Pj_str(pool, cred_info.scheme);
+		c2->cred_info[i].username = Pj_str(pool, cred_info.username);
+		c2->cred_info[i].data_type = cred_info.hashed;
+		c2->cred_info[i].data = Pj_str(pool, cred_info.data);
+	    }
+	    c2->cred_count = i;
+	}
+    }
+}
+
+static HRESULT accconfig2AccConfig(pjsua_acc_config *c1,
+				  Pjsua_Acc_Config *c2)
+{
+    unsigned i;
+
+    //pj_memset(c2, 0, sizeof(Pjsua_Acc_Config));
+
+    Cp(c2->acc_uri, &c1->id);
+    Cp(c2->reg_uri, &c1->reg_uri);
+    Cp(c2->contact_uri, &c1->contact);
+    Cp(c2->proxy_uri, &c1->proxy);
+    c2->reg_timeout = c1->reg_timeout;
+
+
+    IRecordInfo *pUdtRecordInfo = NULL;
+    HRESULT hr = GetRecordInfoFromGuids( LIBID_ACTIVEPJSUALib,
+                                         1, 0, 
+                                         0,
+                                         IID_Pjsip_Cred_Info,
+                                         &pUdtRecordInfo );
+    if( FAILED( hr ) ) {
+        return( hr ); //Return original HRESULT hr2 is for debug only
+    }
+
+    SAFEARRAYBOUND rgsabound[1];
+    rgsabound[0].lLbound = 0;
+    rgsabound[0].cElements = c1->cred_count;
+
+    c2->cred_info = ::SafeArrayCreateEx( VT_RECORD, 1, rgsabound, pUdtRecordInfo );
+
+    pUdtRecordInfo->Release(); //do not forget to release the interface
+
+    for (i=0; i<c1->cred_count; ++i) {
+	Pjsip_Cred_Info cred_info;
+
+	Cp(cred_info.realm, &c1->cred_info[i].realm);
+	Cp(cred_info.scheme, &c1->cred_info[i].scheme);
+	Cp(cred_info.username, &c1->cred_info[i].username);
+	cred_info.hashed = (c1->cred_info[i].data_type != 0);
+	Cp(cred_info.data, &c1->cred_info[i].data);
+
+	long rg = i;
+	SafeArrayPutElement(c2->cred_info, &rg, &cred_info);
+    }
+
+    return S_OK;
+}
+
+static HRESULT Config2config(pj_pool_t *pool, Pjsua_Config *c1, pjsua_config *c2)
+{
+    pj_memset(c2, 0, sizeof(pjsua_config));
+
+    c2->udp_port = c1->udp_port;
+    c2->sip_host = Pj_str(pool, c1->sip_host);
+    c2->sip_port = c1->sip_port;
+    c2->start_rtp_port = c1->rtp_port;
+    c2->max_calls = c1->max_calls;
+    c2->conf_ports = c1->conf_ports;
+    c2->thread_cnt = c1->thread_cnt;
+    c2->stun_srv1 = Pj_str(pool, c1->stun_srv1);
+    c2->stun_port1 = c1->stun_port1;
+    c2->stun_srv2 = Pj_str(pool, c1->stun_srv2);
+    c2->stun_port2 = c1->stun_port2;
+    c2->snd_player_id = c1->snd_player_id;
+    c2->snd_capture_id = c1->snd_capture_id;
+    c2->clock_rate = c1->clock_rate;
+    c2->null_audio = c1->null_audio;
+    c2->quality = c1->quality;
+    c2->complexity = c1->complexity;
+
+    SafeStringArray2pjstrarray(pool, c1->codec_arg, &c2->codec_cnt, c2->codec_arg);
+
+    c2->auto_answer = c1->auto_answer;
+    c2->uas_refresh = c1->uas_refresh;
+    c2->outbound_proxy = Pj_str(pool, c1->outbound_proxy);
+
+    if (!c1->acc_config)
+	c2->acc_cnt = 0;
+    else {
+	HRESULT hr;
+	long lbound;
+	unsigned i;
+
+	hr = SafeArrayGetLBound(c1->acc_config, 1, &lbound);
+	if (FAILED(hr))
+	    c2->acc_cnt = 0;
+	else {
+	    c2->acc_cnt = 0;
+
+	    for (i=0; i<c1->acc_config->cbElements; ++i) {
+		Pjsua_Acc_Config acc_config;
+		long rg = lbound + i;
+		hr = SafeArrayGetElement(c1->acc_config, &rg, &acc_config);
+		if (FAILED(hr))
+		    break;
+		AccConfig2accconfig(pool, &acc_config, &c2->acc_config[i]);
+	    }
+
+	    c2->acc_cnt = i;
+	}
+    }
+
+    c2->log_level = c1->log_level;
+    c2->app_log_level = c1->app_log_level;
+    c2->log_decor = c1->log_decor;
+    c2->log_filename = Pj_str(pool, c1->log_filename);
+
+    SafeStringArray2pjstrarray(pool, c1->buddy_uri, &c2->buddy_cnt, c2->buddy_uri);
+
+    return S_OK;
+}
+
+static HRESULT config2Config(pjsua_config *c1, Pjsua_Config *c2)
+{
+    unsigned i;
+    HRESULT hr;
+
+    //pj_memset(c2, 0, sizeof(Pjsua_Config));
+
+    c2->udp_port = c1->udp_port;
+    Cp(c2->sip_host, &c1->sip_host);
+    c2->sip_port = c1->sip_port;
+    c2->rtp_port = c1->start_rtp_port;
+    c2->max_calls = c1->max_calls;
+    c2->conf_ports = c1->conf_ports;
+    c2->thread_cnt = c1->thread_cnt;
+    Cp(c2->stun_srv1, &c1->stun_srv1);
+    c2->stun_port1 = c1->stun_port1;
+    Cp(c2->stun_srv2, &c1->stun_srv2);
+    c2->stun_port2 = c1->stun_port2;
+    c2->snd_player_id = c1->snd_player_id;
+    c2->snd_capture_id = c1->snd_capture_id;
+    c2->clock_rate = c1->clock_rate;
+    c2->null_audio = c1->null_audio;
+    c2->quality = c1->quality;
+    c2->complexity = c1->complexity;
+
+    pjstrarray2SafeStringArray(c1->codec_cnt, c1->codec_arg, &c2->codec_arg);
+
+    c2->auto_answer = c1->auto_answer;
+    c2->uas_refresh = c1->uas_refresh;
+
+    Cp(c2->outbound_proxy, &c1->outbound_proxy);
+
+    IRecordInfo *pUdtRecordInfo = NULL;
+    hr = GetRecordInfoFromGuids( LIBID_ACTIVEPJSUALib,
+                                 1, 0, 
+                                 0,
+                                 IID_Pjsua_Acc_Config,
+                                 &pUdtRecordInfo );
+    if( FAILED( hr ) ) {
+        return( hr ); //Return original HRESULT hr2 is for debug only
+    }
+
+    SAFEARRAYBOUND rgsabound[1];
+    rgsabound[0].lLbound = 0;
+    rgsabound[0].cElements = c1->acc_cnt;
+
+    c2->acc_config = ::SafeArrayCreateEx( VT_RECORD, 1, rgsabound, pUdtRecordInfo );
+
+    pUdtRecordInfo->Release(); //do not forget to release the interface
+
+    for (i=0; i<c1->acc_cnt; ++i) {
+	Pjsua_Acc_Config acc_cfg;
+
+	hr = accconfig2AccConfig(&c1->acc_config[i], &acc_cfg);
+	if (FAILED(hr))
+	    return hr;
+
+	long rg = i;
+	SafeArrayPutElement(c2->acc_config, &rg, &acc_cfg);
+    }
+
+
+    c2->log_level = c1->log_level;
+    c2->app_log_level = c1->app_log_level;
+    c2->log_decor = c1->log_decor;
+
+    Cp(c2->log_filename, &c1->log_filename);
+
+    pjstrarray2SafeStringArray(c1->buddy_cnt, c1->buddy_uri, &c2->buddy_uri);
+
+    return S_OK;
+}
+
+static void callinfo2CallInfo(pjsua_call_info *c1, Pjsua_Call_Info *c2)
+{
+    pj_memset(c2, 0, sizeof(Pjsua_Call_Info));
+
+    c2->index = c1->index;
+    c2->active = c1->active;
+    c2->is_uac = (c1->role == PJSIP_ROLE_UAC);
+    Cp(c2->local_info, &c1->local_info);
+    Cp(c2->remote_info, &c1->remote_info);
+    c2->state = (Pjsua_Call_State)c1->state;
+    Cp(c2->state_text, &c1->state_text);
+    c2->connect_duration = c1->connect_duration.sec;
+    c2->total_duration = c1->total_duration.sec;
+    c2->cause = c1->cause;
+    Cp(c2->cause_text, &c1->cause_text);
+    c2->has_media = c1->has_media;
+    c2->conf_slot = c1->conf_slot;
+}
+
+static void accinfo2AccInfo(pjsua_acc_info *info1, Pjsua_Acc_Info *info2)
+{
+    pj_memset(info2, 0, sizeof(Pjsua_Acc_Info));
+
+    info2->index = info1->index;
+    Cp(info2->acc_id, &info1->acc_id);
+    info2->has_registration = info1->has_registration;
+    info2->expires = info1->expires;
+    info2->status_code = info1->status;
+    Cp(info2->status_text, &info1->status_text);
+    info2->online_status = info1->online_status;
+}
+
+static void buddyinfo2BuddyInfo(pjsua_buddy_info *info1, Pjsua_Buddy_Info *info2)
+{
+    pj_memset(info2, 0, sizeof(Pjsua_Buddy_Info));
+
+    info2->index = info1->index;
+    info2->is_valid = info1->is_valid;
+    Cp(info2->name, &info1->name);
+    Cp(info2->display, &info1->display_name);
+    Cp(info2->host, &info1->host);
+    info2->port = info1->port;
+    Cp(info2->uri, &info1->uri);
+    info2->status = (Pjsua_Buddy_State)info1->status;
+    Cp(info2->status_text, &info1->status_text);
+    info2->monitor = info1->monitor;
+    info2->acc_index = info1->acc_index;
+}
+
+static CApp *CApp_Instance;
+
+CApp::CApp()
+{
+    CApp_Instance = this;
+}
+
+STDMETHODIMP CApp::app_create(Pj_Status *ret)
+{
+    *ret = pjsua_create();
+    return S_OK;
+}
+
+STDMETHODIMP CApp::app_default_config(Pjsua_Config *pConfig)
+{
+    pjsua_config cfg;
+    pjsua_default_config(&cfg);
+    return config2Config(&cfg, pConfig);
+}
+
+STDMETHODIMP CApp::app_test_config(Pjsua_Config *pConfig, BSTR *retmsg)
+{
+    pjsua_config cfg;
+    HRESULT hr;
+    Temp_Pool tp;
+    char errmsg[PJ_ERR_MSG_SIZE];
+
+    hr = Config2config(tp.get_pool(), pConfig, &cfg);
+    if (FAILED(hr))
+	return hr;
+
+    pjsua_test_config(&cfg, errmsg, sizeof(errmsg));
+    *retmsg = str2bstr(errmsg, strlen(errmsg));
+    return S_OK;
+}
+
+static void on_call_state(int call_index, pjsip_event *e)
+{
+    pjsua_call_info call_info;
+    Pjsua_Call_Info *Call_Info = new Pjsua_Call_Info;
+
+    pjsua_get_call_info(call_index, &call_info);
+    callinfo2CallInfo(&call_info, Call_Info);
+
+    CApp_Instance->Fire_OnCallState(call_index, Call_Info);
+}
+
+static void on_reg_state(int acc_index)
+{
+    CApp_Instance->Fire_OnRegState(acc_index);
+}
+
+static void on_buddy_state(int buddy_index)
+{
+    CApp_Instance->Fire_OnBuddyState(buddy_index);
+}
+
+static void on_pager(int call_index, const pj_str_t *from,
+		     const pj_str_t *to, const pj_str_t *txt)
+{
+    BSTR fromURI, toURI, imText;
+
+    Cp2(&fromURI, from);
+    Cp2(&toURI, to);
+    Cp2(&imText, txt);
+
+    CApp_Instance->Fire_OnIncomingPager(call_index, fromURI, toURI, imText);
+}
+
+static void on_typing(int call_index, const pj_str_t *from,
+		      const pj_str_t *to, pj_bool_t is_typing)
+{
+    BSTR fromURI, toURI;
+
+    Cp2(&fromURI, from);
+    Cp2(&toURI, to);
+
+    CApp_Instance->Fire_OnTypingIndication(call_index, fromURI, toURI, is_typing);
+}
+
+
+STDMETHODIMP CApp::app_init(Pjsua_Config *pConfig, Pj_Status *pStatus)
+{
+    pjsua_config cfg;
+    pjsua_callback cb;
+    Temp_Pool tp;
+    HRESULT hr;
+
+    pj_memset(&cb, 0, sizeof(cb));
+    cb.on_call_state = &on_call_state;
+    cb.on_reg_state = &on_reg_state;
+    cb.on_buddy_state = &on_buddy_state;
+    cb.on_pager = &on_pager;
+    cb.on_typing = &on_typing;
+
+    hr = Config2config(tp.get_pool(), pConfig, &cfg);
+    if (FAILED(hr))
+	return hr;
+    
+    *pStatus = pjsua_init(&cfg, &cb);
+    return S_OK;
+}
+
+STDMETHODIMP CApp::app_start(Pj_Status *retStatus)
+{
+    *retStatus = pjsua_start();
+    return S_OK;
+}
+
+STDMETHODIMP CApp::app_destroy(Pj_Status *retStatus)
+{
+    *retStatus = pjsua_destroy();
+    return S_OK;
+}
+
+STDMETHODIMP CApp::call_get_max_count(int *retCount)
+{
+    *retCount = pjsua_get_max_calls();
+    return S_OK;
+}
+
+STDMETHODIMP CApp::call_get_count(int *retCount)
+{
+    *retCount = pjsua_get_call_count();
+    return S_OK;
+}
+
+STDMETHODIMP CApp::call_is_active(int call_index, Pj_Bool *retVal)
+{
+    *retVal = pjsua_call_is_active(call_index);
+    return S_OK;
+}
+
+STDMETHODIMP CApp::call_has_media(int call_index, Pj_Bool *pRet)
+{
+    *pRet = pjsua_call_has_media(call_index);
+    return S_OK;
+}
+
+STDMETHODIMP CApp::call_get_info(int call_index, Pjsua_Call_Info *pInfo, Pj_Status *pRet)
+{
+    pjsua_call_info info;
+    *pRet = pjsua_get_call_info(call_index, &info);
+    callinfo2CallInfo(&info, pInfo);
+    return S_OK;
+}
+
+STDMETHODIMP CApp::call_make_call(int acc_index, Pj_String dst_uri, int *call_index, Pj_Status *pRet)
+{
+    Temp_Pool tp;
+    pj_str_t tmp = Pj_str(tp.get_pool(), dst_uri);
+
+    *pRet = pjsua_make_call(acc_index, &tmp, call_index);
+    return S_OK;
+}
+
+STDMETHODIMP CApp::call_answer(int call_index, int status_code, Pj_Status *pRet)
+{
+    pjsua_call_answer(call_index, status_code);
+    *pRet = PJ_SUCCESS;
+    return S_OK;
+}
+
+STDMETHODIMP CApp::call_hangup(int call_index, Pj_Status *pRet)
+{
+    pjsua_call_hangup(call_index);
+    *pRet = PJ_SUCCESS;
+    return S_OK;
+}
+
+STDMETHODIMP CApp::call_set_hold(int call_index, Pj_Status *pRet)
+{
+    pjsua_call_set_hold(call_index);
+    *pRet = PJ_SUCCESS;
+    return S_OK;
+}
+
+STDMETHODIMP CApp::call_release_hold(int call_index, Pj_Status *pRet)
+{
+    pjsua_call_reinvite(call_index);
+    *pRet = PJ_SUCCESS;
+    return S_OK;
+}
+
+STDMETHODIMP CApp::call_xfer(int call_index, Pj_String dst_uri, Pj_Status *pRet)
+{
+    Temp_Pool tp;
+    pj_str_t tmp = Pj_str(tp.get_pool(), dst_uri);
+    pjsua_call_xfer(call_index, &tmp);
+    *pRet = PJ_SUCCESS;
+    return S_OK;
+}
+
+STDMETHODIMP CApp::call_dial_dtmf(int call_index, Pj_String digits, Pj_Status *pRet)
+{
+    Temp_Pool tp;
+    pj_str_t tmp = Pj_str(tp.get_pool(), digits);
+    *pRet = pjsua_call_dial_dtmf(call_index, &tmp);
+    return S_OK;
+}
+
+STDMETHODIMP CApp::call_send_im(int call_index, Pj_String text, Pj_Status *pRet)
+{
+    Temp_Pool tp;
+    pj_str_t tmp = Pj_str(tp.get_pool(), text);
+    pjsua_call_send_im(call_index, &tmp);
+    *pRet = PJ_SUCCESS;
+    return S_OK;
+}
+
+STDMETHODIMP CApp::call_typing(int call_index, int is_typing, Pj_Status *pRet)
+{
+    pjsua_call_typing(call_index, is_typing);
+    *pRet = PJ_SUCCESS;
+    return S_OK;
+}
+
+STDMETHODIMP CApp::call_hangup_all()
+{
+    pjsua_call_hangup_all();
+    return S_OK;
+}
+
+STDMETHODIMP CApp::call_get_textstat(int call_index, BSTR *textstat)
+{
+    char buf[1024];
+    pjsua_dump_call(call_index, 1, buf, sizeof(buf), "");
+
+    OLECHAR wbuf[1024];
+    pj_ansi_to_unicode(buf, strlen(buf), wbuf, PJ_ARRAY_SIZE(wbuf));
+    *textstat = SysAllocString(wbuf);
+    return S_OK;
+}
+
+
+STDMETHODIMP CApp::acc_get_count(int *pCount)
+{
+    *pCount = pjsua_get_acc_count();
+    return S_OK;
+}
+
+STDMETHODIMP CApp::acc_get_info(int acc_index, Pjsua_Acc_Info *pInfo, Pj_Status *pRet)
+{
+    pjsua_acc_info info;
+    *pRet = pjsua_acc_get_info(acc_index, &info);
+    accinfo2AccInfo(&info, pInfo);
+    return S_OK;
+}
+
+STDMETHODIMP CApp::acc_add(Pjsua_Acc_Config *pConfig, int *pAcc_Index, Pj_Status *pRet)
+{
+    Temp_Pool tp;
+    pjsua_acc_config config;
+    AccConfig2accconfig(tp.get_pool(), pConfig,  &config);
+    *pRet = pjsua_acc_add(&config, pAcc_Index);
+    return S_OK;
+}
+
+STDMETHODIMP CApp::acc_set_online_status(int acc_index, int is_online, Pj_Status *pRet)
+{
+    *pRet = pjsua_acc_set_online_status(acc_index, is_online);
+    return S_OK;
+}
+
+STDMETHODIMP CApp::acc_set_registration(int acc_index, int reg_active, Pj_Status *pRet)
+{
+    *pRet = pjsua_acc_set_registration(acc_index, reg_active);
+    return S_OK;
+}
+
+STDMETHODIMP CApp::buddy_get_count(int *pCount)
+{
+    *pCount = pjsua_get_buddy_count();
+    return S_OK;
+}
+
+STDMETHODIMP CApp::buddy_get_info(int buddy_index, Pjsua_Buddy_Info *pInfo, Pj_Status *pRet)
+{
+    pjsua_buddy_info info;
+    *pRet = pjsua_buddy_get_info(buddy_index, &info);
+    buddyinfo2BuddyInfo(&info, pInfo);
+    return S_OK;
+}
+
+STDMETHODIMP CApp::buddy_add(Pj_String uri, int *pBuddy_Index, Pj_Status *pRet)
+{
+    Temp_Pool tp;
+    pj_str_t tmp = Pj_str(tp.get_pool(), uri);
+    *pRet = pjsua_buddy_add(&tmp, pBuddy_Index);
+    return S_OK;
+}
+
+STDMETHODIMP CApp::buddy_subscribe_pres(int buddy_index, int subscribe, Pj_Status *pRet)
+{
+    *pRet = pjsua_buddy_subscribe_pres(buddy_index, subscribe);
+    pjsua_pres_refresh();
+    return S_OK;
+}
+
+STDMETHODIMP CApp::im_send_text(int acc_index, Pj_String dst_uri, Pj_String text, Pj_Status *pRet)
+{
+    Temp_Pool tp;
+    pj_str_t tmp_uri = Pj_str(tp.get_pool(), dst_uri);
+    pj_str_t tmp_text = Pj_str(tp.get_pool(), text);
+    *pRet = pjsua_im_send(acc_index, &tmp_uri, &tmp_text);
+    return S_OK;
+}
+
+STDMETHODIMP CApp::im_typing(int acc_index, Pj_URI dst_uri, int is_typing, Pj_Status *pRet)
+{
+    Temp_Pool tp;
+    pj_str_t tmp_uri = Pj_str(tp.get_pool(), dst_uri);
+    *pRet = pjsua_im_typing(acc_index, &tmp_uri, is_typing);
+    return S_OK;
+}
+
+STDMETHODIMP CApp::conf_connect(int src_port, int sink_port, Pj_Status *pRet)
+{
+    *pRet = pjsua_conf_connect(src_port, sink_port);
+    return S_OK;
+}
+
+STDMETHODIMP CApp::conf_disconnect(int src_port, int sink_port, Pj_Status *pRet)
+{
+    *pRet = pjsua_conf_disconnect(src_port, sink_port);
+    return S_OK;
+}
+
+STDMETHODIMP CApp::player_create(Pj_String filename, int *pPlayer_Id, Pj_Status *pRet)
+{
+    Temp_Pool tp;
+    pj_str_t tmp = Pj_str(tp.get_pool(), filename);
+    *pRet = pjsua_player_create(&tmp, pPlayer_Id);
+    return S_OK;
+}
+
+STDMETHODIMP CApp::player_get_conf_port(int player_id, int *pPort)
+{
+    *pPort = pjsua_player_get_conf_port(player_id);
+    return S_OK;
+}
+
+STDMETHODIMP CApp::player_set_pos(int player_id, int pos, Pj_Status *pRet)
+{
+    *pRet = pjsua_player_set_pos(player_id, pos);
+    return S_OK;
+}
+
+STDMETHODIMP CApp::player_destroy(int player_id, Pj_Status *pRet)
+{
+    *pRet = pjsua_player_destroy(player_id);
+    return S_OK;
+}
+
+STDMETHODIMP CApp::recorder_create(Pj_String filename, int *pRecorder_Id, Pj_Status *pRet)
+{
+    Temp_Pool tp;
+    pj_str_t tmp = Pj_str(tp.get_pool(), filename);
+    *pRet = pjsua_recorder_create(&tmp, pRecorder_Id);
+    return S_OK;
+}
+
+STDMETHODIMP CApp::recorder_get_conf_port(int recorder_id, int *pPort)
+{
+    *pPort = pjsua_recorder_get_conf_port(recorder_id);
+    return S_OK;
+}
+
+STDMETHODIMP CApp::recorder_destroy(int recorder_id, Pj_Status *pRet)
+{
+    *pRet = pjsua_recorder_destroy(recorder_id);
+    return S_OK;
+}
+
+STDMETHODIMP CApp::app_load_config(Pj_String filename, Pjsua_Config *pConfig, Pj_Status *pRet)
+{
+    pjsua_config config;
+    Temp_Pool tp;
+    pj_str_t tmp = Pj_str(tp.get_pool(), filename);
+    pjsua_default_config(&config);
+    *pRet = pjsua_load_settings(tmp.ptr, &config);
+    if (*pRet == PJ_SUCCESS)
+	*pRet = config2Config(&config, pConfig);
+    return S_OK;
+}
+
+STDMETHODIMP CApp::app_save_config(Pj_String filename, Pjsua_Config *pConfig, Pj_Status *pRet)
+{
+    Temp_Pool tp;
+    pjsua_config config;
+    pj_str_t tmp = Pj_str(tp.get_pool(), filename);
+    HRESULT hr;
+
+    hr = Config2config(tp.get_pool(), pConfig, &config);
+    if (FAILED(hr))
+	return hr;
+
+    *pRet = pjsua_save_settings(tmp.ptr, &config);
+    return S_OK;
+}
+
+STDMETHODIMP CApp::app_get_current_config(Pjsua_Config *pConfig)
+{
+    pjsua_config *config;
+    config = (pjsua_config*) pjsua_get_config();
+    return config2Config(config, pConfig);
+}
+
+STDMETHODIMP CApp::app_get_error_msg(Pj_Status status, BSTR * pRet)
+{
+    char errmsg[PJ_ERR_MSG_SIZE];
+    OLECHAR werrmsg[PJ_ERR_MSG_SIZE];
+    pj_strerror(status, errmsg, sizeof(errmsg));
+    pj_ansi_to_unicode(errmsg, strlen(errmsg), werrmsg, PJ_ARRAY_SIZE(werrmsg));
+    *pRet = SysAllocString(werrmsg);
+    return S_OK;
+}
+
+STDMETHODIMP CApp::app_verify_sip_url(Pj_String uri, Pj_Status *pRet)
+{
+    Temp_Pool tp;
+    pj_str_t tmp = Pj_str(tp.get_pool(), uri);
+    *pRet = pjsua_verify_sip_url(tmp.ptr);
+    return S_OK;
+}
+
+STDMETHODIMP CApp::app_handle_events(int msec_timeout, int *pEvCount)
+{
+    if (msec_timeout < 0)
+	msec_timeout = 0;
+
+    *pEvCount = pjsua_handle_events(msec_timeout);
+    return S_OK;
+}
Index: pjproject/trunk/pjsip-apps/src/activex-pjsua/app.h
===================================================================
--- pjproject/trunk/pjsip-apps/src/activex-pjsua/app.h	(revision 487)
+++ pjproject/trunk/pjsip-apps/src/activex-pjsua/app.h	(revision 487)
@@ -0,0 +1,91 @@
+// App.h : Declaration of the CApp
+
+#ifndef __APP_H_
+#define __APP_H_
+
+#include "resource.h"       // main symbols
+#include "..\activex-pjsua\activex-pjsuaCP.h"
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CApp
+class ATL_NO_VTABLE CApp : 
+	public CComObjectRootEx<CComSingleThreadModel>,
+	public CComCoClass<CApp, &CLSID_App>,
+	public IConnectionPointContainerImpl<CApp>,
+	public IDispatchImpl<IApp, &IID_IApp, &LIBID_ACTIVEPJSUALib>,
+	public CProxy_IPjsuaEvents<CApp>
+{
+public:
+	CApp();
+
+DECLARE_REGISTRY_RESOURCEID(IDR_APP)
+
+DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+BEGIN_COM_MAP(CApp)
+	COM_INTERFACE_ENTRY(IApp)
+	COM_INTERFACE_ENTRY(IDispatch)
+	COM_INTERFACE_ENTRY(IConnectionPointContainer)
+	COM_INTERFACE_ENTRY_IMPL(IConnectionPointContainer)
+END_COM_MAP()
+
+BEGIN_CONNECTION_POINT_MAP(CApp)
+CONNECTION_POINT_ENTRY(DIID__IPjsuaEvents)
+END_CONNECTION_POINT_MAP()
+
+
+// IApp
+public:
+	STDMETHOD(app_handle_events)(/*[in]*/ int msec_timeout, /*[out,retval]*/ int *pEvCount);
+	STDMETHOD(app_verify_sip_url)(/*[in,string]*/ Pj_String uri, /*[out,retval]*/ Pj_Status *pRet);
+	STDMETHOD(app_get_error_msg)(/*[in]*/ Pj_Status status, /*[out,retval]*/ BSTR * errmsg);
+	STDMETHOD(app_get_current_config)(/*[out,retval]*/ Pjsua_Config *pConfig);
+	STDMETHOD(app_save_config)(/*[in,string]*/ Pj_String filename, /*[in]*/ Pjsua_Config *pConfig, /*[out,retval]*/ Pj_Status *pRet);
+	STDMETHOD(app_load_config)(/*[in,string]*/ Pj_String filename, /*[out]*/ Pjsua_Config *pConfig, /*[out,retval]*/ Pj_Status *pRet);
+	STDMETHOD(recorder_destroy)(/*[in]*/ int recorder_id, /*[out,retval]*/ Pj_Status *pRet);
+	STDMETHOD(recorder_get_conf_port)(/*[in]*/ int recorder_id, /*[out,retval]*/ int *pPort);
+	STDMETHOD(recorder_create)(/*[in,string]*/ Pj_String filename, /*[out]*/ int *pRecorder_Id, /*[out,retval]*/ Pj_Status *pRet);
+	STDMETHOD(player_destroy)(/*[in]*/ int player_id, /*[out,retval]*/ Pj_Status *pRet);
+	STDMETHOD(player_set_pos)(/*[in]*/ int player_id, /*[in]*/ int pos, /*[out,retval]*/ Pj_Status *pRet);
+	STDMETHOD(player_get_conf_port)(/*[in]*/ int player_id, /*[out,retval]*/ int *pPort);
+	STDMETHOD(player_create)(/*[in,string]*/ Pj_String filename, /*[out]*/ int *pPlayer_Id, /*[out,retval]*/ Pj_Status *pRet);
+	STDMETHOD(conf_disconnect)(/*[in]*/ int src_port, /*[in]*/ int sink_port, /*[out,retval]*/ Pj_Status *pRet);
+	STDMETHOD(conf_connect)(/*[in]*/ int src_port, /*[in]*/ int sink_port, /*[out,retval]*/ Pj_Status *pRet);
+	STDMETHOD(im_typing)(/*[in]*/ int acc_index, /*[in,string]*/ Pj_URI dst_uri, /*[in]*/ int is_typing, /*[out,retval]*/ Pj_Status *pRet);
+	STDMETHOD(im_send_text)(/*[in]*/ int acc_index, /*[in,string]*/ Pj_String dst_uri, /*[in,string]*/ Pj_String text, /*[out,retval]*/ Pj_Status *pRet);
+	STDMETHOD(buddy_subscribe_pres)(/*[in]*/ int buddy_index, /*[in]*/ int subscribe, /*[out,retval]*/ Pj_Status *pRet);
+	STDMETHOD(buddy_add)(/*[in,string]*/ Pj_String uri, /*[out]*/ int *pBuddy_Index, /*[out,retval]*/ Pj_Status *pRet);
+	STDMETHOD(buddy_get_info)(/*[in]*/ int buddy_index, /*[out]*/ Pjsua_Buddy_Info *pInfo, /*[out,retval]*/ Pj_Status *pRet);
+	STDMETHOD(buddy_get_count)(/*[out,retval]*/ int *pCount);
+	STDMETHOD(acc_set_registration)(/*[in]*/ int acc_index, /*[in]*/ int reg_active, /*[out,retval]*/ Pj_Status *pRet);
+	STDMETHOD(acc_set_online_status)(/*[in]*/ int acc_index, /*[in]*/ int is_online, /*[out,retval]*/ Pj_Status *pRet);
+	STDMETHOD(acc_add)(/*[in]*/ Pjsua_Acc_Config *pConfig, /*[out]*/ int *pAcc_Index, /*[out,retval]*/ Pj_Status *pRet);
+	STDMETHOD(acc_get_info)(/*[in]*/ int acc_index, /*[out]*/ Pjsua_Acc_Info *pInfo, /*[out,retval]*/ Pj_Status *pRet);
+	STDMETHOD(acc_get_count)(/*[out,retval]*/ int *pCount);
+	STDMETHOD(call_hangup_all)();
+	STDMETHOD(call_typing)(/*[in]*/ int call_index, /*[in]*/ int is_typing, /*[out,retval]*/ Pj_Status *pRet);
+	STDMETHOD(call_send_im)(/*[in]*/ int call_index, /*[in,string]*/ Pj_String text, /*[out,retval]*/ Pj_Status *pRet);
+	STDMETHOD(call_dial_dtmf)(/*[in]*/ int call_index, /*[in,string]*/ Pj_String digits, /*[out,retval]*/ Pj_Status *pRet);
+	STDMETHOD(call_xfer)(/*[in]*/ int call_index, /*[in,string]*/ Pj_String dst_uri, /*[out,retval]*/ Pj_Status *pRet);
+	STDMETHOD(call_release_hold)(/*[in]*/ int call_index, /*[out,retval]*/ Pj_Status *pRet);
+	STDMETHOD(call_set_hold)(/*[in]*/ int call_index, /*[out,retval]*/ Pj_Status *pRet);
+	STDMETHOD(call_hangup)(/*[in]*/ int call_index, /*[out,retval]*/ Pj_Status *pRet);
+	STDMETHOD(call_answer)(/*[in]*/ int call_index, /*[in]*/ int status_code, /*[out,retval]*/ Pj_Status *pRet);
+	STDMETHOD(call_make_call)(/*[in]*/ int acc_index, /*[in,string]*/ Pj_String dst_uri, /*[out]*/ int *call_index, /*[out,retval]*/ Pj_Status *pRet);
+	STDMETHOD(call_get_info)(/*[in]*/ int call_index, /*[out]*/ Pjsua_Call_Info *pInfo, /*[out,retval]*/ Pj_Status *pRet);
+	STDMETHOD(call_has_media)(/*[in]*/ int call_index, /*[out,retval]*/ Pj_Bool *pRet);
+	STDMETHOD(call_is_active)(/*[in]*/ int call_index, /*[out,retval]*/ Pj_Bool *retVal);
+	STDMETHOD(call_get_count)(/*[out,retval]*/ int *retCount);
+	STDMETHOD(call_get_max_count)(/*[out,retval]*/ int *retCount);
+	STDMETHOD(app_destroy)(/*[out,retval]*/ Pj_Status *retStatus);
+	STDMETHOD(app_start)(/*[out,retval]*/ Pj_Status *retStatus);
+	STDMETHOD(app_init)(/*[in]*/ Pjsua_Config *pConfig, /*[out,retval]*/ Pj_Status *pStatus);
+	STDMETHOD(app_test_config)(/*[in]*/ Pjsua_Config *pConfig, /*[out,retval,string]*/ BSTR *retmsg);
+	STDMETHOD(app_default_config)(/*[in,out]*/ Pjsua_Config *pConfig);
+	STDMETHOD(app_create)(/*[out,retval]*/ Pj_Status *ret);
+	STDMETHOD(call_get_textstat)(/* [in] */ int call_index,    /* [retval][out] */ BSTR *textstat);
+
+};
+
+#endif //__APP_H_
Index: pjproject/trunk/pjsip-apps/src/activex-pjsua/app.rgs
===================================================================
--- pjproject/trunk/pjsip-apps/src/activex-pjsua/app.rgs	(revision 487)
+++ pjproject/trunk/pjsip-apps/src/activex-pjsua/app.rgs	(revision 487)
@@ -0,0 +1,26 @@
+HKCR
+{
+	ActivePJSUA.App.1 = s 'App Class'
+	{
+		CLSID = s '{F89DA516-42E5-43A0-8EF7-A960BA386CAB}'
+	}
+	ActivePJSUA.App = s 'App Class'
+	{
+		CLSID = s '{F89DA516-42E5-43A0-8EF7-A960BA386CAB}'
+		CurVer = s 'ActivePJSUA.App.1'
+	}
+	NoRemove CLSID
+	{
+		ForceRemove {F89DA516-42E5-43A0-8EF7-A960BA386CAB} = s 'App Class'
+		{
+			ProgID = s 'ActivePJSUA.App.1'
+			VersionIndependentProgID = s 'ActivePJSUA.App'
+			ForceRemove 'Programmable'
+			InprocServer32 = s '%MODULE%'
+			{
+				val ThreadingModel = s 'Apartment'
+			}
+			'TypeLib' = s '{11E70413-8434-41B6-A5B6-F7DF79FEFC1A}'
+		}
+	}
+}
Index: pjproject/trunk/pjsip-apps/src/activex-pjsua/pjsua-structs.idl
===================================================================
--- pjproject/trunk/pjsip-apps/src/activex-pjsua/pjsua-structs.idl	(revision 487)
+++ pjproject/trunk/pjsip-apps/src/activex-pjsua/pjsua-structs.idl	(revision 487)
@@ -0,0 +1,156 @@
+import "oaidl.idl";
+import "ocidl.idl";
+
+typedef long Pj_Status;
+typedef BSTR Pj_URI;
+typedef BSTR Pj_String;
+typedef int  Pj_Bool;
+
+
+[
+    uuid(9CE3052A-7A32-4229-B31C-5E02E0667A77),
+    version(1.0),
+    helpstring("PJSIP credential information"),
+]
+typedef struct Pjsip_Cred_Info
+{
+    Pj_String   realm;
+    Pj_String	scheme;
+    Pj_String	username;
+    int		hashed;
+    Pj_String	data;
+} Pjsip_Cred_Info;
+
+
+[
+    uuid(3B12B04F-6E48-46a7-B9E0-6C4BF1594A96),
+    version(1.0),
+    helpstring("PJSUA Account configuration"),
+]
+typedef struct Pjsua_Acc_Config
+{
+    Pj_URI			acc_uri;
+    Pj_URI			reg_uri;
+    Pj_URI			contact_uri;
+    Pj_URI			proxy_uri;
+    int				reg_timeout;
+    SAFEARRAY(Pjsip_Cred_Info)	cred_info;
+} Pjsua_Acc_Config;
+
+[
+    uuid(E4B6573D-CF5E-484d-863F-ADAD5947FBE4),
+    version(1.0),
+    helpstring("PJSUA configuration"),
+]
+typedef struct Pjsua_Config
+{
+    unsigned int		udp_port;
+    Pj_String			sip_host;
+    unsigned int		sip_port;
+    unsigned int		rtp_port;
+    unsigned int		max_calls;
+    unsigned int		conf_ports;
+    unsigned int		thread_cnt;
+    Pj_String			stun_srv1;
+    unsigned int		stun_port1;
+    Pj_String			stun_srv2;
+    unsigned int		stun_port2;
+    unsigned int		snd_player_id;
+    unsigned int		snd_capture_id;
+    unsigned int		clock_rate;
+    Pj_Bool			null_audio;
+    unsigned int		quality;
+    unsigned int		complexity;
+    SAFEARRAY(Pj_String)	codec_arg;
+    unsigned int		auto_answer;
+    unsigned int		uas_refresh;
+    Pj_String			outbound_proxy;
+    SAFEARRAY(Pjsua_Acc_Config) acc_config;
+    unsigned int		log_level;
+    unsigned int		app_log_level;
+    unsigned long		log_decor;
+    Pj_String			log_filename;
+    SAFEARRAY(Pj_String)	buddy_uri;
+} Pjsua_Config;
+
+
+typedef enum Pjsua_Call_State
+{
+    PJSUA_CALL_STATE_NULL,
+    PJSUA_CALL_STATE_CALLING,
+    PJSUA_CALL_STATE_INCOMING,
+    PJSUA_CALL_STATE_EARLY,
+    PJSUA_CALL_STATE_CONNECTING,
+    PJSUA_CALL_STATE_CONFIRMED,
+    PJSUA_CALL_STATE_DISCONNECTED,
+} Pjsua_Call_State;
+
+
+[
+    uuid(5043AC9E-A417-4f03-927E-D7AE52DDD064),
+    version(1.0),
+    helpstring("PJSUA Call Information"),
+]
+typedef struct Pjsua_Call_Info
+{
+    unsigned int	index;
+    Pj_Bool		active;
+    Pj_Bool		is_uac;
+    Pj_String		local_info;
+    Pj_String		remote_info;
+    Pjsua_Call_State	state;
+    Pj_String		state_text;
+    unsigned int	connect_duration;
+    unsigned int	total_duration;
+    unsigned int	cause;
+    Pj_String		cause_text;
+    Pj_Bool		has_media;
+    unsigned int	conf_slot;
+} Pjsua_Call_Info;
+
+
+typedef enum Pjsua_Buddy_State
+{
+    PJSUA_BUDDY_STATE_UNKNOWN,
+    PJSUA_BUDDY_STATE_ONLINE,
+    PJSUA_BUDDY_STATE_OFFLINE,
+} Pjsua_Buddy_State;	
+
+
+[
+    uuid(2729F0BC-8A5E-4f3f-BC29-C1740A86393A),
+    version(1.0),
+    helpstring("PJSUA Buddy Information"),
+]
+typedef struct Pjsua_Buddy_Info
+{
+    unsigned int	index;
+    Pj_Bool		is_valid;
+    Pj_String		name;
+    Pj_String		display;
+    Pj_String		host;
+    unsigned int  	port;
+    Pj_URI		uri;
+    Pjsua_Buddy_State	status;
+    Pj_String		status_text;
+    Pj_Bool		monitor;
+    int			acc_index;
+} Pjsua_Buddy_Info;
+
+
+[
+    uuid(8D345956-10B7-4450-8A06-A80D2F319EFD),
+    version(1.0),
+    helpstring("PJSUA Account Information"),
+]
+typedef struct Pjsua_Acc_Info
+{
+    unsigned int	index;
+    Pj_URI		acc_id;
+    Pj_Bool		has_registration;
+    int			expires;
+    unsigned int	status_code;
+    Pj_String		status_text;
+    Pj_Bool		online_status;
+} Pjsua_Acc_Info;
+
Index: pjproject/trunk/pjsip-apps/src/activex-pjsua/stdafx.cpp
===================================================================
--- pjproject/trunk/pjsip-apps/src/activex-pjsua/stdafx.cpp	(revision 487)
+++ pjproject/trunk/pjsip-apps/src/activex-pjsua/stdafx.cpp	(revision 487)
@@ -0,0 +1,12 @@
+// stdafx.cpp : source file that includes just the standard includes
+//  stdafx.pch will be the pre-compiled header
+//  stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+#ifdef _ATL_STATIC_REGISTRY
+#include <statreg.h>
+#include <statreg.cpp>
+#endif
+
+#include <atlimpl.cpp>
Index: pjproject/trunk/pjsip-apps/src/activex-pjsua/stdafx.h
===================================================================
--- pjproject/trunk/pjsip-apps/src/activex-pjsua/stdafx.h	(revision 487)
+++ pjproject/trunk/pjsip-apps/src/activex-pjsua/stdafx.h	(revision 487)
@@ -0,0 +1,27 @@
+// stdafx.h : include file for standard system include files,
+//      or project specific include files that are used frequently,
+//      but are changed infrequently
+
+#if !defined(AFX_STDAFX_H__D1920725_3220_40F4_9B04_762A3AB60D6C__INCLUDED_)
+#define AFX_STDAFX_H__D1920725_3220_40F4_9B04_762A3AB60D6C__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#define STRICT
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0400
+#endif
+#define _ATL_APARTMENT_THREADED
+
+#include <atlbase.h>
+//You may derive a class from CComModule and use it if you want to override
+//something, but do not change the name of _Module
+extern CComModule _Module;
+#include <atlcom.h>
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_STDAFX_H__D1920725_3220_40F4_9B04_762A3AB60D6C__INCLUDED)
Index: pjproject/trunk/pjsip-apps/src/pjsua/main.c
===================================================================
--- pjproject/trunk/pjsip-apps/src/pjsua/main.c	(revision 486)
+++ pjproject/trunk/pjsip-apps/src/pjsua/main.c	(revision 487)
@@ -43,9 +43,4 @@
 
 
-    /* Init logging: */
-    if (pjsua_console_app_logging_init(&cfg) != PJ_SUCCESS)
-	return 1;
-
-
     /* Init pjsua */
     if (pjsua_init(&cfg, &console_callback) != PJ_SUCCESS)
@@ -83,8 +78,4 @@
 
 
-    /* Close logging: */
-    pjsua_console_app_logging_shutdown();
-
-
     /* Exit... */
 
Index: pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h
===================================================================
--- pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h	(revision 486)
+++ pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h	(revision 487)
@@ -144,6 +144,12 @@
     unsigned	conf_ports;
 
-    /** Number of worker threads (default: 1) */
+    /** Number of worker threads (value >=0, default: 1) */
     unsigned	thread_cnt;
+
+    /** Separate ioqueue for media? (default: yes) */
+    pj_bool_t	media_has_ioqueue;
+
+    /** Number of worker thread for media (value >=0, default: 1) */
+    unsigned	media_thread_cnt;
 
     /** First STUN server IP address. When STUN is configured, then the
@@ -360,4 +366,5 @@
     pj_str_t		status_text;
     pj_bool_t		monitor;
+    int			acc_index;
 };
 
@@ -440,4 +447,10 @@
 
 /**
+ * Poll pjsua.
+ */
+PJ_DECL(int) pjsua_handle_events(unsigned msec_timeout);
+
+
+/**
  * Get SIP endpoint instance.
  * Only valid after pjsua_init().
@@ -559,4 +572,12 @@
  */
 PJ_DECL(void) pjsua_call_hangup_all(void);
+
+
+/**
+ * Dump call and media statistics to string.
+ */
+PJ_DECL(void) pjsua_dump_call(int call_index, int with_media, 
+			      char *buffer, unsigned maxlen,
+			      const char *indent);
 
 
@@ -599,5 +620,5 @@
  * this will start unregistration process.
  */
-PJ_DECL(void) pjsua_acc_set_registration(unsigned acc_index, pj_bool_t renew);
+PJ_DECL(pj_status_t) pjsua_acc_set_registration(unsigned acc_index, pj_bool_t renew);
 
 
@@ -638,5 +659,5 @@
  * Refresh both presence client and server subscriptions.
  */
-PJ_DECL(void) pjsua_pres_refresh(int acc_index);
+PJ_DECL(void) pjsua_pres_refresh(void);
 
 /**
@@ -713,5 +734,5 @@
  * Get conference port associated with player.
  */
-PJ_DECL(unsigned) pjsua_player_get_conf_port(pjsua_player_id id);
+PJ_DECL(int) pjsua_player_get_conf_port(pjsua_player_id id);
 
 
@@ -740,5 +761,5 @@
  * Get conference port associated with recorder.
  */
-PJ_DECL(unsigned) pjsua_recorder_get_conf_port(pjsua_recorder_id id);
+PJ_DECL(int) pjsua_recorder_get_conf_port(pjsua_recorder_id id);
 
 
Index: pjproject/trunk/pjsip/include/pjsua-lib/pjsua_console_app.h
===================================================================
--- pjproject/trunk/pjsip/include/pjsua-lib/pjsua_console_app.h	(revision 486)
+++ pjproject/trunk/pjsip/include/pjsua-lib/pjsua_console_app.h	(revision 487)
@@ -21,7 +21,4 @@
 
 
-pj_status_t pjsua_console_app_logging_init(const pjsua_config *cfg);
-void pjsua_console_app_logging_shutdown(void);
-
 void pjsua_console_app_main(void);
 
Index: pjproject/trunk/pjsip/src/pjsua-lib/pjsua_console_app.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsua-lib/pjsua_console_app.c	(revision 486)
+++ pjproject/trunk/pjsip/src/pjsua-lib/pjsua_console_app.c	(revision 487)
@@ -782,5 +782,5 @@
 		}
 
-		pjsua_pres_refresh(current_acc);
+		pjsua_pres_refresh();
 
 	    } else if (result.uri_result) {
@@ -815,5 +815,5 @@
 		   acc_info.acc_id.ptr,
 		   (acc_info.online_status?"online":"offline"));
-	    pjsua_pres_refresh(current_acc);
+	    pjsua_pres_refresh();
 	    break;
 
@@ -972,57 +972,4 @@
 
 /*****************************************************************************
- * Console application custom logging:
- */
-
-
-static FILE *log_file;
-
-
-static void app_log_writer(int level, const char *buffer, int len)
-{
-    /* Write to both stdout and file. */
-
-    if (level <= (int)pjsua_get_config()->app_log_level)
-	pj_log_write(level, buffer, len);
-
-    if (log_file) {
-	fwrite(buffer, len, 1, log_file);
-	fflush(log_file);
-    }
-}
-
-
-pj_status_t pjsua_console_app_logging_init(const pjsua_config *cfg)
-{
-    /* Redirect log function to ours */
-
-    pj_log_set_log_func( &app_log_writer );
-
-    /* If output log file is desired, create the file: */
-
-    if (cfg->log_filename.slen) {
-	log_file = fopen(cfg->log_filename.ptr, "wt");
-	if (log_file == NULL) {
-	    PJ_LOG(1,(THIS_FILE, "Unable to open log file %s", 
-		      cfg->log_filename.ptr));   
-	    return -1;
-	}
-    }
-
-    return PJ_SUCCESS;
-}
-
-
-void pjsua_console_app_logging_shutdown(void)
-{
-    /* Close logging file, if any: */
-
-    if (log_file) {
-	fclose(log_file);
-	log_file = NULL;
-    }
-}
-
-/*****************************************************************************
  * Error display:
  */
Index: pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c	(revision 486)
+++ pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c	(revision 487)
@@ -52,4 +52,6 @@
 
     cfg->thread_cnt = 1;
+    cfg->media_has_ioqueue = 1;
+    cfg->media_thread_cnt = 1;
     cfg->udp_port = 5060;
     cfg->start_rtp_port = 4000;
@@ -247,4 +249,23 @@
 }
 
+/**
+ * Poll pjsua.
+ */
+PJ_DECL(int) pjsua_handle_events(unsigned msec_timeout)
+{
+    unsigned count = 0;
+    pj_time_val tv;
+    pj_status_t status;
+
+    tv.sec = 0;
+    tv.msec = msec_timeout;
+    pj_time_val_normalize(&tv);
+
+    status = pjsip_endpt_handle_events2(pjsua.endpt, &tv, &count);
+    if (status != PJ_SUCCESS)
+	return -status;
+
+    return count;
+}
 
 
@@ -505,5 +526,7 @@
     /* Must create media endpoint too */
     status = pjmedia_endpt_create(&pjsua.cp.factory, 
-				  pjsip_endpt_get_ioqueue(pjsua.endpt), 0,
+				  pjsua.config.media_has_ioqueue? NULL :
+				       pjsip_endpt_get_ioqueue(pjsua.endpt), 
+				  pjsua.config.media_thread_cnt,
 				  &pjsua.med_endpt);
     if (status != PJ_SUCCESS) {
@@ -755,4 +778,55 @@
 
 
+/*****************************************************************************
+ * Console application custom logging:
+ */
+
+
+static void log_writer(int level, const char *buffer, int len)
+{
+    /* Write to both stdout and file. */
+
+    if (level <= (int)pjsua.config.app_log_level)
+	pj_log_write(level, buffer, len);
+
+    if (pjsua.log_file) {
+	fwrite(buffer, len, 1, pjsua.log_file);
+	fflush(pjsua.log_file);
+    }
+}
+
+
+static pj_status_t logging_init()
+{
+    /* Redirect log function to ours */
+
+    pj_log_set_log_func( &log_writer );
+
+    /* If output log file is desired, create the file: */
+
+    if (pjsua.config.log_filename.slen) {
+	pjsua.log_file = fopen(pjsua.config.log_filename.ptr, "wt");
+	if (pjsua.log_file == NULL) {
+	    PJ_LOG(1,(THIS_FILE, "Unable to open log file %s", 
+		      pjsua.config.log_filename.ptr));   
+	    return -1;
+	}
+    }
+
+    return PJ_SUCCESS;
+}
+
+
+static void logging_shutdown(void)
+{
+    /* Close logging file, if any: */
+
+    if (pjsua.log_file) {
+	fclose(pjsua.log_file);
+	pjsua.log_file = NULL;
+    }
+}
+
+
 /*
  * Initialize pjsua application.
@@ -807,4 +881,8 @@
     pj_log_set_level(pjsua.config.log_level);
     pj_log_set_decor(pjsua.config.log_decor);
+
+    status = logging_init();
+    if (status != PJ_SUCCESS)
+	goto on_error;
 
 
@@ -854,5 +932,5 @@
 	}
 	status = pjmedia_transport_udp_attach(pjsua.med_endpt, NULL,
-					      &pjsua.calls[i].skinfo,
+					      &pjsua.calls[i].skinfo, 0,
 					      &pjsua.calls[i].med_tp);
     }
@@ -1369,5 +1447,5 @@
  * Get conference port associated with player.
  */
-PJ_DEF(unsigned) pjsua_player_get_conf_port(pjsua_player_id id)
+PJ_DEF(int) pjsua_player_get_conf_port(pjsua_player_id id)
 {
     PJ_ASSERT_RETURN(id>=0 && id < PJ_ARRAY_SIZE(pjsua.player), PJ_EINVAL);
@@ -1453,5 +1531,5 @@
  * Get conference port associated with recorder.
  */
-PJ_DEF(unsigned) pjsua_recorder_get_conf_port(pjsua_recorder_id id)
+PJ_DEF(int) pjsua_recorder_get_conf_port(pjsua_recorder_id id)
 {
     PJ_ASSERT_RETURN(id>=0 && id < PJ_ARRAY_SIZE(pjsua.recorder), PJ_EINVAL);
@@ -1521,17 +1599,4 @@
     /* Signal threads to quit: */
     pjsua.quit_flag = 1;
-
-    /* Terminate all calls. */
-    pjsua_call_hangup_all();
-
-    /* Terminate all presence subscriptions. */
-    pjsua_pres_shutdown();
-
-    /* Unregister, if required: */
-    for (i=0; i<(int)pjsua.config.acc_cnt; ++i) {
-	if (pjsua.acc[i].regc) {
-	    pjsua_acc_set_registration(i, PJ_FALSE);
-	}
-    }
 
     /* Wait worker threads to quit: */
@@ -1545,7 +1610,20 @@
     }
 
-
-    /* Wait for some time to allow unregistration to complete: */
+    
     if (pjsua.endpt) {
+	/* Terminate all calls. */
+	pjsua_call_hangup_all();
+
+	/* Terminate all presence subscriptions. */
+	pjsua_pres_shutdown();
+
+	/* Unregister, if required: */
+	for (i=0; i<(int)pjsua.config.acc_cnt; ++i) {
+	    if (pjsua.acc[i].regc) {
+		pjsua_acc_set_registration(i, PJ_FALSE);
+	    }
+	}
+
+	/* Wait for some time to allow unregistration to complete: */
 	PJ_LOG(4,(THIS_FILE, "Shutting down..."));
 	busy_sleep(1000);
@@ -1630,4 +1708,9 @@
 
 
+    PJ_LOG(4,(THIS_FILE, "PJSUA destroyed..."));
+
+    /* End logging */
+    logging_shutdown();
+
     /* Done. */
 
Index: pjproject/trunk/pjsip/src/pjsua-lib/pjsua_imp.h
===================================================================
--- pjproject/trunk/pjsip/src/pjsua-lib/pjsua_imp.h	(revision 486)
+++ pjproject/trunk/pjsip/src/pjsua-lib/pjsua_imp.h	(revision 487)
@@ -127,4 +127,7 @@
     pjsua_config    config;	    /**< PJSUA configs			*/
 
+    /* Log file: */
+    FILE	   *log_file;	    /**< Log file.			*/
+
     /* Application callback
     : */
Index: pjproject/trunk/pjsip/src/pjsua-lib/pjsua_pres.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsua-lib/pjsua_pres.c	(revision 486)
+++ pjproject/trunk/pjsip/src/pjsua-lib/pjsua_pres.c	(revision 487)
@@ -472,4 +472,5 @@
     }
 
+    info->acc_index = buddy->acc_index;
     return PJ_SUCCESS;
 }
@@ -550,8 +551,12 @@
  * Refresh presence
  */
-PJ_DEF(void) pjsua_pres_refresh(int acc_index)
-{
+PJ_DEF(void) pjsua_pres_refresh()
+{
+    unsigned i;
+
     refresh_client_subscription();
-    refresh_server_subscription(acc_index);
+
+    for (i=0; i<PJ_ARRAY_SIZE(pjsua.acc); ++i)
+	refresh_server_subscription(i);
 }
 
@@ -573,7 +578,5 @@
     }
 
-    for (acc_index=0; acc_index<(int)pjsua.config.acc_cnt; ++acc_index) {
-	pjsua_pres_refresh(acc_index);
-    }
+    pjsua_pres_refresh();
 }
 
Index: pjproject/trunk/pjsip/src/pjsua-lib/pjsua_reg.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsua-lib/pjsua_reg.c	(revision 486)
+++ pjproject/trunk/pjsip/src/pjsua-lib/pjsua_reg.c	(revision 487)
@@ -133,5 +133,5 @@
  * Update registration. If renew is false, then unregistration will be performed.
  */
-PJ_DECL(void) pjsua_acc_set_registration(unsigned acc_index, pj_bool_t renew)
+PJ_DECL(pj_status_t) pjsua_acc_set_registration(unsigned acc_index, pj_bool_t renew)
 {
     pj_status_t status = 0;
@@ -144,9 +144,9 @@
 		pjsua_perror(THIS_FILE, "Unable to create registration", 
 			     status);
-		return;
+		return PJ_EINVALIDOP;
 	    }
 	}
 	if (!pjsua.acc[acc_index].regc)
-	    return;
+	    return PJ_EINVALIDOP;
 
 	status = pjsip_regc_register(pjsua.acc[acc_index].regc, 1, 
@@ -156,5 +156,5 @@
 	if (pjsua.acc[acc_index].regc == NULL) {
 	    PJ_LOG(3,(THIS_FILE, "Currently not registered"));
-	    return;
+	    return PJ_EINVALIDOP;
 	}
 	status = pjsip_regc_unregister(pjsua.acc[acc_index].regc, &tdata);
@@ -171,4 +171,6 @@
 	         (renew? "Registration" : "Unregistration")));
     }
+
+    return status;
 }
 
Index: pjproject/trunk/pjsip/src/pjsua-lib/pjsua_settings.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsua-lib/pjsua_settings.c	(revision 486)
+++ pjproject/trunk/pjsip/src/pjsua-lib/pjsua_settings.c	(revision 487)
@@ -686,7 +686,11 @@
 }
 
-static void dump_media_session(pjmedia_session *session)
+static void dump_media_session(const char *indent, 
+			       char *buf, unsigned maxlen,
+			       pjmedia_session *session)
 {
     unsigned i;
+    char *p = buf, *end = buf+maxlen;
+    int len;
     pjmedia_session_info info;
 
@@ -716,13 +720,20 @@
 
 	
-	PJ_LOG(3,(THIS_FILE, 
-		  "%s#%d %.*s @%dKHz, %s, peer=%s:%d",
-		  "               ",
-		  i,
+	len = pj_ansi_snprintf(buf, end-p, 
+		  "%s  #%d %.*s @%dKHz, %s, peer=%s:%d",
+		  indent, i,
 		  info.stream_info[i].fmt.encoding_name.slen,
 		  info.stream_info[i].fmt.encoding_name.ptr,
 		  info.stream_info[i].fmt.clock_rate / 1000,
 		  dir,
-		  rem_addr, rem_port));
+		  rem_addr, rem_port);
+	if (len < 1 || len > end-p) {
+	    *p = '\0';
+	    return;
+	}
+
+	p += len;
+	*p++ = '\n';
+	*p = '\0';
 
 	if (stat.rx.update_cnt == 0)
@@ -738,17 +749,18 @@
 	}
 
-	PJ_LOG(3,(THIS_FILE, 
-	       "                  RX pt=%d, stat last update: %s\n"
-	       "                     total %spkt %sB (%sB +IP hdr)%s\n"
-	       "                     pkt loss=%d (%3.1f%%), dup=%d (%3.1f%%), reorder=%d (%3.1f%%)%s\n"
-	       "                           (msec)    min     avg     max     last\n"
-	       "                     loss period: %7.3f %7.3f %7.3f %7.3f%s\n"
-	       "                     jitter     : %7.3f %7.3f %7.3f %7.3f%s",
-	       info.stream_info[i].fmt.pt,
+	len = pj_ansi_snprintf(p, end-p,
+	       "%s     RX pt=%d, stat last update: %s\n"
+	       "%s        total %spkt %sB (%sB +IP hdr)\n"
+	       "%s        pkt loss=%d (%3.1f%%), dup=%d (%3.1f%%), reorder=%d (%3.1f%%)\n"
+	       "%s              (msec)    min     avg     max     last\n"
+	       "%s        loss period: %7.3f %7.3f %7.3f %7.3f\n"
+	       "%s        jitter     : %7.3f %7.3f %7.3f %7.3f%s",
+	       indent, info.stream_info[i].fmt.pt,
 	       last_update,
+	       indent,
 	       good_number(packets, stat.rx.pkt),
 	       good_number(bytes, stat.rx.bytes),
 	       good_number(ipbytes, stat.rx.bytes + stat.rx.pkt * 32),
-	       "",
+	       indent,
 	       stat.rx.loss,
 	       stat.rx.loss * 100.0 / stat.rx.pkt,
@@ -757,10 +769,10 @@
 	       stat.rx.reorder, 
 	       stat.rx.reorder * 100.0 / stat.rx.pkt,
-	       "",
+	       indent, indent,
 	       stat.rx.loss_period.min / 1000.0, 
 	       stat.rx.loss_period.avg / 1000.0, 
 	       stat.rx.loss_period.max / 1000.0,
 	       stat.rx.loss_period.last / 1000.0,
-	       "",
+	       indent,
 	       stat.rx.jitter.min / 1000.0,
 	       stat.rx.jitter.avg / 1000.0,
@@ -768,7 +780,15 @@
 	       stat.rx.jitter.last / 1000.0,
 	       ""
-	       ));
-
-
+	       );
+
+	if (len < 1 || len > end-p) {
+	    *p = '\0';
+	    return;
+	}
+
+	p += len;
+	*p++ = '\n';
+	*p = '\0';
+	
 	if (stat.tx.update_cnt == 0)
 	    strcpy(last_update, "never");
@@ -783,19 +803,23 @@
 	}
 
-	PJ_LOG(3,(THIS_FILE,
-	       "                  TX pt=%d, ptime=%dms, stat last update: %s\n"
-	       "                     total %spkt %sB (%sB +IP hdr)%s\n"
-	       "                     pkt loss=%d (%3.1f%%), dup=%d (%3.1f%%), reorder=%d (%3.1f%%)%s\n"
-	       "                           (msec)    min     avg     max     last\n"
-	       "                     loss period: %7.3f %7.3f %7.3f %7.3f%s\n"
-	       "                     jitter     : %7.3f %7.3f %7.3f %7.3f%s",
+	len = pj_ansi_snprintf(p, end-p,
+	       "%s     TX pt=%d, ptime=%dms, stat last update: %s\n"
+	       "%s        total %spkt %sB (%sB +IP hdr)\n"
+	       "%s        pkt loss=%d (%3.1f%%), dup=%d (%3.1f%%), reorder=%d (%3.1f%%)\n"
+	       "%s              (msec)    min     avg     max     last\n"
+	       "%s        loss period: %7.3f %7.3f %7.3f %7.3f\n"
+	       "%s        jitter     : %7.3f %7.3f %7.3f %7.3f%s",
+	       indent,
 	       info.stream_info[i].tx_pt,
 	       info.stream_info[i].param->info.frm_ptime *
 		info.stream_info[i].param->setting.frm_per_pkt,
 	       last_update,
+
+	       indent,
 	       good_number(packets, stat.tx.pkt),
 	       good_number(bytes, stat.tx.bytes),
 	       good_number(ipbytes, stat.tx.bytes + stat.tx.pkt * 32),
-	       "",
+
+	       indent,
 	       stat.tx.loss,
 	       stat.tx.loss * 100.0 / stat.tx.pkt,
@@ -804,10 +828,11 @@
 	       stat.tx.reorder, 
 	       stat.tx.reorder * 100.0 / stat.tx.pkt,
-	       "",
+
+	       indent, indent,
 	       stat.tx.loss_period.min / 1000.0, 
 	       stat.tx.loss_period.avg / 1000.0, 
 	       stat.tx.loss_period.max / 1000.0,
 	       stat.tx.loss_period.last / 1000.0,
-	       "",
+	       indent,
 	       stat.tx.jitter.min / 1000.0,
 	       stat.tx.jitter.avg / 1000.0,
@@ -815,17 +840,104 @@
 	       stat.tx.jitter.last / 1000.0,
 	       ""
-	       ));
-
-
-	PJ_LOG(3,(THIS_FILE,
-	       "                 RTT msec       : %7.3f %7.3f %7.3f %7.3f%s", 
+	       );
+
+	if (len < 1 || len > end-p) {
+	    *p = '\0';
+	    return;
+	}
+
+	p += len;
+	*p++ = '\n';
+	*p = '\0';
+
+	len = pj_ansi_snprintf(p, end-p,
+	       "%s    RTT msec       : %7.3f %7.3f %7.3f %7.3f", 
+	       indent,
 	       stat.rtt.min / 1000.0,
 	       stat.rtt.avg / 1000.0,
 	       stat.rtt.max / 1000.0,
-	       stat.rtt.last / 1000.0,
-	       ""
-	       ));
-
-    }
+	       stat.rtt.last / 1000.0
+	       );
+	if (len < 1 || len > end-p) {
+	    *p = '\0';
+	    return;
+	}
+
+	p += len;
+	*p++ = '\n';
+	*p = '\0';
+    }
+}
+
+PJ_DEF(void) pjsua_dump_call(int call_index, int with_media, 
+			     char *buffer, unsigned maxlen,
+			     const char *indent)
+{
+    pjsua_call *call = &pjsua.calls[call_index];
+    pj_time_val duration, res_delay, con_delay;
+    char tmp[128];
+    char *p, *end;
+    int len;
+
+    *buffer = '\0';
+    p = buffer;
+    end = buffer + maxlen;
+    len = 0;
+
+    PJ_ASSERT_ON_FAIL(call_index >= 0 && 
+		      call_index < PJ_ARRAY_SIZE(pjsua.calls), return);
+
+    if (call->inv == NULL)
+	return;
+
+    print_call(indent, call_index, tmp, sizeof(tmp));
+    
+    len = pj_ansi_strlen(tmp);
+    pj_ansi_strcpy(buffer, tmp);
+
+    p += len;
+    *p++ = '\r';
+    *p++ = '\n';
+
+    /* Calculate call duration */
+    if (call->inv->state >= PJSIP_INV_STATE_CONFIRMED) {
+	pj_gettimeofday(&duration);
+	PJ_TIME_VAL_SUB(duration, call->conn_time);
+	con_delay = call->conn_time;
+	PJ_TIME_VAL_SUB(con_delay, call->start_time);
+    } else {
+	duration.sec = duration.msec = 0;
+	con_delay.sec = con_delay.msec = 0;
+    }
+
+    /* Calculate first response delay */
+    if (call->inv->state >= PJSIP_INV_STATE_EARLY) {
+	res_delay = call->res_time;
+	PJ_TIME_VAL_SUB(res_delay, call->start_time);
+    } else {
+	res_delay.sec = res_delay.msec = 0;
+    }
+
+    /* Print duration */
+    len = pj_ansi_snprintf(p, end-p, 
+		           "%s  Call time: %02dh:%02dm:%02ds, "
+		           "1st res in %d ms, conn in %dms",
+			   indent,
+		           (duration.sec / 3600),
+		           ((duration.sec % 3600)/60),
+		           (duration.sec % 60),
+		           PJ_TIME_VAL_MSEC(res_delay), 
+		           PJ_TIME_VAL_MSEC(con_delay));
+    
+    if (len > 0 && len < end-p) {
+	p += len;
+	*p++ = '\n';
+	*p = '\0';
+    }
+
+    /* Dump session statistics */
+    if (with_media && call->session)
+	dump_media_session(indent, p, end-p, call->session);
+
 }
 
@@ -835,6 +947,6 @@
 PJ_DEF(void) pjsua_dump(pj_bool_t detail)
 {
-    char buf[128];
     unsigned old_decor;
+    char buf[1024];
 
     PJ_LOG(3,(THIS_FILE, "Start dumping application states:"));
@@ -863,46 +975,8 @@
 
 	for (i=0; i<pjsua.config.max_calls; ++i) {
-
-	    pjsua_call *call = &pjsua.calls[i];
-	    pj_time_val duration, res_delay, con_delay;
-
-	    if (call->inv == NULL)
-		continue;
-
-	    print_call("  ", i, buf, sizeof(buf));
-	    PJ_LOG(3,(THIS_FILE, "%s", buf));
-
-	    /* Calculate call duration */
-	    if (call->inv->state >= PJSIP_INV_STATE_CONFIRMED) {
-		pj_gettimeofday(&duration);
-		PJ_TIME_VAL_SUB(duration, call->conn_time);
-		con_delay = call->conn_time;
-		PJ_TIME_VAL_SUB(con_delay, call->start_time);
-	    } else {
-		duration.sec = duration.msec = 0;
-		con_delay.sec = con_delay.msec = 0;
-	    }
-
-	    /* Calculate first response delay */
-	    if (call->inv->state >= PJSIP_INV_STATE_EARLY) {
-		res_delay = call->res_time;
-		PJ_TIME_VAL_SUB(res_delay, call->start_time);
-	    } else {
-		res_delay.sec = res_delay.msec = 0;
-	    }
-
-	    /* Print duration */
-	    PJ_LOG(3,(THIS_FILE, 
-		      "               Call time: %02dh:%02dm:%02ds, "
-		      "1st res in %d ms, conn in %dms",
-		      (duration.sec / 3600),
-		      ((duration.sec % 3600)/60),
-		      (duration.sec % 60),
-		      PJ_TIME_VAL_MSEC(res_delay), 
-		      PJ_TIME_VAL_MSEC(con_delay)));
-
-	    /* Dump session statistics */
-	    if (call->session)
-		dump_media_session(call->session);
+	    if (pjsua.calls[i].inv) {
+		pjsua_dump_call(i, detail, buf, sizeof(buf), "  ");
+		PJ_LOG(3,(THIS_FILE, "%s", buf));
+	    }
 	}
     }
@@ -925,5 +999,5 @@
     char *argv[4] = { "pjsua", "--config-file", NULL, NULL};
 
-    argv[3] = (char*)filename;
+    argv[2] = (char*)filename;
     return pjsua_parse_args(argc, argv, cfg);
 }
@@ -1104,10 +1178,14 @@
 
     /* Encoding quality and complexity */
-    pj_ansi_sprintf(line, "--quality %d\n",
-		    config->quality);
-    pj_strcat2(&cfg, line);
-    pj_ansi_sprintf(line, "--complexity %d\n",
-		    config->complexity);
-    pj_strcat2(&cfg, line);
+    if (config->quality > 0) {
+	pj_ansi_sprintf(line, "--quality %d\n",
+			config->quality);
+	pj_strcat2(&cfg, line);
+    }
+    if (config->complexity > 0) {
+	pj_ansi_sprintf(line, "--complexity %d\n",
+			config->complexity);
+	pj_strcat2(&cfg, line);
+    }
 
     /* ptime */
