Initial work on pjsua ActiveX component

git-svn-id: https://svn.pjsip.org/repos/pjproject/trunk@487 74dad513-b988-da41-8d7b-12977e46ad98
This commit is contained in:
Benny Prijono 2006-06-01 12:28:44 +00:00
parent 8c634f4b5a
commit b9b32abf60
22 changed files with 2328 additions and 183 deletions

View File

@ -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

View File

@ -3,6 +3,42 @@ Microsoft Developer Studio Workspace File, Format Version 6.00
###############################################################################
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>
Package=<5>

View File

@ -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);
}

View File

@ -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

View File

@ -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;
};
};

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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_

View File

@ -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}'
}
}
}

View File

@ -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;

View File

@ -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>

View File

@ -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)

View File

@ -42,11 +42,6 @@ int main(int argc, char *argv[])
return 1;
/* Init logging: */
if (pjsua_console_app_logging_init(&cfg) != PJ_SUCCESS)
return 1;
/* Init pjsua */
if (pjsua_init(&cfg, &console_callback) != PJ_SUCCESS)
return 1;
@ -82,10 +77,6 @@ int main(int argc, char *argv[])
pjsua_destroy();
/* Close logging: */
pjsua_console_app_logging_shutdown();
/* Exit... */
return 0;

View File

@ -143,9 +143,15 @@ struct pjsua_config
*/
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
* two STUN server settings must be fully set.
* (default: none)
@ -359,6 +365,7 @@ struct pjsua_buddy_info
pjsua_buddy_status status;
pj_str_t status_text;
pj_bool_t monitor;
int acc_index;
};
typedef struct pjsua_buddy_info pjsua_buddy_info;
@ -438,6 +445,12 @@ PJ_DECL(pj_status_t) pjsua_start(void);
*/
PJ_DECL(pj_status_t) pjsua_destroy(void);
/**
* Poll pjsua.
*/
PJ_DECL(int) pjsua_handle_events(unsigned msec_timeout);
/**
* Get SIP endpoint instance.
* Only valid after pjsua_init().
@ -560,6 +573,14 @@ PJ_DECL(void) pjsua_call_typing(int call_index, pj_bool_t is_typing);
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);
/*****************************************************************************
* PJSUA Account and Client Registration API (defined in pjsua_reg.c).
*/
@ -598,7 +619,7 @@ PJ_DECL(pj_status_t) pjsua_acc_set_online_status(unsigned acc_index,
* Update registration or perform unregistration. If renew argument is zero,
* 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);
@ -637,7 +658,7 @@ PJ_DECL(pj_status_t) pjsua_buddy_subscribe_pres(unsigned buddy_index,
/**
* Refresh both presence client and server subscriptions.
*/
PJ_DECL(void) pjsua_pres_refresh(int acc_index);
PJ_DECL(void) pjsua_pres_refresh(void);
/**
* Dump presence subscriptions.
@ -712,7 +733,7 @@ PJ_DECL(pj_status_t) pjsua_player_create(const pj_str_t *filename,
/**
* 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);
/**
@ -739,7 +760,7 @@ PJ_DECL(pj_status_t) pjsua_recorder_create(const pj_str_t *filename,
/**
* 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);
/**

View File

@ -20,9 +20,6 @@
#define __PJSUA_CONSOLE_APP_H__
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);
extern pjsip_module pjsua_console_app_msg_logger;

View File

@ -781,7 +781,7 @@ void pjsua_console_app_main(void)
pjsua_buddy_subscribe_pres(result.nb_result-1, (menuin[0]=='s'));
}
pjsua_pres_refresh(current_acc);
pjsua_pres_refresh();
} else if (result.uri_result) {
puts("Sorry, can only subscribe to buddy's presence, "
@ -814,7 +814,7 @@ void pjsua_console_app_main(void)
printf("Setting %s online status to %s\n",
acc_info.acc_id.ptr,
(acc_info.online_status?"online":"offline"));
pjsua_pres_refresh(current_acc);
pjsua_pres_refresh();
break;
case 'c':
@ -970,59 +970,6 @@ pjsip_module pjsua_console_app_msg_logger =
/*****************************************************************************
* 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:
*/

View File

@ -51,6 +51,8 @@ PJ_DEF(void) pjsua_default_config(pjsua_config *cfg)
pj_memset(cfg, 0, sizeof(pjsua_config));
cfg->thread_cnt = 1;
cfg->media_has_ioqueue = 1;
cfg->media_thread_cnt = 1;
cfg->udp_port = 5060;
cfg->start_rtp_port = 4000;
cfg->max_calls = 4;
@ -246,6 +248,25 @@ static int PJ_THREAD_FUNC pjsua_poll(void *arg)
return 0;
}
/**
* 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;
}
#define pjsua_has_stun() (pjsua.config.stun_port1 && \
@ -504,7 +525,9 @@ PJ_DEF(pj_status_t) pjsua_create(void)
/* 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) {
pjsua_perror(THIS_FILE,
@ -754,6 +777,57 @@ static void copy_config(pj_pool_t *pool, pjsua_config *dst,
}
/*****************************************************************************
* 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.
* This will initialize all libraries, create endpoint instance, and register
@ -807,6 +881,10 @@ PJ_DECL(pj_status_t) pjsua_init(const pjsua_config *cfg,
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;
/* Create SIP UDP socket */
if (pjsua.config.udp_port) {
@ -853,7 +931,7 @@ PJ_DECL(pj_status_t) pjsua_init(const pjsua_config *cfg,
goto on_error;
}
status = pjmedia_transport_udp_attach(pjsua.med_endpt, NULL,
&pjsua.calls[i].skinfo,
&pjsua.calls[i].skinfo, 0,
&pjsua.calls[i].med_tp);
}
@ -1368,7 +1446,7 @@ PJ_DEF(pj_status_t) pjsua_player_create( const pj_str_t *filename,
/**
* 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);
return pjsua.player[id].slot;
@ -1452,7 +1530,7 @@ PJ_DEF(pj_status_t) pjsua_recorder_create( const pj_str_t *filename,
/**
* 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);
return pjsua.recorder[id].slot;
@ -1521,19 +1599,6 @@ PJ_DEF(pj_status_t) pjsua_destroy(void)
/* 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: */
for (i=0; i<(int)pjsua.config.thread_cnt; ++i) {
@ -1544,9 +1609,22 @@ PJ_DEF(pj_status_t) pjsua_destroy(void)
}
}
/* 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);
}
@ -1629,6 +1707,11 @@ PJ_DEF(pj_status_t) pjsua_destroy(void)
pj_caching_pool_destroy(&pjsua.cp);
PJ_LOG(4,(THIS_FILE, "PJSUA destroyed..."));
/* End logging */
logging_shutdown();
/* Done. */
return PJ_SUCCESS;

View File

@ -126,6 +126,9 @@ struct pjsua
/* Config: */
pjsua_config config; /**< PJSUA configs */
/* Log file: */
FILE *log_file; /**< Log file. */
/* Application callback
: */
pjsua_callback cb; /**< Application callback. */

View File

@ -471,6 +471,7 @@ PJ_DEF(pj_status_t) pjsua_buddy_get_info(unsigned index,
info->status_text = pj_str("Offline");
}
info->acc_index = buddy->acc_index;
return PJ_SUCCESS;
}
@ -549,10 +550,14 @@ PJ_DEF(pj_status_t) pjsua_acc_set_online_status( unsigned acc_index,
/*
* 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);
}
@ -572,9 +577,7 @@ void pjsua_pres_shutdown(void)
pjsua.buddies[i].monitor = 0;
}
for (acc_index=0; acc_index<(int)pjsua.config.acc_cnt; ++acc_index) {
pjsua_pres_refresh(acc_index);
}
pjsua_pres_refresh();
}
/*

View File

@ -132,7 +132,7 @@ PJ_DEF(pj_status_t) pjsua_acc_get_info( unsigned acc_index,
/*
* 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;
pjsip_tx_data *tdata = 0;
@ -143,11 +143,11 @@ PJ_DECL(void) pjsua_acc_set_registration(unsigned acc_index, pj_bool_t renew)
if (status != PJ_SUCCESS) {
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,
&tdata);
@ -155,7 +155,7 @@ PJ_DECL(void) pjsua_acc_set_registration(unsigned acc_index, pj_bool_t renew)
} else {
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);
}
@ -170,6 +170,8 @@ PJ_DECL(void) pjsua_acc_set_registration(unsigned acc_index, pj_bool_t renew)
PJ_LOG(3,(THIS_FILE, "%s sent",
(renew? "Registration" : "Unregistration")));
}
return status;
}
/*

View File

@ -685,9 +685,13 @@ static const char *good_number(char *buf, pj_int32_t val)
return buf;
}
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;
pjmedia_session_get_info(session, &info);
@ -715,15 +719,22 @@ static void dump_media_session(pjmedia_session *session)
dir = "inactive";
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)
strcpy(last_update, "never");
@ -737,39 +748,48 @@ static void dump_media_session(pjmedia_session *session)
now.msec);
}
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,
stat.rx.dup,
stat.rx.dup * 100.0 / stat.rx.pkt,
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,
stat.rx.jitter.max / 1000.0,
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");
else {
@ -782,60 +802,152 @@ static void dump_media_session(pjmedia_session *session)
now.msec);
}
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,
stat.tx.dup,
stat.tx.dup * 100.0 / stat.tx.pkt,
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,
stat.tx.jitter.max / 1000.0,
stat.tx.jitter.last / 1000.0,
""
));
);
if (len < 1 || len > end-p) {
*p = '\0';
return;
}
PJ_LOG(3,(THIS_FILE,
" RTT msec : %7.3f %7.3f %7.3f %7.3f%s",
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);
}
/*
* Dump application states.
*/
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:"));
@ -862,48 +974,10 @@ PJ_DEF(void) pjsua_dump(pj_bool_t detail)
unsigned i;
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;
if (pjsua.calls[i].inv) {
pjsua_dump_call(i, detail, buf, sizeof(buf), " ");
PJ_LOG(3,(THIS_FILE, "%s", buf));
}
/* 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);
}
}
@ -924,7 +998,7 @@ PJ_DECL(pj_status_t) pjsua_load_settings(const char *filename,
int argc = 3;
char *argv[4] = { "pjsua", "--config-file", NULL, NULL};
argv[3] = (char*)filename;
argv[2] = (char*)filename;
return pjsua_parse_args(argc, argv, cfg);
}
@ -1103,12 +1177,16 @@ PJ_DEF(int) pjsua_dump_settings(const pjsua_config *config,
/* 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 */
if (config->ptime) {