summaryrefslogtreecommitdiff
path: root/pjsip-apps
diff options
context:
space:
mode:
authorDavid M. Lee <dlee@digium.com>2013-01-07 14:24:28 -0600
committerDavid M. Lee <dlee@digium.com>2013-01-07 14:24:28 -0600
commitf3ab456a17af1c89a6e3be4d20c5944853df1cb0 (patch)
treed00e1a332cd038a6d906a1ea0ac91e1a4458e617 /pjsip-apps
Import pjproject-2.0.1
Diffstat (limited to 'pjsip-apps')
-rw-r--r--pjsip-apps/bin/samples/.keep0
-rw-r--r--pjsip-apps/build/Footprint.mak28
-rw-r--r--pjsip-apps/build/Makefile94
-rw-r--r--pjsip-apps/build/Samples-vc.mak116
-rw-r--r--pjsip-apps/build/Samples.mak78
-rw-r--r--pjsip-apps/build/dummy.c9
-rw-r--r--pjsip-apps/build/get-footprint.py338
-rw-r--r--pjsip-apps/build/libpjproject.vcproj2772
-rw-r--r--pjsip-apps/build/os-win32.mak2
-rw-r--r--pjsip-apps/build/output/.keep0
-rw-r--r--pjsip-apps/build/pjsua.vcproj3636
-rw-r--r--pjsip-apps/build/pjsystest.vcproj533
-rw-r--r--pjsip-apps/build/py_pjsua.vcproj244
-rw-r--r--pjsip-apps/build/python_pjsua.vcproj268
-rw-r--r--pjsip-apps/build/sample_debug.vcproj3265
-rw-r--r--pjsip-apps/build/samples.vcproj1754
-rw-r--r--pjsip-apps/build/vidgui.vcproj207
-rw-r--r--pjsip-apps/build/wince-evc4/output/.keep0
-rw-r--r--pjsip-apps/build/wince-evc4/wince_demos.vcw305
-rw-r--r--pjsip-apps/docs/.keep0
-rw-r--r--pjsip-apps/lib/.keep0
-rw-r--r--pjsip-apps/src/3rdparty_media_sample/Makefile34
-rw-r--r--pjsip-apps/src/3rdparty_media_sample/alt_pjsua_aud.c631
-rw-r--r--pjsip-apps/src/3rdparty_media_sample/alt_pjsua_vid.c602
-rw-r--r--pjsip-apps/src/3rdparty_media_sample/config_site.h42
-rw-r--r--pjsip-apps/src/confbot/confbot.py575
-rw-r--r--pjsip-apps/src/confbot/config.py41
-rw-r--r--pjsip-apps/src/ipjsua/Classes/ConfigViewController.h32
-rw-r--r--pjsip-apps/src/ipjsua/Classes/ConfigViewController.m158
-rw-r--r--pjsip-apps/src/ipjsua/Classes/FirstViewController.h37
-rw-r--r--pjsip-apps/src/ipjsua/Classes/FirstViewController.m107
-rw-r--r--pjsip-apps/src/ipjsua/Classes/TabBarController.h26
-rw-r--r--pjsip-apps/src/ipjsua/Classes/TabBarController.m30
-rw-r--r--pjsip-apps/src/ipjsua/Classes/ipjsuaAppDelegate.h37
-rw-r--r--pjsip-apps/src/ipjsua/Classes/ipjsuaAppDelegate.m252
-rw-r--r--pjsip-apps/src/ipjsua/MainWindow.xib780
-rw-r--r--pjsip-apps/src/ipjsua/Resources-iPad/MainWindow-iPad.xib913
-rw-r--r--pjsip-apps/src/ipjsua/Resources-iPad/SecondView-iPad.xib561
-rw-r--r--pjsip-apps/src/ipjsua/SecondView.xib501
-rw-r--r--pjsip-apps/src/ipjsua/config.cfg2
-rw-r--r--pjsip-apps/src/ipjsua/ipjsua-Info.plist39
-rw-r--r--pjsip-apps/src/ipjsua/ipjsua.xcodeproj/project.pbxproj492
-rw-r--r--pjsip-apps/src/ipjsua/ipjsua_Prefix.pch8
-rw-r--r--pjsip-apps/src/ipjsua/main.m27
-rw-r--r--pjsip-apps/src/ipjsystest/Classes/RootViewController.h32
-rw-r--r--pjsip-apps/src/ipjsystest/Classes/RootViewController.m335
-rw-r--r--pjsip-apps/src/ipjsystest/Classes/TestViewController.h35
-rw-r--r--pjsip-apps/src/ipjsystest/Classes/TestViewController.m91
-rw-r--r--pjsip-apps/src/ipjsystest/Classes/ipjsystestAppDelegate.h29
-rw-r--r--pjsip-apps/src/ipjsystest/Classes/ipjsystestAppDelegate.m55
-rw-r--r--pjsip-apps/src/ipjsystest/MainWindow.xib507
-rw-r--r--pjsip-apps/src/ipjsystest/RootViewController.xib380
-rw-r--r--pjsip-apps/src/ipjsystest/TestViewController.xib496
-rw-r--r--pjsip-apps/src/ipjsystest/ipjsystest-Info.plist34
-rwxr-xr-xpjsip-apps/src/ipjsystest/ipjsystest.xcodeproj/project.pbxproj434
-rw-r--r--pjsip-apps/src/ipjsystest/ipjsystest_Prefix.pch14
-rw-r--r--pjsip-apps/src/ipjsystest/main.m27
-rw-r--r--pjsip-apps/src/pjsua/gui.h39
-rw-r--r--pjsip-apps/src/pjsua/main.c113
-rw-r--r--pjsip-apps/src/pjsua/main_rtems.c12
-rw-r--r--pjsip-apps/src/pjsua/pjsua_app.c6312
-rw-r--r--pjsip-apps/src/pjsua_wince/README.TXT0
-rw-r--r--pjsip-apps/src/pjsua_wince/StdAfx.cpp8
-rw-r--r--pjsip-apps/src/pjsua_wince/StdAfx.h25
-rw-r--r--pjsip-apps/src/pjsua_wince/newres.h39
-rw-r--r--pjsip-apps/src/pjsua_wince/output/.keep0
-rw-r--r--pjsip-apps/src/pjsua_wince/pjsua_wince.cpp780
-rw-r--r--pjsip-apps/src/pjsua_wince/pjsua_wince.h12
-rw-r--r--pjsip-apps/src/pjsua_wince/pjsua_wince.icobin0 -> 1078 bytes
-rw-r--r--pjsip-apps/src/pjsua_wince/pjsua_wince.rc108
-rw-r--r--pjsip-apps/src/pjsua_wince/pjsua_wince.vcp1097
-rw-r--r--pjsip-apps/src/pjsua_wince/pjsua_wince.vcproj3627
-rw-r--r--pjsip-apps/src/pjsua_wince/resource.h28
-rw-r--r--pjsip-apps/src/pjsystest/gui.h72
-rw-r--r--pjsip-apps/src/pjsystest/main_console.c144
-rw-r--r--pjsip-apps/src/pjsystest/main_wm.c444
-rw-r--r--pjsip-apps/src/pjsystest/pjsystest_wince.rc108
-rw-r--r--pjsip-apps/src/pjsystest/pjsystest_wince.rc210
-rw-r--r--pjsip-apps/src/pjsystest/resource.h18
-rw-r--r--pjsip-apps/src/pjsystest/systest.c1369
-rw-r--r--pjsip-apps/src/pjsystest/systest.h106
-rw-r--r--pjsip-apps/src/pocketpj/PocketPJ.cpp66
-rw-r--r--pjsip-apps/src/pocketpj/PocketPJ.h49
-rw-r--r--pjsip-apps/src/pocketpj/PocketPJ.rc316
-rw-r--r--pjsip-apps/src/pocketpj/PocketPJ.vcc102
-rw-r--r--pjsip-apps/src/pocketpj/PocketPJ.vcp1923
-rw-r--r--pjsip-apps/src/pocketpj/PocketPJ.vcproj5137
-rw-r--r--pjsip-apps/src/pocketpj/PocketPJ.vcw269
-rw-r--r--pjsip-apps/src/pocketpj/PocketPJDlg.cpp792
-rw-r--r--pjsip-apps/src/pocketpj/PocketPJDlg.h129
-rw-r--r--pjsip-apps/src/pocketpj/PopUpWnd.cpp235
-rw-r--r--pjsip-apps/src/pocketpj/PopUpWnd.h67
-rw-r--r--pjsip-apps/src/pocketpj/ReadMe.txt81
-rw-r--r--pjsip-apps/src/pocketpj/SettingsDlg.cpp376
-rw-r--r--pjsip-apps/src/pocketpj/SettingsDlg.h99
-rw-r--r--pjsip-apps/src/pocketpj/StdAfx.cpp6
-rw-r--r--pjsip-apps/src/pocketpj/StdAfx.h32
-rw-r--r--pjsip-apps/src/pocketpj/newres.h28
-rw-r--r--pjsip-apps/src/pocketpj/output/.keep0
-rw-r--r--pjsip-apps/src/pocketpj/res/PocketPJ.icobin0 -> 1078 bytes
-rw-r--r--pjsip-apps/src/pocketpj/res/PocketPJ.rc213
-rw-r--r--pjsip-apps/src/pocketpj/res/action.bmpbin0 -> 246 bytes
-rw-r--r--pjsip-apps/src/pocketpj/res/blank.bmpbin0 -> 246 bytes
-rw-r--r--pjsip-apps/src/pocketpj/res/invisibl.bmpbin0 -> 246 bytes
-rw-r--r--pjsip-apps/src/pocketpj/res/invisibl.icobin0 -> 318 bytes
-rw-r--r--pjsip-apps/src/pocketpj/res/offline.bmpbin0 -> 246 bytes
-rw-r--r--pjsip-apps/src/pocketpj/res/offline.icobin0 -> 318 bytes
-rw-r--r--pjsip-apps/src/pocketpj/res/online.bmpbin0 -> 246 bytes
-rw-r--r--pjsip-apps/src/pocketpj/res/online.icobin0 -> 318 bytes
-rw-r--r--pjsip-apps/src/pocketpj/resource.h71
-rw-r--r--pjsip-apps/src/py_pjsua/DEPRECATED.txt2
-rw-r--r--pjsip-apps/src/py_pjsua/Makefile6
-rw-r--r--pjsip-apps/src/py_pjsua/helper.mak17
-rw-r--r--pjsip-apps/src/py_pjsua/pjsua.py264
-rw-r--r--pjsip-apps/src/py_pjsua/pjsua_app.py780
-rw-r--r--pjsip-apps/src/py_pjsua/py_pjsua.c5872
-rw-r--r--pjsip-apps/src/py_pjsua/py_pjsua.def2
-rw-r--r--pjsip-apps/src/py_pjsua/py_pjsua.h2662
-rw-r--r--pjsip-apps/src/py_pjsua/setup.py44
-rw-r--r--pjsip-apps/src/python/Makefile12
-rw-r--r--pjsip-apps/src/python/_pjsua.c4605
-rw-r--r--pjsip-apps/src/python/_pjsua.def2
-rw-r--r--pjsip-apps/src/python/_pjsua.h3508
-rw-r--r--pjsip-apps/src/python/helper.mak17
-rw-r--r--pjsip-apps/src/python/pjsua.py2862
-rw-r--r--pjsip-apps/src/python/samples/call.py169
-rw-r--r--pjsip-apps/src/python/samples/presence.py175
-rw-r--r--pjsip-apps/src/python/samples/registration.py70
-rw-r--r--pjsip-apps/src/python/samples/simplecall.py88
-rw-r--r--pjsip-apps/src/python/setup-vc.py80
-rw-r--r--pjsip-apps/src/python/setup.py113
-rw-r--r--pjsip-apps/src/samples/aectest.c304
-rw-r--r--pjsip-apps/src/samples/auddemo.c582
-rw-r--r--pjsip-apps/src/samples/aviplay.c560
-rw-r--r--pjsip-apps/src/samples/confbench.c347
-rw-r--r--pjsip-apps/src/samples/confsample.c609
-rw-r--r--pjsip-apps/src/samples/debug.c32
-rw-r--r--pjsip-apps/src/samples/encdec.c263
-rw-r--r--pjsip-apps/src/samples/footprint.c654
-rw-r--r--pjsip-apps/src/samples/httpdemo.c183
-rw-r--r--pjsip-apps/src/samples/icedemo.c1276
-rw-r--r--pjsip-apps/src/samples/invtester.c295
-rw-r--r--pjsip-apps/src/samples/jbsim.c1141
-rw-r--r--pjsip-apps/src/samples/latency.c202
-rw-r--r--pjsip-apps/src/samples/level.c179
-rw-r--r--pjsip-apps/src/samples/main_rtems.c12
-rw-r--r--pjsip-apps/src/samples/mix.c237
-rw-r--r--pjsip-apps/src/samples/pcaputil.c540
-rw-r--r--pjsip-apps/src/samples/pjsip-perf.c1853
-rw-r--r--pjsip-apps/src/samples/playfile.c217
-rw-r--r--pjsip-apps/src/samples/playsine.c317
-rw-r--r--pjsip-apps/src/samples/proxy.h585
-rw-r--r--pjsip-apps/src/samples/recfile.c202
-rw-r--r--pjsip-apps/src/samples/resampleplay.c232
-rw-r--r--pjsip-apps/src/samples/simple_pjsua.c201
-rw-r--r--pjsip-apps/src/samples/simpleua.c1030
-rw-r--r--pjsip-apps/src/samples/sipecho.c688
-rw-r--r--pjsip-apps/src/samples/siprtp.c2189
-rw-r--r--pjsip-apps/src/samples/siprtp_report.c231
-rw-r--r--pjsip-apps/src/samples/sipstateless.c243
-rw-r--r--pjsip-apps/src/samples/stateful_proxy.c587
-rw-r--r--pjsip-apps/src/samples/stateless_proxy.c255
-rw-r--r--pjsip-apps/src/samples/stereotest.c336
-rw-r--r--pjsip-apps/src/samples/streamutil.c1174
-rw-r--r--pjsip-apps/src/samples/strerror.c71
-rw-r--r--pjsip-apps/src/samples/tonegen.c159
-rw-r--r--pjsip-apps/src/samples/util.h173
-rw-r--r--pjsip-apps/src/samples/vid_streamutil.c967
-rw-r--r--pjsip-apps/src/symbian_ua/main_symbian.cpp82
-rw-r--r--pjsip-apps/src/symbian_ua/symbian_ua_reg.rss10
-rw-r--r--pjsip-apps/src/symbian_ua/ua.cpp1186
-rw-r--r--pjsip-apps/src/symbian_ua/ua.h24
-rw-r--r--pjsip-apps/src/symbian_ua_gui/application.uidesign157
-rw-r--r--pjsip-apps/src/symbian_ua_gui/data/symbian_ua_gui.l0112
-rw-r--r--pjsip-apps/src/symbian_ua_gui/data/symbian_ua_gui.loc11
-rw-r--r--pjsip-apps/src/symbian_ua_gui/data/symbian_ua_gui.rss71
-rw-r--r--pjsip-apps/src/symbian_ua_gui/data/symbian_ua_guiContainer.l0121
-rw-r--r--pjsip-apps/src/symbian_ua_gui/data/symbian_ua_guiContainer.loc11
-rw-r--r--pjsip-apps/src/symbian_ua_gui/data/symbian_ua_guiContainer.rssi141
-rw-r--r--pjsip-apps/src/symbian_ua_gui/data/symbian_ua_guiSettingItemList.l0131
-rw-r--r--pjsip-apps/src/symbian_ua_gui/data/symbian_ua_guiSettingItemList.loc11
-rw-r--r--pjsip-apps/src/symbian_ua_gui/data/symbian_ua_guiSettingItemList.rssi275
-rw-r--r--pjsip-apps/src/symbian_ua_gui/data/symbian_ua_gui_reg.loc11
-rw-r--r--pjsip-apps/src/symbian_ua_gui/data/symbian_ua_gui_reg.rss21
-rw-r--r--pjsip-apps/src/symbian_ua_gui/gfx/list_icon.bmpbin0 -> 2356 bytes
-rw-r--r--pjsip-apps/src/symbian_ua_gui/gfx/list_icon_mask.bmpbin0 -> 294 bytes
-rw-r--r--pjsip-apps/src/symbian_ua_gui/gfx/mark_icon.bmpbin0 -> 2134 bytes
-rw-r--r--pjsip-apps/src/symbian_ua_gui/gfx/mark_icon_mask.bmpbin0 -> 166 bytes
-rw-r--r--pjsip-apps/src/symbian_ua_gui/gfx/qgn_menu_symbian_ua_gui.svg56
-rw-r--r--pjsip-apps/src/symbian_ua_gui/group/ABLD.BAT15
-rw-r--r--pjsip-apps/src/symbian_ua_gui/group/Icons_aif_scalable_dc.mk71
-rw-r--r--pjsip-apps/src/symbian_ua_gui/group/bld.inf12
-rw-r--r--pjsip-apps/src/symbian_ua_gui/group/symbian_ua_gui.mmp102
-rw-r--r--pjsip-apps/src/symbian_ua_gui/inc/Symbian_ua_guiSettingItemListSettings.h73
-rw-r--r--pjsip-apps/src/symbian_ua_gui/inc/symbian_ua.h50
-rw-r--r--pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_gui.hrh17
-rw-r--r--pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_gui.pan18
-rw-r--r--pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_guiAppUi.h129
-rw-r--r--pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_guiApplication.h45
-rw-r--r--pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_guiContainer.h123
-rw-r--r--pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_guiContainer.hrh17
-rw-r--r--pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_guiContainerView.h98
-rw-r--r--pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_guiDocument.h46
-rw-r--r--pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_guiSettingItemList.h97
-rw-r--r--pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_guiSettingItemList.hrh22
-rw-r--r--pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_guiSettingItemListView.h95
-rw-r--r--pjsip-apps/src/symbian_ua_gui/sis/symbian_ua_gui.pkg36
-rw-r--r--pjsip-apps/src/symbian_ua_gui/sis/symbian_ua_gui.txt0
-rw-r--r--pjsip-apps/src/symbian_ua_gui/src/Symbian_ua_guiSettingItemListSets.cpp154
-rw-r--r--pjsip-apps/src/symbian_ua_gui/src/symbian_ua.cpp514
-rw-r--r--pjsip-apps/src/symbian_ua_gui/src/symbian_ua_guiAppUi.cpp257
-rw-r--r--pjsip-apps/src/symbian_ua_gui/src/symbian_ua_guiApplication.cpp96
-rw-r--r--pjsip-apps/src/symbian_ua_gui/src/symbian_ua_guiContainer.cpp295
-rw-r--r--pjsip-apps/src/symbian_ua_gui/src/symbian_ua_guiContainerView.cpp488
-rw-r--r--pjsip-apps/src/symbian_ua_gui/src/symbian_ua_guiDocument.cpp67
-rw-r--r--pjsip-apps/src/symbian_ua_gui/src/symbian_ua_guiSettingItemList.cpp433
-rw-r--r--pjsip-apps/src/symbian_ua_gui/src/symbian_ua_guiSettingItemListView.cpp295
-rw-r--r--pjsip-apps/src/symbian_ua_gui/symbian_ua_guiContainer.uidesign382
-rw-r--r--pjsip-apps/src/symbian_ua_gui/symbian_ua_guiSettingItemList.uidesign380
-rw-r--r--pjsip-apps/src/symsndtest/app_main.cpp434
-rw-r--r--pjsip-apps/src/symsndtest/main_symbian.cpp83
-rw-r--r--pjsip-apps/src/symsndtest/symsndtest_reg.rss10
-rw-r--r--pjsip-apps/src/vidgui/INSTALL.TXT32
-rw-r--r--pjsip-apps/src/vidgui/pj-pkgconfig.mak10
-rw-r--r--pjsip-apps/src/vidgui/vidgui.cpp735
-rw-r--r--pjsip-apps/src/vidgui/vidgui.h102
-rw-r--r--pjsip-apps/src/vidgui/vidgui.pro36
-rw-r--r--pjsip-apps/src/vidgui/vidwin.cpp309
-rw-r--r--pjsip-apps/src/vidgui/vidwin.h55
229 files changed, 95147 insertions, 0 deletions
diff --git a/pjsip-apps/bin/samples/.keep b/pjsip-apps/bin/samples/.keep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/pjsip-apps/bin/samples/.keep
diff --git a/pjsip-apps/build/Footprint.mak b/pjsip-apps/build/Footprint.mak
new file mode 100644
index 0000000..cc63179
--- /dev/null
+++ b/pjsip-apps/build/Footprint.mak
@@ -0,0 +1,28 @@
+#
+# This file is used by get-footprint.py script to build samples/footprint.c
+# to get the footprint report for PJSIP/PJMEDIA.
+#
+include ../../build.mak
+include ../../build/common.mak
+
+
+###############################################################################
+# Gather all flags.
+#
+export _CFLAGS := $(APP_CFLAGS) $(CFLAGS)
+export _CXXFLAGS:= $(_CFLAGS)
+
+export _LDFLAGS := $(APP_LDFLAGS) $(APP_LDLIBS) $(LDFLAGS)
+
+EXE := footprint.exe
+
+all:
+ $(APP_CC) -o $(EXE) ../src/samples/footprint.c $(FCFLAGS) $(_CFLAGS) $(_LDFLAGS)
+ $(CROSS_COMPILE)strip --strip-all $(EXE)
+
+clean:
+ rm -f $(EXE)
+
+print_name:
+ @echo $(MACHINE_NAME) $(OS_NAME) $(CROSS_COMPILE)$(CC_NAME) `$(CROSS_COMPILE)$(CC_NAME) -dumpversion`
+
diff --git a/pjsip-apps/build/Makefile b/pjsip-apps/build/Makefile
new file mode 100644
index 0000000..146e841
--- /dev/null
+++ b/pjsip-apps/build/Makefile
@@ -0,0 +1,94 @@
+include ../../build.mak
+include $(PJDIR)/build/common.mak
+
+
+RULES_MAK := $(PJDIR)/build/rules.mak
+
+PJLIB_LIB:=../../pjlib/lib/libpj-$(TARGET_NAME)$(LIBEXT)
+PJLIB_UTIL_LIB:=../../pjlib-util/lib/libpjlib-util-$(TARGET_NAME)$(LIBEXT)
+PJNATH_LIB:=../../pjnath/lib/libpjnath-$(TARGET_NAME)$(LIBEXT)
+PJMEDIA_LIB:=../../pjmedia/lib/libpjmedia-$(TARGET_NAME)$(LIBEXT)
+PJMEDIA_AUDIODEV_LIB:=../../pjmedia/lib/libpjmedia-audiodev-$(TARGET_NAME)$(LIBEXT)
+PJMEDIA_CODEC_LIB:=../../pjmedia/lib/libpjmedia-codec-$(TARGET_NAME)$(LIBEXT)
+PJSIP_LIB:=../../pjsip/lib/libpjsip-$(TARGET_NAME)$(LIBEXT)
+PJSIP_UA_LIB:=../../pjsip/lib/libpjsip-ua-$(TARGET_NAME)$(LIBEXT)
+PJSIP_SIMPLE_LIB:=../../pjsip/lib/libpjsip-simple-$(TARGET_NAME)$(LIBEXT)
+PJSUA_LIB_LIB=../../pjsip/lib/libpjsua-$(TARGET_NAME)$(LIBEXT)
+
+
+###############################################################################
+# Gather all flags.
+#
+export _CFLAGS := $(CC_CFLAGS) $(OS_CFLAGS) $(HOST_CFLAGS) $(M_CFLAGS) \
+ $(PJ_CFLAGS) $(CFLAGS) $(CC_INC)../../pjsip/include \
+ $(CC_INC)../../pjlib/include \
+ $(CC_INC)../../pjlib-util/include \
+ $(CC_INC)../../pjnath/include \
+ $(CC_INC)../../pjmedia/include
+export _CXXFLAGS:= $(_CFLAGS) $(CC_CXXFLAGS) $(OS_CXXFLAGS) $(M_CXXFLAGS) \
+ $(HOST_CXXFLAGS) $(CXXFLAGS)
+
+###############################################################################
+# Defines for building PJSUA
+#
+export PJSUA_SRCDIR = ../src/pjsua
+export PJSUA_OBJS += $(OS_OBJS) $(M_OBJS) $(CC_OBJS) $(HOST_OBJS) \
+ main.o pjsua_app.o
+export PJSUA_CFLAGS += $(_CFLAGS)
+export PJSUA_LDFLAGS += $(APP_LDFLAGS) $(APP_LDLIBS) $(LDFLAGS)
+export PJSUA_EXE:=../bin/pjsua-$(TARGET_NAME)$(HOST_EXE)
+
+
+###############################################################################
+# Defines for building pjsystest
+#
+export PJSYSTEST_SRCDIR = ../src/pjsystest
+export PJSYSTEST_OBJS += $(OS_OBJS) $(M_OBJS) $(CC_OBJS) $(HOST_OBJS) \
+ systest.o main_console.o
+export PJSYSTEST_CFLAGS += $(_CFLAGS)
+export PJSYSTEST_LDFLAGS += $(APP_LDFLAGS) $(APP_LDLIBS) $(LDFLAGS)
+export PJSYSTEST_EXE:=../bin/pjsystest-$(TARGET_NAME)$(HOST_EXE)
+
+
+export CC_OUT CC AR RANLIB HOST_MV HOST_RM HOST_RMDIR HOST_MKDIR OBJEXT LD LDOUT
+###############################################################################
+# Main entry
+#
+#
+TARGETS := pjsua pjsystest samples
+
+.PHONY: $(TARGETS)
+
+all: $(TARGETS)
+
+doc:
+
+dep: depend
+distclean: realclean
+
+.PHONY: dep depend pjsua clean realclean distclean
+
+pjsua:
+ $(MAKE) -f $(RULES_MAK) APP=PJSUA app=pjsua $(PJSUA_EXE)
+
+pjsystest:
+ $(MAKE) -f $(RULES_MAK) APP=PJSYSTEST app=pjsystest $(PJSYSTEST_EXE)
+
+samples:
+ $(MAKE) -f Samples.mak
+
+.PHONY: ../lib/pjsua.ko
+../lib/pjsua.ko:
+ $(MAKE) -f $(RULES_MAK) APP=PJSUA app=pjsua $@
+
+clean depend realclean:
+ $(MAKE) -f $(RULES_MAK) APP=PJSUA app=pjsua $@
+ $(MAKE) -f $(RULES_MAK) APP=PJSYSTEST app=pjsystest $@
+ $(MAKE) -f Samples.mak $@
+ @if test "$@" = "depend"; then \
+ echo '$(PJSUA_EXE): $(APP_LIB_FILES)' >> .pjsua-$(TARGET_NAME).depend; \
+ echo '$(PJSYSTEST_EXE): $(APP_LIB_FILES)' >> .pjsystest-$(TARGET_NAME).depend; \
+ fi
+
+
+
diff --git a/pjsip-apps/build/Samples-vc.mak b/pjsip-apps/build/Samples-vc.mak
new file mode 100644
index 0000000..279c78e
--- /dev/null
+++ b/pjsip-apps/build/Samples-vc.mak
@@ -0,0 +1,116 @@
+
+LIBEXT = .lib
+
+TARGET = i386-win32-vc$(VC_VER)-$(BUILD_MODE)
+
+!if "$(BUILD_MODE)" == "debug"
+BUILD_FLAGS = /MTd /Od /Zi /W4
+!elseif "$(BUILD_MODE)" == "debug-static"
+BUILD_FLAGS = /MTd /Od /Zi /W4
+!elseif "$(BUILD_MODE)" == "debug-dynamic"
+BUILD_FLAGS = /MDd /Od /Zi /W4
+!elseif "$(BUILD_MODE)" == "release-static"
+BUILD_FLAGS = /Ox /MT /DNDEBUG /W4
+!else
+BUILD_FLAGS = /Ox /MD /DNDEBUG /W4
+!endif
+
+PJLIB_LIB = ..\..\pjlib\lib\pjlib-$(TARGET)$(LIBEXT)
+PJLIB_UTIL_LIB = ..\..\pjlib-util\lib\pjlib-util-$(TARGET)$(LIBEXT)
+PJNATH_LIB = ..\..\pjnath\lib\pjnath-$(TARGET)$(LIBEXT)
+PJMEDIA_LIB = ..\..\pjmedia\lib\pjmedia-$(TARGET)$(LIBEXT)
+PJMEDIA_CODEC_LIB = ..\..\pjmedia\lib\pjmedia-codec-$(TARGET)$(LIBEXT)
+PJMEDIA_AUDIODEV_LIB = ..\..\pjmedia\lib\pjmedia-audiodev-$(TARGET)$(LIBEXT)
+PJMEDIA_VIDEODEV_LIB = ..\..\pjmedia\lib\pjmedia-videodev-$(TARGET)$(LIBEXT)
+PJSIP_LIB = ..\..\pjsip\lib\pjsip-core-$(TARGET)$(LIBEXT)
+PJSIP_UA_LIB = ..\..\pjsip\lib\pjsip-ua-$(TARGET)$(LIBEXT)
+PJSIP_SIMPLE_LIB = ..\..\pjsip\lib\pjsip-simple-$(TARGET)$(LIBEXT)
+PJSUA_LIB_LIB = ..\..\pjsip\lib\pjsua-lib-$(TARGET)$(LIBEXT)
+
+GSM_LIB = ..\..\third_party\lib\libgsmcodec-$(TARGET)$(LIBEXT)
+ILBC_LIB = ..\..\third_party\lib\libilbccodec-$(TARGET)$(LIBEXT)
+PORTAUDIO_LIB = ..\..\third_party\lib\libportaudio-$(TARGET)$(LIBEXT)
+RESAMPLE_LIB = ..\..\third_party\lib\libresample-$(TARGET)$(LIBEXT)
+SPEEX_LIB = ..\..\third_party\lib\libspeex-$(TARGET)$(LIBEXT)
+SRTP_LIB = ..\..\third_party\lib\libsrtp-$(TARGET)$(LIBEXT)
+G7221_LIB = ..\..\third_party\lib\libg7221codec-$(TARGET)$(LIBEXT)
+BASECLASSES_LIB = ..\..\third_party\lib\libbaseclasses-$(TARGET)$(LIBEXT)
+
+THIRD_PARTY_LIBS = $(GSM_LIB) $(ILBC_LIB) $(PORTAUDIO_LIB) $(RESAMPLE_LIB) \
+ $(SPEEX_LIB) $(SRTP_LIB) $(G7221_LIB) $(BASECLASSES_LIB)
+
+LIBS = $(PJSUA_LIB_LIB) $(PJSIP_UA_LIB) $(PJSIP_SIMPLE_LIB) \
+ $(PJSIP_LIB) $(PJMEDIA_CODEC_LIB) $(PJMEDIA_AUDIODEV_LIB) \
+ $(PJMEDIA_VIDEODEV_LIB) \
+ $(PJMEDIA_LIB) $(PJNATH_LIB) $(PJLIB_UTIL_LIB) $(PJLIB_LIB) \
+ $(THIRD_PARTY_LIBS)
+
+CFLAGS = /DPJ_WIN32=1 /DPJ_M_I386=1 \
+ $(BUILD_FLAGS) \
+ -I..\..\pjsip\include \
+ -I..\..\pjlib\include \
+ -I..\..\pjlib-util\include \
+ -I..\..\pjmedia\include \
+ -I..\..\pjnath/include
+LDFLAGS = $(BUILD_FLAGS) $(LIBS) \
+ Iphlpapi.lib ole32.lib user32.lib dsound.lib dxguid.lib netapi32.lib \
+ mswsock.lib ws2_32.lib gdi32.lib advapi32.lib oleaut32.lib
+
+SRCDIR = ..\src\samples
+OBJDIR = .\output\samples-$(TARGET)
+BINDIR = ..\bin\samples\$(TARGET)
+
+
+SAMPLES = $(BINDIR)\auddemo.exe \
+ $(BINDIR)\aectest.exe \
+ $(BINDIR)\aviplay.exe \
+ $(BINDIR)\confsample.exe \
+ $(BINDIR)\confbench.exe \
+ $(BINDIR)\encdec.exe \
+ $(BINDIR)\httpdemo.exe \
+ $(BINDIR)\icedemo.exe \
+ $(BINDIR)\jbsim.exe \
+ $(BINDIR)\latency.exe \
+ $(BINDIR)\level.exe \
+ $(BINDIR)\mix.exe \
+ $(BINDIR)\pcaputil.exe\
+ $(BINDIR)\pjsip-perf.exe \
+ $(BINDIR)\playfile.exe \
+ $(BINDIR)\playsine.exe\
+ $(BINDIR)\recfile.exe \
+ $(BINDIR)\resampleplay.exe \
+ $(BINDIR)\simpleua.exe \
+ $(BINDIR)\simple_pjsua.exe \
+ $(BINDIR)\sipecho.exe \
+ $(BINDIR)\siprtp.exe \
+ $(BINDIR)\sipstateless.exe \
+ $(BINDIR)\stateful_proxy.exe \
+ $(BINDIR)\stateless_proxy.exe \
+ $(BINDIR)\stereotest.exe \
+ $(BINDIR)\streamutil.exe \
+ $(BINDIR)\strerror.exe \
+ $(BINDIR)\tonegen.exe \
+ $(BINDIR)\vid_streamutil.exe
+
+
+all: $(BINDIR) $(OBJDIR) $(SAMPLES)
+
+$(SAMPLES): $(SRCDIR)\$(@B).c $(LIBS) $(SRCDIR)\util.h Samples-vc.mak
+ cl -nologo -c $(SRCDIR)\$(@B).c /Fo$(OBJDIR)\$(@B).obj $(CFLAGS)
+ cl /nologo $(OBJDIR)\$(@B).obj /Fe$@ /Fm$(OBJDIR)\$(@B).map $(LDFLAGS)
+ @rem the following two lines is just for cleaning up the 'bin' directory
+ if exist $(BINDIR)\*.ilk del /Q $(BINDIR)\*.ilk
+ if exist $(BINDIR)\*.pdb del /Q $(BINDIR)\*.pdb
+
+$(BINDIR):
+ if not exist $(BINDIR) mkdir $(BINDIR)
+
+$(OBJDIR):
+ if not exist $(OBJDIR) mkdir $(OBJDIR)
+
+clean:
+ echo Cleaning up samples...
+ if exist $(BINDIR) del /Q $(BINDIR)\*
+ if exist $(BINDIR) rmdir $(BINDIR)
+ if exist $(OBJDIR) del /Q $(OBJDIR)\*.*
+
diff --git a/pjsip-apps/build/Samples.mak b/pjsip-apps/build/Samples.mak
new file mode 100644
index 0000000..e4aca92
--- /dev/null
+++ b/pjsip-apps/build/Samples.mak
@@ -0,0 +1,78 @@
+
+include ../../build/common.mak
+
+
+###############################################################################
+# Gather all flags.
+#
+export _CFLAGS := $(PJ_CFLAGS) $(CFLAGS)
+export _CXXFLAGS:= $(PJ_CXXFLAGS)
+export _LDFLAGS := $(PJ_LDFLAGS) $(PJ_LDLIBS) $(LDFLAGS)
+
+SRCDIR := ../src/samples
+OBJDIR := ./output/samples-$(TARGET_NAME)
+BINDIR := ../bin/samples/$(TARGET_NAME)
+
+SAMPLES := auddemo \
+ aviplay \
+ aectest \
+ aviplay \
+ confsample \
+ encdec \
+ httpdemo \
+ icedemo \
+ jbsim \
+ latency \
+ level \
+ mix \
+ pjsip-perf \
+ pcaputil \
+ playfile \
+ playsine \
+ recfile \
+ resampleplay \
+ simpleua \
+ simple_pjsua \
+ sipecho \
+ siprtp \
+ sipstateless \
+ stateful_proxy \
+ stateless_proxy \
+ stereotest \
+ streamutil \
+ strerror \
+ tonegen \
+ vid_streamutil
+
+EXES := $(foreach file, $(SAMPLES), $(BINDIR)/$(file)$(HOST_EXE))
+
+all: $(BINDIR) $(OBJDIR) $(EXES)
+
+$(BINDIR)/%$(HOST_EXE): $(OBJDIR)/%$(OBJEXT) $(PJ_LIB_FILES)
+ $(LD) $(LDOUT)$(subst /,$(HOST_PSEP),$@) \
+ $(subst /,$(HOST_PSEP),$<) \
+ $(_LDFLAGS)
+
+$(OBJDIR)/%$(OBJEXT): $(SRCDIR)/%.c
+ $(CC) $(_CFLAGS) \
+ $(CC_OUT)$(subst /,$(HOST_PSEP),$@) \
+ $(subst /,$(HOST_PSEP),$<)
+
+$(OBJDIR):
+ $(subst @@,$(subst /,$(HOST_PSEP),$@),$(HOST_MKDIR))
+
+$(BINDIR):
+ $(subst @@,$(subst /,$(HOST_PSEP),$@),$(HOST_MKDIR))
+
+depend:
+
+clean:
+ $(subst @@,$(subst /,$(HOST_PSEP),$(OBJDIR)/*),$(HOST_RMR))
+ $(subst @@,$(subst /,$(HOST_PSEP),$(OBJDIR)),$(HOST_RMDIR))
+ $(subst @@,$(EXES),$(HOST_RM))
+ rm -rf $(BINDIR)
+
+distclean realclean: clean
+# $(subst @@,$(subst /,$(HOST_PSEP),$(EXES)) $(subst /,$(HOST_PSEP),$(EXES)),$(HOST_RM))
+# $(subst @@,$(DEP_FILE),$(HOST_RM))
+
diff --git a/pjsip-apps/build/dummy.c b/pjsip-apps/build/dummy.c
new file mode 100644
index 0000000..1cb9b48
--- /dev/null
+++ b/pjsip-apps/build/dummy.c
@@ -0,0 +1,9 @@
+/* $Id: dummy.c 2660 2009-04-28 19:38:43Z nanang $ */
+
+/**
+ * This is an empty C file for helping libpjproject so it gets built properly.
+ */
+
+#ifdef _MSC_VER
+# pragma warning(disable: 4206) // translation unit is empty
+#endif
diff --git a/pjsip-apps/build/get-footprint.py b/pjsip-apps/build/get-footprint.py
new file mode 100644
index 0000000..f936c0c
--- /dev/null
+++ b/pjsip-apps/build/get-footprint.py
@@ -0,0 +1,338 @@
+# $Id: get-footprint.py 1352 2007-06-08 01:41:25Z bennylp $
+#
+# This file is used to generate PJSIP/PJMEDIA footprint report.
+# To use this file, just run it in pjsip-apps/build directory, to
+# produce footprint.txt and footprint.htm report files.
+#
+import os
+import sys
+import string
+import time
+
+compile_flags1 = [
+ # Base
+ ['BASE', 'Empty application size'],
+ ['', 'Subtotal: Empty application size'],
+
+ ['HAS_PJLIB', 'Minimum PJLIB only'],
+
+ # Subtotal
+ ['', 'Subtotal'],
+
+ # PJLIB-UTIL
+ ['HAS_PJLIB_STUN', 'STUN client'],
+ ['HAS_PJLIB_GETOPT', 'getopt() functionality'],
+
+ # Subtotal
+ ['', 'TOTAL']
+]
+
+compile_flags = [
+ # Base
+ ['BASE', 'Empty application size'],
+ ['', 'Subtotal: empty application size on this platform'],
+
+ ['HAS_PJLIB', 'PJLIB (pool, data structures, hash tables, ioqueue, socket, timer heap, etc.). ' +
+ 'For targets that statically link application with LIBC, the size includes ' +
+ 'various LIBC functions that are used by PJLIB.'],
+ ['', 'Subtotal: Application linked with PJLIB'],
+
+ # PJLIB-UTIL
+ ['HAS_PJLIB_STUN', 'PJLIB-UTIL STUN client'],
+ ['HAS_PJLIB_GETOPT', 'PJLIB-UTIL getopt() functionality'],
+ ['HAS_PJLIB_SCANNER', 'PJLIB-UTIL text scanner (needed by SIP parser)'],
+ ['HAS_PJLIB_XML', 'PJLIB-UTIL tiny XML (parsing and API) (needs text scanner)'],
+ ['HAS_PJLIB_DNS', 'PJLIB-UTIL DNS packet and parsing'],
+ ['HAS_PJLIB_RESOLVER', 'PJLIB-UTIL Asynchronous DNS resolver/caching engine'],
+ ['HAS_PJLIB_CRC32', 'PJLIB-UTIL CRC32 algorithm'],
+ ['HAS_PJLIB_HMAC_MD5', 'PJLIB-UTIL HMAC-MD5 algorithm'],
+ ['HAS_PJLIB_HMAC_SHA1', 'PJLIB-UTIL HMAC-SHA1 algorithm'],
+
+ # PJSIP
+ ['HAS_PJSIP_CORE_MSG_ELEM', 'PJSIP Core - Messaging Elements and Parsing (message, headers, SIP URI, TEL URI/RFC 3966, etc.)'],
+ ['HAS_PJSIP_CORE', 'PJSIP Core - Endpoint (transport management, module management, event distribution, etc.)'],
+ ['HAS_PJSIP_CORE_MSG_UTIL', 'PJSIP Core - Stateless operations, SIP SRV, server resolution and fail-over'],
+ ['HAS_PJSIP_UDP_TRANSPORT', 'PJSIP UDP transport'],
+ ['', 'Subtotal: A minimalistic SIP application (parsing, UDP transport+STUN, no transaction)'],
+
+ ['HAS_PJSIP_TCP_TRANSPORT', 'PJSIP TCP transport'],
+ ['HAS_PJSIP_TLS_TRANSPORT', 'PJSIP TLS transport'],
+ ['HAS_PJSIP_INFO', 'PJSIP INFO support (RFC 2976) (no special treatment, thus the zero size)'],
+ ['HAS_PJSIP_TRANSACTION', 'PJSIP transaction and stateful API'],
+ ['HAS_PJSIP_AUTH_CLIENT', 'PJSIP digest authentication client'],
+ ['HAS_PJSIP_UA_LAYER', 'PJSIP User agent layer and base dialog and usage management (draft-ietf-sipping-dialogusage-01)'],
+ ['HAS_PJMEDIA_SDP', 'PJMEDIA SDP Parsing and API (RFC 2327), needed by SDP negotiator'],
+ ['HAS_PJMEDIA_SDP_NEGOTIATOR','PJMEDIA SDP negotiator (RFC 3264), needed by INVITE session'],
+ ['HAS_PJSIP_INV_SESSION', 'PJSIP INVITE session API'],
+ ['HAS_PJSIP_REGC', 'PJSIP client registration API'],
+ ['', 'Subtotal: Minimal SIP application with registration (including digest authentication)'],
+
+ ['HAS_PJSIP_EVENT_FRAMEWORK','PJSIP Event/SUBSCRIBE framework, RFC 3265 (needed by call transfer, and presence)'],
+ ['HAS_PJSIP_CALL_TRANSFER', 'PJSIP Call Transfer/REFER support (RFC 3515)'],
+ ['', 'Subtotal: Minimal SIP application with call transfer'],
+
+
+ ['HAS_PJSIP_PRESENCE', 'PJSIP Presence subscription, including PIDF/X-PIDF support (RFC 3856, RFC 3863, etc) (needs XML)'],
+ ['HAS_PJSIP_MESSAGE', 'PJSIP Instant Messaging/MESSAGE support (RFC 3428) (no special treatment, thus the zero size)'],
+ ['HAS_PJSIP_IS_COMPOSING', 'PJSIP Message Composition indication (RFC 3994)'],
+
+ # Subtotal
+ ['', 'Subtotal: Complete PJSIP package (call, registration, presence, IM) +STUN +GETOPT (+PJLIB), no media'],
+
+ # PJNATH
+ ['HAS_PJNATH_STUN', 'PJNATH STUN'],
+ ['HAS_PJNATH_ICE', 'PJNATH ICE'],
+
+ # PJMEDIA
+ ['HAS_PJMEDIA_EC', 'PJMEDIA accoustic echo cancellation'],
+ ['HAS_PJMEDIA_SND_DEV', 'PJMEDIA sound device backend (platform specific)'],
+ ['HAS_PJMEDIA_SILENCE_DET', 'PJMEDIA Adaptive silence detector'],
+ ['HAS_PJMEDIA', 'PJMEDIA endpoint'],
+ ['HAS_PJMEDIA_PLC', 'PJMEDIA Packet Lost Concealment implementation (needed by G.711, GSM, and sound device port)'],
+ ['HAS_PJMEDIA_SND_PORT', 'PJMEDIA sound device media port'],
+ ['HAS_PJMEDIA_RESAMPLE', 'PJMEDIA resampling algorithm (large filter disabled)'],
+ ['HAS_PJMEDIA_G711_CODEC', 'PJMEDIA G.711 codec (PCMA/PCMU, including PLC) (may have already been linked by other module)'],
+ ['HAS_PJMEDIA_CONFERENCE', 'PJMEDIA conference bridge (needs resampling and silence detector)'],
+ ['HAS_PJMEDIA_MASTER_PORT', 'PJMEDIA master port'],
+ ['HAS_PJMEDIA_RTP', 'PJMEDIA stand-alone RTP'],
+ ['HAS_PJMEDIA_RTCP', 'PJMEDIA stand-alone RTCP and media quality calculation'],
+ ['HAS_PJMEDIA_JBUF', 'PJMEDIA stand-alone adaptive jitter buffer'],
+ ['HAS_PJMEDIA_STREAM', 'PJMEDIA stream for remote media communication (needs RTP, RTCP, and jitter buffer)'],
+ ['HAS_PJMEDIA_TONEGEN', 'PJMEDIA tone generator'],
+ ['HAS_PJMEDIA_UDP_TRANSPORT','PJMEDIA UDP media transport'],
+ ['HAS_PJMEDIA_FILE_PLAYER', 'PJMEDIA WAV file player'],
+ ['HAS_PJMEDIA_FILE_CAPTURE', 'PJMEDIA WAV file writer'],
+ ['HAS_PJMEDIA_MEM_PLAYER', 'PJMEDIA fixed buffer player'],
+ ['HAS_PJMEDIA_MEM_CAPTURE', 'PJMEDIA fixed buffer writer'],
+ ['HAS_PJMEDIA_ICE', 'PJMEDIA ICE transport'],
+
+ # Subtotal
+ ['', 'Subtotal: Complete SIP and all PJMEDIA features (G.711 codec only)'],
+
+ # Codecs
+ ['HAS_PJMEDIA_GSM_CODEC', 'PJMEDIA GSM codec (including PLC)'],
+ ['HAS_PJMEDIA_SPEEX_CODEC', 'PJMEDIA Speex codec (narrowband, wideband, ultra-wideband)'],
+ ['HAS_PJMEDIA_ILBC_CODEC', 'PJMEDIA iLBC codec'],
+
+ # Total
+ ['', 'TOTAL: complete libraries (+all codecs)'],
+]
+
+# Executable size report, tuple of:
+# <all flags>, <flags added>, <text size>, <data>, <bss>, <description>
+exe_size = []
+
+#
+# Write the report to text file
+#
+def print_text_report(filename):
+ output = open(filename, 'w')
+
+ output.write('PJSIP and PJMEDIA footprint report\n')
+ output.write('Auto-generated by pjsip-apps/build/get-footprint.py\n')
+ output.write('\n')
+
+ # Write Revision info.
+ f = os.popen('svn info | grep Revision')
+ output.write(f.readline())
+
+ output.write('Date: ')
+ output.write(time.asctime())
+ output.write('\n')
+ output.write('\n')
+
+ # Write individual module size
+ output.write('Footprint (in bytes):\n')
+ output.write(' .text .data .bss Module Description\n')
+ output.write('==========================================================\n')
+
+ for i in range(1, len(exe_size)):
+ e = exe_size[i]
+ prev = exe_size[i-1]
+
+ if e[1]<>'':
+ output.write(' ')
+ output.write( string.rjust(`string.atoi(e[2]) - string.atoi(prev[2])`, 8) )
+ output.write( string.rjust(`string.atoi(e[3]) - string.atoi(prev[3])`, 8) )
+ output.write( string.rjust(`string.atoi(e[4]) - string.atoi(prev[4])`, 8) )
+ output.write(' ' + e[5] + '\n')
+ else:
+ output.write(' ------------------------\n')
+ output.write(' ')
+ output.write( string.rjust(e[2], 8) )
+ output.write( string.rjust(e[3], 8) )
+ output.write( string.rjust(e[4], 8) )
+ output.write(' ' + e[5] + '\n')
+ output.write('\n')
+
+
+ # Done
+ output.close()
+
+
+#
+# Write the report to HTML file
+#
+def print_html_report():
+
+ # Get Revision info.
+ f = os.popen('svn info | grep Revision')
+ revision = f.readline().split()[1]
+
+ # Get Machine, OS, and CC name
+ f = os.popen('make -f Footprint.mak print_name')
+ names = f.readline().split()
+ m = names[0]
+ o = names[1]
+ cc = names[2]
+ cc_ver = names[3]
+
+ # Open HTML file
+ filename = 'footprint-' + m + '-' + o + '.htm'
+ output = open(filename, 'w')
+
+ title = 'PJSIP and PJMEDIA footprint report for ' + m + '-' + o + ' target'
+ output.write('<HTML><HEAD>\n');
+ output.write(' <TITLE>' + title + '</TITLE>\n')
+ output.write(' <LINK href="/style/style.css" type="text/css" rel="stylesheet">\n')
+ output.write('</HEAD>\n');
+ output.write('<BODY bgcolor="white">\n');
+ output.write('<!--#include virtual="/header.html" -->')
+
+ output.write(' <H1>' + title + '</H1>\n')
+ output.write('Auto-generated by pjsip-apps/build/get-footprint.py script\n')
+ output.write('<p>Date: ' + time.asctime() + '<BR>\n')
+ output.write('Revision: r' + revision + '</p>\n\n')
+ output.write('<HR>\n')
+ output.write('\n')
+
+ # Info
+ output.write('<H2>Build Configuration</H2>\n')
+
+ # build.mak
+ output.write('\n<H3>build.mak</H3>\n')
+ output.write('<tt>\n')
+ f = open('../../build.mak', 'r')
+ s = f.readlines()
+ for l in s:
+ output.write(l + '<BR>\n')
+ output.write('</tt>\n')
+ output.write('<p>Using ' + cc + ' version ' + cc_ver +'</p>\n')
+
+ # user.mak
+ output.write('\n<H3>user.mak</H3>\n')
+ output.write('<tt>\n')
+ f = open('../../user.mak', 'r')
+ s = f.readlines()
+ for l in s:
+ output.write(l + '<BR>\n')
+ output.write('</tt>\n')
+
+ # config_site.h
+ output.write('\n<H3>&lt;pj/config.site.h&gt;</H3>\n')
+ output.write('<tt>\n')
+ f = os.popen('cpp -dM -I../../pjlib/include ../../pjlib/include/pj/config_site.h | grep PJ')
+ s = f.readlines()
+ for l in s:
+ output.write(l + '<BR>\n')
+ output.write('</tt>\n')
+
+
+
+ # Write individual module size
+ output.write('<H2>Footprint Report</H2>\n')
+ output.write('<p>The table below shows the footprint of individual feature, in bytes.</p>')
+ output.write('<TABLE border="1" cellpadding="2" cellspacing="0">\n' +
+ '<TR bgcolor="#e8e8ff">\n' +
+ ' <TD align="center"><strong>.text</strong></TD>\n' +
+ ' <TD align="center"><strong>.data</strong></TD>\n' +
+ ' <TD align="center"><strong>.bss</strong></TD>\n' +
+ ' <TD align="center"><strong>Features/Module Description</strong></TD>\n' +
+ '</TR>\n')
+
+
+ for i in range(1, len(exe_size)):
+ e = exe_size[i]
+ prev = exe_size[i-1]
+
+ output.write('<TR>\n')
+ if e[1]<>'':
+ output.write( ' <TD align="right">' + `string.atoi(e[2]) - string.atoi(prev[2])` + '</TD>\n')
+ output.write( ' <TD align="right">' + `string.atoi(e[3]) - string.atoi(prev[3])` + '</TD>\n')
+ output.write( ' <TD align="right">' + `string.atoi(e[4]) - string.atoi(prev[4])` + '</TD>\n' )
+ output.write( ' <TD>' + e[5] + '</TD>\n')
+ else:
+ empty_size = exe_size[1]
+ output.write('<TR bgcolor="#e8e8ff">\n')
+ output.write( ' <TD align="right">&nbsp;</TD>\n')
+ output.write( ' <TD align="right">&nbsp;</TD>\n')
+ output.write( ' <TD align="right">&nbsp;</TD>\n')
+ output.write( ' <TD><strong>' + e[5] + ': .text=' + e[2]+ ', .data=' + e[3] + ', .bss=' + e[4] )
+ output.write( '\n </strong> <BR>(Size minus empty application size: ' + \
+ '.text=' + `string.atoi(e[2]) - string.atoi(empty_size[2])` + \
+ ', .data=' + `string.atoi(e[3]) - string.atoi(empty_size[3])` + \
+ ', .data=' + `string.atoi(e[4]) - string.atoi(empty_size[4])` + \
+ ')\n' )
+ output.write( ' </TD>\n')
+
+ output.write('</TR>\n')
+
+ output.write('</TABLE>\n')
+ output.write('<!--#include virtual="/footer.html" -->')
+ output.write('</BODY>\n')
+ output.write('</HTML>\n')
+
+ # Done
+ output.close()
+
+
+
+
+#
+# Get the size of individual feature
+#
+def get_size(all_flags, flags, desc):
+ file = 'footprint.exe'
+ # Remove file
+ rc = os.system("make -f Footprint.mak FCFLAGS='" + all_flags + "' clean")
+ # Make the executable
+ cmd = "make -f Footprint.mak FCFLAGS='" + all_flags + "' all"
+ #print cmd
+ rc = os.system(cmd)
+ if rc <> 0:
+ sys.exit(1)
+
+ # Run 'size' against the executable
+ f = os.popen('size ' + file)
+ # Skip header of the 'size' output
+ f.readline()
+ # Get the sizes
+ size = f.readline()
+ f.close()
+ # Split into tokens
+ tokens = size.split()
+ # Build the size tuple and add to exe_size
+ elem = all_flags, flags, tokens[0], tokens[1], tokens[2], desc
+ exe_size.append(elem)
+ # Remove file
+ rc = os.system("make -f Footprint.mak FCFLAGS='" + all_flags + "' clean")
+
+# Main
+elem = '', '', '0', '0', '0', ''
+exe_size.append(elem)
+
+all_flags = ''
+for elem in compile_flags:
+ if elem[0] <> '':
+ flags = '-D' + elem[0]
+ all_flags += flags + ' '
+ get_size(all_flags, elem[0], elem[1])
+ else:
+ e = exe_size[len(exe_size)-1]
+ n = all_flags, '', e[2], e[3], e[4], elem[1]
+ exe_size.append(n)
+
+
+#print_text_report('footprint.txt')
+print_html_report()
+
diff --git a/pjsip-apps/build/libpjproject.vcproj b/pjsip-apps/build/libpjproject.vcproj
new file mode 100644
index 0000000..8bf1552
--- /dev/null
+++ b/pjsip-apps/build/libpjproject.vcproj
@@ -0,0 +1,2772 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="libpjproject"
+ ProjectGUID="{23D7679C-764C-4E02-8B29-BB882CEEEFE2}"
+ RootNamespace="libpjproject"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="Windows Mobile 6 Standard SDK (ARMV4I)"
+ />
+ <Platform
+ Name="Windows Mobile 6 Professional SDK (ARMV4I)"
+ />
+ <Platform
+ Name="Pocket PC 2003 (ARMV4)"
+ />
+ <Platform
+ Name="Smartphone 2003 (ARMV4)"
+ />
+ <Platform
+ Name="Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ />
+ <Platform
+ Name="Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-win32-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ OutputFile="..\..\lib\$(ProjectName)-$(TargetCPU)-$(PlatformName)-vc$(VSVer)-$(ConfigurationName).lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Windows Mobile 6 Standard SDK (ARMV4I)"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm6-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ OutputFile="..\..\lib\$(ProjectName)-$(TargetCPU)-wm6std-vc$(VSVer)-$(ConfigurationName).lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Windows Mobile 6 Professional SDK (ARMV4I)"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm6-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ OutputFile="..\..\lib\$(ProjectName)-$(TargetCPU)-wm6pro-vc$(VSVer)-$(ConfigurationName).lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Pocket PC 2003 (ARMV4)"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm2003-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ OutputFile="..\..\lib\$(ProjectName)-$(TargetCPU)-wm2003ppc-vc$(VSVer)-$(ConfigurationName).lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Smartphone 2003 (ARMV4)"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm2003-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ OutputFile="..\..\lib\$(ProjectName)-$(TargetCPU)-wm2003sp-vc$(VSVer)-$(ConfigurationName).lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm5-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ OutputFile="..\..\lib\$(ProjectName)-$(TargetCPU)-wm5ppc-vc$(VSVer)-$(ConfigurationName).lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm5-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ OutputFile="..\..\lib\$(ProjectName)-$(TargetCPU)-wm5sp-vc$(VSVer)-$(ConfigurationName).lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-win32-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ OutputFile="..\..\lib\$(ProjectName)-$(TargetCPU)-$(PlatformName)-vc$(VSVer)-$(ConfigurationName).lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Windows Mobile 6 Standard SDK (ARMV4I)"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm6-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ OutputFile="..\..\lib\$(ProjectName)-$(TargetCPU)-wm6std-vc$(VSVer)-$(ConfigurationName).lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Windows Mobile 6 Professional SDK (ARMV4I)"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm6-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ OutputFile="..\..\lib\$(ProjectName)-$(TargetCPU)-wm6pro-vc$(VSVer)-$(ConfigurationName).lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Pocket PC 2003 (ARMV4)"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm2003-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ OutputFile="..\..\lib\$(ProjectName)-$(TargetCPU)-wm2003ppc-vc$(VSVer)-$(ConfigurationName).lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Smartphone 2003 (ARMV4)"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm2003-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ OutputFile="..\..\lib\$(ProjectName)-$(TargetCPU)-wm2003sp-vc$(VSVer)-$(ConfigurationName).lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm5-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ OutputFile="..\..\lib\$(ProjectName)-$(TargetCPU)-wm5ppc-vc$(VSVer)-$(ConfigurationName).lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm5-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ OutputFile="..\..\lib\$(ProjectName)-$(TargetCPU)-wm5sp-vc$(VSVer)-$(ConfigurationName).lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Static|Win32"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-win32-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ OutputFile="..\..\lib\$(ProjectName)-$(TargetCPU)-$(PlatformName)-vc$(VSVer)-$(ConfigurationName).lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Static|Windows Mobile 6 Standard SDK (ARMV4I)"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm6-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ OutputFile="..\..\lib\$(ProjectName)-$(TargetCPU)-wm6std-vc$(VSVer)-$(ConfigurationName).lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Static|Windows Mobile 6 Professional SDK (ARMV4I)"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm6-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ OutputFile="..\..\lib\$(ProjectName)-$(TargetCPU)-wm6pro-vc$(VSVer)-$(ConfigurationName).lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Static|Pocket PC 2003 (ARMV4)"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm2003-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ OutputFile="..\..\lib\$(ProjectName)-$(TargetCPU)-wm2003ppc-vc$(VSVer)-$(ConfigurationName).lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Static|Smartphone 2003 (ARMV4)"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm2003-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ OutputFile="..\..\lib\$(ProjectName)-$(TargetCPU)-wm2003sp-vc$(VSVer)-$(ConfigurationName).lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Static|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm5-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ OutputFile="..\..\lib\$(ProjectName)-$(TargetCPU)-wm5ppc-vc$(VSVer)-$(ConfigurationName).lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Static|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm5-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ OutputFile="..\..\lib\$(ProjectName)-$(TargetCPU)-wm5sp-vc$(VSVer)-$(ConfigurationName).lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Dynamic|Win32"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-win32-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ OutputFile="..\..\lib\$(ProjectName)-$(TargetCPU)-$(PlatformName)-vc$(VSVer)-$(ConfigurationName).lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Dynamic|Windows Mobile 6 Standard SDK (ARMV4I)"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm6-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ OutputFile="..\..\lib\$(ProjectName)-$(TargetCPU)-wm6std-vc$(VSVer)-$(ConfigurationName).lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Dynamic|Windows Mobile 6 Professional SDK (ARMV4I)"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm6-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ OutputFile="..\..\lib\$(ProjectName)-$(TargetCPU)-wm6pro-vc$(VSVer)-$(ConfigurationName).lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Dynamic|Pocket PC 2003 (ARMV4)"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm2003-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ OutputFile="..\..\lib\$(ProjectName)-$(TargetCPU)-wm2003ppc-vc$(VSVer)-$(ConfigurationName).lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Dynamic|Smartphone 2003 (ARMV4)"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm2003-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ OutputFile="..\..\lib\$(ProjectName)-$(TargetCPU)-wm2003sp-vc$(VSVer)-$(ConfigurationName).lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Dynamic|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm5-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ EnableFloatingPointEmulation="false"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ AdditionalOptions=""
+ OutputFile="..\..\lib\$(ProjectName)-$(TargetCPU)-wm5ppc-vc$(VSVer)-$(ConfigurationName).lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Dynamic|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm5-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ OutputFile="..\..\lib\$(ProjectName)-$(TargetCPU)-wm5sp-vc$(VSVer)-$(ConfigurationName).lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Dynamic|Win32"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-win32-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ OutputFile="..\..\lib\$(ProjectName)-$(TargetCPU)-$(PlatformName)-vc$(VSVer)-$(ConfigurationName).lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Dynamic|Windows Mobile 6 Standard SDK (ARMV4I)"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm6-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ OutputFile="..\..\lib\$(ProjectName)-$(TargetCPU)-wm6std-vc$(VSVer)-$(ConfigurationName).lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Dynamic|Windows Mobile 6 Professional SDK (ARMV4I)"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm6-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ OutputFile="..\..\lib\$(ProjectName)-$(TargetCPU)-wm6pro-vc$(VSVer)-$(ConfigurationName).lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Dynamic|Pocket PC 2003 (ARMV4)"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm2003-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ OutputFile="..\..\lib\$(ProjectName)-$(TargetCPU)-wm2003ppc-vc$(VSVer)-$(ConfigurationName).lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Dynamic|Smartphone 2003 (ARMV4)"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm2003-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ OutputFile="..\..\lib\$(ProjectName)-$(TargetCPU)-wm2003sp-vc$(VSVer)-$(ConfigurationName).lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Dynamic|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm5-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ OutputFile="..\..\lib\$(ProjectName)-$(TargetCPU)-wm5ppc-vc$(VSVer)-$(ConfigurationName).lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Dynamic|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm5-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ OutputFile="..\..\lib\$(ProjectName)-$(TargetCPU)-wm5sp-vc$(VSVer)-$(ConfigurationName).lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Static|Win32"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-win32-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ OutputFile="..\..\lib\$(ProjectName)-$(TargetCPU)-$(PlatformName)-vc$(VSVer)-$(ConfigurationName).lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Static|Windows Mobile 6 Standard SDK (ARMV4I)"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm6-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ OutputFile="..\..\lib\$(ProjectName)-$(TargetCPU)-wm6std-vc$(VSVer)-$(ConfigurationName).lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Static|Windows Mobile 6 Professional SDK (ARMV4I)"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm6-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ OutputFile="..\..\lib\$(ProjectName)-$(TargetCPU)-wm6pro-vc$(VSVer)-$(ConfigurationName).lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Static|Pocket PC 2003 (ARMV4)"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm2003-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ OutputFile="..\..\lib\$(ProjectName)-$(TargetCPU)-wm2003ppc-vc$(VSVer)-$(ConfigurationName).lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Static|Smartphone 2003 (ARMV4)"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm2003-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ OutputFile="..\..\lib\$(ProjectName)-$(TargetCPU)-wm2003sp-vc$(VSVer)-$(ConfigurationName).lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Static|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm5-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ OutputFile="..\..\lib\$(ProjectName)-$(TargetCPU)-wm5ppc-vc$(VSVer)-$(ConfigurationName).lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Static|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm5-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ OutputFile="..\..\lib\$(ProjectName)-$(TargetCPU)-wm5sp-vc$(VSVer)-$(ConfigurationName).lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath=".\dummy.c"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/pjsip-apps/build/os-win32.mak b/pjsip-apps/build/os-win32.mak
new file mode 100644
index 0000000..30f422e
--- /dev/null
+++ b/pjsip-apps/build/os-win32.mak
@@ -0,0 +1,2 @@
+
+export LDFLAGS += -lwinmm
diff --git a/pjsip-apps/build/output/.keep b/pjsip-apps/build/output/.keep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/pjsip-apps/build/output/.keep
diff --git a/pjsip-apps/build/pjsua.vcproj b/pjsip-apps/build/pjsua.vcproj
new file mode 100644
index 0000000..717d7dc
--- /dev/null
+++ b/pjsip-apps/build/pjsua.vcproj
@@ -0,0 +1,3636 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="pjsua"
+ ProjectGUID="{8310649E-A25E-4AF0-91E8-9E3CC659BB89}"
+ RootNamespace="pjsua"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="Pocket PC 2003 (ARMV4)"
+ />
+ <Platform
+ Name="Smartphone 2003 (ARMV4)"
+ />
+ <Platform
+ Name="Windows Mobile 6 Standard SDK (ARMV4I)"
+ />
+ <Platform
+ Name="Windows Mobile 6 Professional SDK (ARMV4I)"
+ />
+ <Platform
+ Name="Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ />
+ <Platform
+ Name="Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-win32-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PreprocessorDefinitions="_CONSOLE;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Pocket PC 2003 (ARMV4)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm2003-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ OutputFile="..\bin\$(ProjectName)-$(TargetCPU)-wm2003ppc-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Smartphone 2003 (ARMV4)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm2003-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ OutputFile="..\bin\$(ProjectName)-$(TargetCPU)-wm2003sp-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-win32-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PreprocessorDefinitions="_CONSOLE;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ IgnoreDefaultLibraryNames="msvcrt.lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Pocket PC 2003 (ARMV4)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm2003-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ OutputFile="..\bin\$(ProjectName)-$(TargetCPU)-wm2003ppc-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Smartphone 2003 (ARMV4)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm2003-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ OutputFile="..\bin\$(ProjectName)-$(TargetCPU)-wm2003sp-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Static|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-win32-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PreprocessorDefinitions="_CONSOLE;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Static|Pocket PC 2003 (ARMV4)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm2003-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ OutputFile="..\bin\$(ProjectName)-$(TargetCPU)-wm2003ppc-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Static|Smartphone 2003 (ARMV4)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm2003-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ OutputFile="..\bin\$(ProjectName)-$(TargetCPU)-wm2003sp-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Dynamic|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-win32-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PreprocessorDefinitions="_CONSOLE;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Dynamic|Pocket PC 2003 (ARMV4)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm2003-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ OutputFile="..\bin\$(ProjectName)-$(TargetCPU)-wm2003ppc-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Dynamic|Smartphone 2003 (ARMV4)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm2003-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ OutputFile="..\bin\$(ProjectName)-$(TargetCPU)-wm2003sp-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Dynamic|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-win32-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PreprocessorDefinitions="_CONSOLE;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Dynamic|Pocket PC 2003 (ARMV4)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm2003-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ OutputFile="..\bin\$(ProjectName)-$(TargetCPU)-wm2003ppc-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Dynamic|Smartphone 2003 (ARMV4)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm2003-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ OutputFile="..\bin\$(ProjectName)-$(TargetCPU)-wm2003sp-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Static|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-win32-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PreprocessorDefinitions="_CONSOLE;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Static|Pocket PC 2003 (ARMV4)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm2003-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ OutputFile="..\bin\$(ProjectName)-$(TargetCPU)-wm2003ppc-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Static|Smartphone 2003 (ARMV4)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm2003-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ OutputFile="..\bin\$(ProjectName)-$(TargetCPU)-wm2003sp-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Windows Mobile 6 Standard SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm6-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ OutputFile="..\bin\$(ProjectName)-$(TargetCPU)-wm6std-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Windows Mobile 6 Professional SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm6-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ OutputFile="..\bin\$(ProjectName)-$(TargetCPU)-wm6pro-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm5-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ OutputFile="..\bin\$(ProjectName)-$(TargetCPU)-wm5ppc-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm5-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ OutputFile="..\bin\$(ProjectName)-$(TargetCPU)-wm5sp-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Windows Mobile 6 Standard SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm6-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ OutputFile="..\bin\$(ProjectName)-$(TargetCPU)-wm6std-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Windows Mobile 6 Professional SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm6-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ OutputFile="..\bin\$(ProjectName)-$(TargetCPU)-wm6pro-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm5-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ OutputFile="..\bin\$(ProjectName)-$(TargetCPU)-wm5ppc-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm5-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ OutputFile="..\bin\$(ProjectName)-$(TargetCPU)-wm5sp-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Static|Windows Mobile 6 Standard SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm6-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ OutputFile="..\bin\$(ProjectName)-$(TargetCPU)-wm6std-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Static|Windows Mobile 6 Professional SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm6-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ OutputFile="..\bin\$(ProjectName)-$(TargetCPU)-wm6pro-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Static|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm5-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ OutputFile="..\bin\$(ProjectName)-$(TargetCPU)-wm5ppc-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Static|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm5-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ OutputFile="..\bin\$(ProjectName)-$(TargetCPU)-wm5sp-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Dynamic|Windows Mobile 6 Standard SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm6-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ OutputFile="..\bin\$(ProjectName)-$(TargetCPU)-wm6std-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Dynamic|Windows Mobile 6 Professional SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm6-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ OutputFile="..\bin\$(ProjectName)-$(TargetCPU)-wm6pro-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Dynamic|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm5-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ OutputFile="..\bin\$(ProjectName)-$(TargetCPU)-wm5ppc-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Dynamic|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm5-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ OutputFile="..\bin\$(ProjectName)-$(TargetCPU)-wm5sp-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Dynamic|Windows Mobile 6 Standard SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm6-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ OutputFile="..\bin\$(ProjectName)-$(TargetCPU)-wm6std-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Dynamic|Windows Mobile 6 Professional SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm6-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ OutputFile="..\bin\$(ProjectName)-$(TargetCPU)-wm6pro-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Dynamic|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm5-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ OutputFile="..\bin\$(ProjectName)-$(TargetCPU)-wm5ppc-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Dynamic|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm5-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ OutputFile="..\bin\$(ProjectName)-$(TargetCPU)-wm5sp-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Static|Windows Mobile 6 Standard SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm6-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ OutputFile="..\bin\$(ProjectName)-$(TargetCPU)-wm6std-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Static|Windows Mobile 6 Professional SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm6-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ OutputFile="..\bin\$(ProjectName)-$(TargetCPU)-wm6pro-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Static|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm5-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ OutputFile="..\bin\$(ProjectName)-$(TargetCPU)-wm5ppc-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Static|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm5-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ OutputFile="..\bin\$(ProjectName)-$(TargetCPU)-wm5sp-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath="..\src\pjsua\main.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\pjsua\pjsua_app.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/pjsip-apps/build/pjsystest.vcproj b/pjsip-apps/build/pjsystest.vcproj
new file mode 100644
index 0000000..5f72a58
--- /dev/null
+++ b/pjsip-apps/build/pjsystest.vcproj
@@ -0,0 +1,533 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="pjsystest"
+ ProjectGUID="{5E507EA2-CB39-47CA-BD39-49EB58D7A0BB}"
+ RootNamespace="pjsystest"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Windows Mobile 6 Standard SDK (ARMV4I)"
+ />
+ <Platform
+ Name="Windows Mobile 6 Professional SDK (ARMV4I)"
+ />
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Windows Mobile 6 Standard SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm6-common-defaults.vsprops"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjlib/include,../../pjlib-util/include,../../pjnath/include,../../pjmedia/include,../../pjsip/include"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ AdditionalIncludeDirectories=""
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalOptions=" /subsystem:windowsce,5.02"
+ AdditionalDependencies="aygshell.lib coredll.lib winsock.lib ws2.lib"
+ IgnoreDefaultLibraryNames="oldnames.lib"
+ DelayLoadDLLs=""
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles="input.8.wav|$(ProjectDir)\..\..\tests\pjsua\wavs\|%CSIDL_PROGRAM_FILES%\$(ProjectName)|0;tock8.wav|$(ProjectDir)\..\..\tests\pjsua\wavs\|%CSIDL_PROGRAM_FILES%\$(ProjectName)|0;"
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Windows Mobile 6 Professional SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm6-common-defaults.vsprops"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="1"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjlib/include,../../pjlib-util/include,../../pjnath/include,../../pjmedia/include,../../pjsip/include"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES)"
+ Culture="1033"
+ AdditionalIncludeDirectories="$(IntDir)"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalOptions=" /subsystem:windowsce,5.02"
+ AdditionalDependencies="aygshell.lib coredll.lib winsock.lib ws2.lib"
+ IgnoreDefaultLibraryNames="oldnames.lib"
+ DelayLoadDLLs="$(NOINHERIT)"
+ TargetMachine="0"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles="input.8.wav|$(ProjectDir)\..\..\tests\pjsua\wavs\|%CSIDL_PROGRAM_FILES%\$(ProjectName)|0;tock8.wav|$(ProjectDir)\..\..\tests\pjsua\wavs\|%CSIDL_PROGRAM_FILES%\$(ProjectName)|0;"
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-win32-common-defaults.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PreprocessorDefinitions="_CONSOLE;"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Windows Mobile 6 Standard SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-wm6-release-defaults.vsprops;..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjlib/include,../../pjlib-util/include,../../pjnath/include,../../pjmedia/include,../../pjsip/include"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ AdditionalIncludeDirectories=""
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalOptions=" /subsystem:windowsce,5.02"
+ AdditionalDependencies="aygshell.lib coredll.lib winsock.lib ws2.lib"
+ IgnoreDefaultLibraryNames="oldnames.lib"
+ DelayLoadDLLs=""
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles="msvcr80.dll|$(BINDIR)\$(INSTRUCTIONSET)\|%CSIDL_PROGRAM_FILES%\$(ProjectName)|0;input.8.wav|$(ProjectDir)\..\..\tests\pjsua\wavs\|%CSIDL_PROGRAM_FILES%\$(ProjectName)|0;tock8.wav|$(ProjectDir)\..\..\tests\pjsua\wavs\|%CSIDL_PROGRAM_FILES%\$(ProjectName)|0;"
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Windows Mobile 6 Professional SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm6-release-defaults.vsprops"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="1"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjlib/include,../../pjlib-util/include,../../pjnath/include,../../pjmedia/include,../../pjsip/include"
+ BufferSecurityCheck="false"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES)"
+ Culture="1033"
+ AdditionalIncludeDirectories="&quot;$(IntDir)&quot;"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalOptions=" /subsystem:windowsce,5.02"
+ AdditionalDependencies="aygshell.lib coredll.lib winsock.lib ws2.lib"
+ IgnoreDefaultLibraryNames="oldnames.lib"
+ DelayLoadDLLs=""
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles="msvcr80.dll|$(BINDIR)\$(INSTRUCTIONSET)\|%CSIDL_PROGRAM_FILES%\$(ProjectName)|0;input.8.wav|$(ProjectDir)\..\..\tests\pjsua\wavs\|%CSIDL_PROGRAM_FILES%\$(ProjectName)|0;tock8.wav|$(ProjectDir)\..\..\tests\pjsua\wavs\|%CSIDL_PROGRAM_FILES%\$(ProjectName)|0;"
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-win32-release-defaults.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PreprocessorDefinitions="_CONSOLE;"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath="..\src\pjsystest\main_console.c"
+ >
+ <FileConfiguration
+ Name="Debug|Windows Mobile 6 Standard SDK (ARMV4I)"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 6 Professional SDK (ARMV4I)"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 6 Standard SDK (ARMV4I)"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 6 Professional SDK (ARMV4I)"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\pjsystest\main_wm.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\pjsystest\systest.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath="..\src\pjsystest\gui.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pjsystest\systest.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File
+ RelativePath="..\src\pjsystest\pjsystest_wince.rc"
+ >
+ <FileConfiguration
+ Name="Release|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/pjsip-apps/build/py_pjsua.vcproj b/pjsip-apps/build/py_pjsua.vcproj
new file mode 100644
index 0000000..93998d0
--- /dev/null
+++ b/pjsip-apps/build/py_pjsua.vcproj
@@ -0,0 +1,244 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="py_pjsua"
+ ProjectGUID="{C44FC030-D46A-47FF-B731-B47ECA5B2B10}"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-win32-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ AdditionalIncludeDirectories="..\..\pjlib\include,..\..\pjlib-util\include,..\..\pjmedia\include,..\..\pjsip\include,../../pjnath/include"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="python24.lib ole32.lib shell32.lib user32.lib odbc32.lib odbccp32.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib iphlpapi.lib"
+ OutputFile="..\bin\py-pjsua-$(TargetCPU)-$(PlatformName)-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-win32-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="_LIB;"
+ PrecompiledHeaderFile=""
+ AdditionalIncludeDirectories="..\..\pjlib\include,..\..\pjlib-util\include,..\..\pjmedia\include,..\..\pjsip\include,../../pjnath/include"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="python24_d.lib ole32.lib shell32.lib user32.lib odbc32.lib odbccp32.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib iphlpapi.lib"
+ OutputFile="..\bin\py-pjsua-$(TargetCPU)-$(PlatformName)-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath="..\src\py_pjsua\pjsua.py"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\py_pjsua\pjsua_app.py"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\py_pjsua\py_pjsua.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\py_pjsua\py_pjsua.def"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath="..\src\py_pjsua\py_pjsua.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/pjsip-apps/build/python_pjsua.vcproj b/pjsip-apps/build/python_pjsua.vcproj
new file mode 100644
index 0000000..66e322a
--- /dev/null
+++ b/pjsip-apps/build/python_pjsua.vcproj
@@ -0,0 +1,268 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="python_pjsua"
+ ProjectGUID="{0C91838B-3372-40B4-A764-DE075A4BC94B}"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\output\python_pjsua-i386-win32-vc8-debug"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="_DEBUG"
+ MkTypLibCompatible="true"
+ SuppressStartupBanner="true"
+ TargetEnvironment="1"
+ TypeLibraryName=".\output\python_pjsua-i386-win32-vc6-debug/python_pjsua.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\pjlib\include,..\..\pjlib-util\include,..\..\pjmedia\include,..\..\pjsip\include,../../pjnath/include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;PY_PJSUA_EXPORTS"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile="$(OutDir)/python_pjsua.pch"
+ AssemblerListingLocation="$(OutDir)/"
+ ObjectFile="$(OutDir)/"
+ ProgramDataBaseFileName="$(OutDir)/"
+ BrowseInformation="1"
+ WarningLevel="4"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1057"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="python24_d.lib odbc32.lib odbccp32.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib iphlpapi.lib"
+ OutputFile="..\lib\_pjsua_d.pyd"
+ LinkIncremental="2"
+ SuppressStartupBanner="true"
+ AdditionalLibraryDirectories="../../pjlib/lib,../../pjlib-util/lib,../../pjmedia/lib,../../pjsip/lib,F:\incoming\projects\divusi\Python-2.4\Python-2.4\PCbuild,F:\incoming\projects\divusi\Python-2.4\Python-2.4\PC\VC6"
+ ModuleDefinitionFile="..\src\python\_pjsua.def"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(OutDir)/_pjsua_d.pdb"
+ ImportLibrary="$(OutDir)/_pjsua_d.lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ SuppressStartupBanner="true"
+ OutputFile=".\output\python_pjsua-i386-win32-vc6-debug/python_pjsua.bsc"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\output\python_pjsua-i386-win32-vc8-release"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ MkTypLibCompatible="true"
+ SuppressStartupBanner="true"
+ TargetEnvironment="1"
+ TypeLibraryName=".\output\python_pjsua-i386-win32-vc6-release/python_pjsua.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="..\..\pjlib\include,..\..\pjlib-util\include,..\..\pjmedia\include,..\..\pjsip\include,../../pjnath/include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;PY_PJSUA_EXPORTS"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ PrecompiledHeaderFile="$(OutDir)/python_pjsua.pch"
+ AssemblerListingLocation="$(OutDir)/"
+ ObjectFile="$(OutDir)/"
+ ProgramDataBaseFileName="$(OutDir)/"
+ BrowseInformation="1"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1057"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="python24.lib odbc32.lib odbccp32.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib iphlpapi.lib"
+ OutputFile="..\lib\_pjsua.pyd"
+ LinkIncremental="1"
+ SuppressStartupBanner="true"
+ AdditionalLibraryDirectories="../../pjlib/lib,../../pjlib-util/lib,../../pjmedia/lib,../../pjsip/lib"
+ IgnoreDefaultLibraryNames="libcmt.lib"
+ ModuleDefinitionFile="..\src\python\_pjsua.def"
+ ProgramDatabaseFile="$(OutDir)/_pjsua.pdb"
+ GenerateMapFile="true"
+ MapFileName="$(OutDir)/_pjsua.map"
+ ImportLibrary="$(OutDir)/_pjsua.lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ SuppressStartupBanner="true"
+ OutputFile=".\output\python_pjsua-i386-win32-vc6-release/python_pjsua.bsc"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath="..\src\python\_pjsua.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\python\_pjsua.def"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath="..\src\python\_pjsua.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/pjsip-apps/build/sample_debug.vcproj b/pjsip-apps/build/sample_debug.vcproj
new file mode 100644
index 0000000..f9e7726
--- /dev/null
+++ b/pjsip-apps/build/sample_debug.vcproj
@@ -0,0 +1,3265 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="sample_debug"
+ ProjectGUID="{A0F1AA62-0F6F-420D-B09A-AC04B6862821}"
+ RootNamespace="sample_debug"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="Windows Mobile 6 Standard SDK (ARMV4I)"
+ />
+ <Platform
+ Name="Windows Mobile 6 Professional SDK (ARMV4I)"
+ />
+ <Platform
+ Name="Pocket PC 2003 (ARMV4)"
+ />
+ <Platform
+ Name="Smartphone 2003 (ARMV4)"
+ />
+ <Platform
+ Name="Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ />
+ <Platform
+ Name="Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-win32-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PreprocessorDefinitions="_CONSOLE;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib oleaut32.lib uuid.lib ole32.lib user32.lib"
+ OutputFile="..\bin\sample-debug-$(TargetCPU)-$(PlatformName)-vc$(VSVer)-$(ConfigurationName).exe"
+ IgnoreDefaultLibraryNames="MSVCRT.LIB"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Windows Mobile 6 Standard SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm6-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib oleaut32.lib uuid.lib ole32.lib user32.lib"
+ OutputFile="..\bin\sample-debug-$(TargetCPU)-wm6std-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Windows Mobile 6 Professional SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm6-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib oleaut32.lib uuid.lib ole32.lib user32.lib"
+ OutputFile="..\bin\sample-debug-$(TargetCPU)-wm6pro-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Pocket PC 2003 (ARMV4)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm2003-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib oleaut32.lib uuid.lib ole32.lib user32.lib"
+ OutputFile="..\bin\sample-debug-$(TargetCPU)-wm2003ppc-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Smartphone 2003 (ARMV4)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm2003-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib oleaut32.lib uuid.lib ole32.lib user32.lib"
+ OutputFile="..\bin\sample-debug-$(TargetCPU)-wm2003sp-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm5-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib oleaut32.lib uuid.lib ole32.lib user32.lib"
+ OutputFile="..\bin\sample-debug-$(TargetCPU)-wm5ppc-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm5-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib oleaut32.lib uuid.lib ole32.lib user32.lib"
+ OutputFile="..\bin\sample-debug-$(TargetCPU)-wm5sp-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-win32-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PreprocessorDefinitions="_CONSOLE;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib oleaut32.lib uuid.lib ole32.lib user32.lib"
+ OutputFile="..\bin\sample-debug-$(TargetCPU)-$(PlatformName)-vc$(VSVer)-$(ConfigurationName).exe"
+ IgnoreDefaultLibraryNames=""
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Windows Mobile 6 Standard SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm6-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib oleaut32.lib uuid.lib ole32.lib user32.lib"
+ OutputFile="..\bin\sample-debug-$(TargetCPU)-wm6std-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Windows Mobile 6 Professional SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm6-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib oleaut32.lib uuid.lib ole32.lib user32.lib"
+ OutputFile="..\bin\sample-debug-$(TargetCPU)-wm6pro-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Pocket PC 2003 (ARMV4)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm2003-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib oleaut32.lib uuid.lib ole32.lib user32.lib"
+ OutputFile="..\bin\sample-debug-$(TargetCPU)-wm2003ppc-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Smartphone 2003 (ARMV4)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm2003-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib oleaut32.lib uuid.lib ole32.lib user32.lib"
+ OutputFile="..\bin\sample-debug-$(TargetCPU)-wm2003sp-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm5-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib oleaut32.lib uuid.lib ole32.lib user32.lib"
+ OutputFile="..\bin\sample-debug-$(TargetCPU)-wm5ppc-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm5-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib oleaut32.lib uuid.lib ole32.lib user32.lib"
+ OutputFile="..\bin\sample-debug-$(TargetCPU)-wm5sp-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Static|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-win32-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PreprocessorDefinitions="_CONSOLE;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib oleaut32.lib uuid.lib ole32.lib user32.lib"
+ OutputFile="..\bin\sample-debug-$(TargetCPU)-$(PlatformName)-vc$(VSVer)-$(ConfigurationName).exe"
+ IgnoreDefaultLibraryNames="MSVCRT.LIB"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Static|Windows Mobile 6 Standard SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm6-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib oleaut32.lib uuid.lib ole32.lib user32.lib"
+ OutputFile="..\bin\sample-debug-$(TargetCPU)-wm6std-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Static|Windows Mobile 6 Professional SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm6-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib oleaut32.lib uuid.lib ole32.lib user32.lib"
+ OutputFile="..\bin\sample-debug-$(TargetCPU)-wm6pro-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Static|Pocket PC 2003 (ARMV4)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm2003-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib oleaut32.lib uuid.lib ole32.lib user32.lib"
+ OutputFile="..\bin\sample-debug-$(TargetCPU)-wm2003ppc-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Static|Smartphone 2003 (ARMV4)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm2003-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib oleaut32.lib uuid.lib ole32.lib user32.lib"
+ OutputFile="..\bin\sample-debug-$(TargetCPU)-wm2003sp-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Static|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm5-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib oleaut32.lib uuid.lib ole32.lib user32.lib"
+ OutputFile="..\bin\sample-debug-$(TargetCPU)-wm5ppc-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Static|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm5-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib oleaut32.lib uuid.lib ole32.lib user32.lib"
+ OutputFile="..\bin\sample-debug-$(TargetCPU)-wm5sp-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Dynamic|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-win32-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PreprocessorDefinitions="_CONSOLE;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib oleaut32.lib uuid.lib ole32.lib user32.lib"
+ OutputFile="..\bin\sample-debug-$(TargetCPU)-$(PlatformName)-vc$(VSVer)-$(ConfigurationName).exe"
+ IgnoreDefaultLibraryNames=""
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Dynamic|Windows Mobile 6 Standard SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm6-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib oleaut32.lib uuid.lib ole32.lib user32.lib"
+ OutputFile="..\bin\sample-debug-$(TargetCPU)-wm6std-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Dynamic|Windows Mobile 6 Professional SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm6-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib oleaut32.lib uuid.lib ole32.lib user32.lib"
+ OutputFile="..\bin\sample-debug-$(TargetCPU)-wm6pro-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Dynamic|Pocket PC 2003 (ARMV4)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm2003-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib oleaut32.lib uuid.lib ole32.lib user32.lib"
+ OutputFile="..\bin\sample-debug-$(TargetCPU)-wm2003ppc-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Dynamic|Smartphone 2003 (ARMV4)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm2003-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib oleaut32.lib uuid.lib ole32.lib user32.lib"
+ OutputFile="..\bin\sample-debug-$(TargetCPU)-wm2003sp-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Dynamic|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm5-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib oleaut32.lib uuid.lib ole32.lib user32.lib"
+ OutputFile="..\bin\sample-debug-$(TargetCPU)-wm5ppc-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Dynamic|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm5-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib oleaut32.lib uuid.lib ole32.lib user32.lib"
+ OutputFile="..\bin\sample-debug-$(TargetCPU)-wm5sp-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Dynamic|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-win32-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PreprocessorDefinitions="_CONSOLE;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib oleaut32.lib uuid.lib ole32.lib user32.lib"
+ OutputFile="..\bin\sample-debug-$(TargetCPU)-$(PlatformName)-vc$(VSVer)-$(ConfigurationName).exe"
+ IgnoreDefaultLibraryNames="MSVCRT.LIB"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Dynamic|Windows Mobile 6 Standard SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm6-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib oleaut32.lib uuid.lib ole32.lib user32.lib"
+ OutputFile="..\bin\sample-debug-$(TargetCPU)-wm6std-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Dynamic|Windows Mobile 6 Professional SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm6-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib oleaut32.lib uuid.lib ole32.lib user32.lib"
+ OutputFile="..\bin\sample-debug-$(TargetCPU)-wm6pro-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Dynamic|Pocket PC 2003 (ARMV4)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm2003-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib oleaut32.lib uuid.lib ole32.lib user32.lib"
+ OutputFile="..\bin\sample-debug-$(TargetCPU)-wm2003ppc-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Dynamic|Smartphone 2003 (ARMV4)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm2003-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib oleaut32.lib uuid.lib ole32.lib user32.lib"
+ OutputFile="..\bin\sample-debug-$(TargetCPU)-wm2003sp-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Dynamic|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm5-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib oleaut32.lib uuid.lib ole32.lib user32.lib"
+ OutputFile="..\bin\sample-debug-$(TargetCPU)-wm5ppc-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Dynamic|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-dynamic-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm5-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib oleaut32.lib uuid.lib ole32.lib user32.lib"
+ OutputFile="..\bin\sample-debug-$(TargetCPU)-wm5sp-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Static|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-win32-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PreprocessorDefinitions="_CONSOLE;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib oleaut32.lib uuid.lib ole32.lib user32.lib"
+ OutputFile="..\bin\sample-debug-$(TargetCPU)-$(PlatformName)-vc$(VSVer)-$(ConfigurationName).exe"
+ IgnoreDefaultLibraryNames="MSVCRT.LIB"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Static|Windows Mobile 6 Standard SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm6-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib oleaut32.lib uuid.lib ole32.lib user32.lib"
+ OutputFile="..\bin\sample-debug-$(TargetCPU)-wm6std-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Static|Windows Mobile 6 Professional SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm6-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib oleaut32.lib uuid.lib ole32.lib user32.lib"
+ OutputFile="..\bin\sample-debug-$(TargetCPU)-wm6pro-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Static|Pocket PC 2003 (ARMV4)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm2003-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib oleaut32.lib uuid.lib ole32.lib user32.lib"
+ OutputFile="..\bin\sample-debug-$(TargetCPU)-wm2003ppc-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Static|Smartphone 2003 (ARMV4)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm2003-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib oleaut32.lib uuid.lib ole32.lib user32.lib"
+ OutputFile="..\bin\sample-debug-$(TargetCPU)-wm2003sp-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Static|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm5-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib oleaut32.lib uuid.lib ole32.lib user32.lib"
+ OutputFile="..\bin\sample-debug-$(TargetCPU)-wm5ppc-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Static|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-release-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-wm5-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib oleaut32.lib uuid.lib ole32.lib user32.lib"
+ OutputFile="..\bin\sample-debug-$(TargetCPU)-wm5sp-vc$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath="..\src\samples\debug.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/pjsip-apps/build/samples.vcproj b/pjsip-apps/build/samples.vcproj
new file mode 100644
index 0000000..fb0c6d5
--- /dev/null
+++ b/pjsip-apps/build/samples.vcproj
@@ -0,0 +1,1754 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="samples"
+ ProjectGUID="{E378A1FC-0C9C-4462-860F-7E60BC1BF84E}"
+ RootNamespace="samples"
+ Keyword="MakeFileProj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="Pocket PC 2003 (ARMV4)"
+ />
+ <Platform
+ Name="Smartphone 2003 (ARMV4)"
+ />
+ <Platform
+ Name="Windows Mobile 6 Standard SDK (ARMV4I)"
+ />
+ <Platform
+ Name="Windows Mobile 6 Professional SDK (ARMV4I)"
+ />
+ <Platform
+ Name="Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ />
+ <Platform
+ Name="Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\output\$(ProjectName)-i386-$(PlatformName)-vs8-$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="0"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ BuildLogFile=""
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release VC_VER=8"
+ ReBuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release VC_VER=8 /a"
+ CleanCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release VC_VER=8 clean"
+ Output="All samples"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Pocket PC 2003 (ARMV4)"
+ OutputDirectory=".\output\$(ProjectName)-wm2003ppc-$(PlatformName)-vs8-$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="0"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ BuildLogFile=""
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release VC_VER=8"
+ ReBuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release VC_VER=8 /a"
+ CleanCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release VC_VER=8 clean"
+ Output="All samples"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Smartphone 2003 (ARMV4)"
+ OutputDirectory=".\output\$(ProjectName)-wm2003sp-$(PlatformName)-vs8-$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="0"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ BuildLogFile=""
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release VC_VER=8"
+ ReBuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release VC_VER=8 /a"
+ CleanCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release VC_VER=8 clean"
+ Output="All samples"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Windows Mobile 6 Standard SDK (ARMV4I)"
+ OutputDirectory=".\output\$(ProjectName)-wm6std-$(PlatformName)-vs8-$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="0"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ BuildLogFile=""
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release VC_VER=8"
+ ReBuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release VC_VER=8 /a"
+ CleanCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release VC_VER=8 clean"
+ Output="All samples"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Windows Mobile 6 Professional SDK (ARMV4I)"
+ OutputDirectory=".\output\$(ProjectName)-wm6pro-$(PlatformName)-vs8-$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="0"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ BuildLogFile=""
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release VC_VER=8"
+ ReBuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release VC_VER=8 /a"
+ CleanCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release VC_VER=8 clean"
+ Output="All samples"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ OutputDirectory=".\output\$(ProjectName)-wm5ppc-$(PlatformName)-vs8-$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="0"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ BuildLogFile=""
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release VC_VER=8"
+ ReBuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release VC_VER=8 /a"
+ CleanCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release VC_VER=8 clean"
+ Output="All samples"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ OutputDirectory=".\output\$(ProjectName)-wm5sp-$(PlatformName)-vs8-$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="0"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ BuildLogFile=""
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release VC_VER=8"
+ ReBuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release VC_VER=8 /a"
+ CleanCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release VC_VER=8 clean"
+ Output="All samples"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\output\$(ProjectName)-i386-$(PlatformName)-vs8-$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="0"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ BuildLogFile=""
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug VC_VER=8"
+ ReBuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug VC_VER=8 /a"
+ CleanCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug VC_VER=8 clean"
+ Output="All samples"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Pocket PC 2003 (ARMV4)"
+ OutputDirectory=".\output\$(ProjectName)-wm2003ppc-$(PlatformName)-vs8-$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="0"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ BuildLogFile=""
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug VC_VER=8"
+ ReBuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug VC_VER=8 /a"
+ CleanCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug VC_VER=8 clean"
+ Output="All samples"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Smartphone 2003 (ARMV4)"
+ OutputDirectory=".\output\$(ProjectName)-wm2003sp-$(PlatformName)-vs8-$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="0"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ BuildLogFile=""
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug VC_VER=8"
+ ReBuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug VC_VER=8 /a"
+ CleanCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug VC_VER=8 clean"
+ Output="All samples"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Windows Mobile 6 Standard SDK (ARMV4I)"
+ OutputDirectory=".\output\$(ProjectName)-wm6std-$(PlatformName)-vs8-$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="0"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ BuildLogFile=""
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug VC_VER=8"
+ ReBuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug VC_VER=8 /a"
+ CleanCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug VC_VER=8 clean"
+ Output="All samples"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Windows Mobile 6 Professional SDK (ARMV4I)"
+ OutputDirectory=".\output\$(ProjectName)-wm6pro-$(PlatformName)-vs8-$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="0"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ BuildLogFile=""
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug VC_VER=8"
+ ReBuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug VC_VER=8 /a"
+ CleanCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug VC_VER=8 clean"
+ Output="All samples"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ OutputDirectory=".\output\$(ProjectName)-wm5ppc-$(PlatformName)-vs8-$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="0"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ BuildLogFile=""
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug VC_VER=8"
+ ReBuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug VC_VER=8 /a"
+ CleanCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug VC_VER=8 clean"
+ Output="All samples"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ OutputDirectory=".\output\$(ProjectName)-wm5sp-$(PlatformName)-vs8-$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="0"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ BuildLogFile=""
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug VC_VER=8"
+ ReBuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug VC_VER=8 /a"
+ CleanCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug VC_VER=8 clean"
+ Output="All samples"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Static|Win32"
+ OutputDirectory=".\output\$(ProjectName)-i386-$(PlatformName)-vs8-$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="0"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ BuildLogFile=""
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug-static VC_VER=8"
+ ReBuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug-static VC_VER=8 /a"
+ CleanCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug-static VC_VER=8 clean"
+ Output="All samples"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Static|Pocket PC 2003 (ARMV4)"
+ OutputDirectory=".\output\$(ProjectName)-wm2003ppc-$(PlatformName)-vs8-$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="0"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ BuildLogFile=""
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug-static VC_VER=8"
+ ReBuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug-static VC_VER=8 /a"
+ CleanCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug-static VC_VER=8 clean"
+ Output="All samples"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Static|Smartphone 2003 (ARMV4)"
+ OutputDirectory=".\output\$(ProjectName)-wm2003sp-$(PlatformName)-vs8-$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="0"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ BuildLogFile=""
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug-static VC_VER=8"
+ ReBuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug-static VC_VER=8 /a"
+ CleanCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug-static VC_VER=8 clean"
+ Output="All samples"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Static|Windows Mobile 6 Standard SDK (ARMV4I)"
+ OutputDirectory=".\output\$(ProjectName)-wm6std-$(PlatformName)-vs8-$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="0"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ BuildLogFile=""
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug-static VC_VER=8"
+ ReBuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug-static VC_VER=8 /a"
+ CleanCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug-static VC_VER=8 clean"
+ Output="All samples"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Static|Windows Mobile 6 Professional SDK (ARMV4I)"
+ OutputDirectory=".\output\$(ProjectName)-wm6pro-$(PlatformName)-vs8-$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="0"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ BuildLogFile=""
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug-static VC_VER=8"
+ ReBuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug-static VC_VER=8 /a"
+ CleanCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug-static VC_VER=8 clean"
+ Output="All samples"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Static|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ OutputDirectory=".\output\$(ProjectName)-wm5ppc-$(PlatformName)-vs8-$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="0"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ BuildLogFile=""
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug-static VC_VER=8"
+ ReBuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug-static VC_VER=8 /a"
+ CleanCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug-static VC_VER=8 clean"
+ Output="All samples"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Static|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ OutputDirectory=".\output\$(ProjectName)-wm5sp-$(PlatformName)-vs8-$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="0"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ BuildLogFile=""
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug-static VC_VER=8"
+ ReBuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug-static VC_VER=8 /a"
+ CleanCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug-static VC_VER=8 clean"
+ Output="All samples"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Dynamic|Win32"
+ OutputDirectory=".\output\$(ProjectName)-i386-$(PlatformName)-vs8-$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="0"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ BuildLogFile=""
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release-dynamic VC_VER=8"
+ ReBuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release-dynamic VC_VER=8 /a"
+ CleanCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release-dynamic VC_VER=8 clean"
+ Output="All samples"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Dynamic|Pocket PC 2003 (ARMV4)"
+ OutputDirectory=".\output\$(ProjectName)-wm2003ppc-$(PlatformName)-vs8-$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="0"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ BuildLogFile=""
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release-dynamic VC_VER=8"
+ ReBuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release-dynamic VC_VER=8 /a"
+ CleanCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release-dynamic VC_VER=8 clean"
+ Output="All samples"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Dynamic|Smartphone 2003 (ARMV4)"
+ OutputDirectory=".\output\$(ProjectName)-wm2003sp-$(PlatformName)-vs8-$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="0"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ BuildLogFile=""
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release-dynamic VC_VER=8"
+ ReBuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release-dynamic VC_VER=8 /a"
+ CleanCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release-dynamic VC_VER=8 clean"
+ Output="All samples"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Dynamic|Windows Mobile 6 Standard SDK (ARMV4I)"
+ OutputDirectory=".\output\$(ProjectName)-wm6std-$(PlatformName)-vs8-$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="0"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ BuildLogFile=""
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release-dynamic VC_VER=8"
+ ReBuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release-dynamic VC_VER=8 /a"
+ CleanCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release-dynamic VC_VER=8 clean"
+ Output="All samples"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Dynamic|Windows Mobile 6 Professional SDK (ARMV4I)"
+ OutputDirectory=".\output\$(ProjectName)-wm6pro-$(PlatformName)-vs8-$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="0"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ BuildLogFile=""
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release-dynamic VC_VER=8"
+ ReBuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release-dynamic VC_VER=8 /a"
+ CleanCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release-dynamic VC_VER=8 clean"
+ Output="All samples"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Dynamic|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ OutputDirectory=".\output\$(ProjectName)-wm5ppc-$(PlatformName)-vs8-$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="0"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ BuildLogFile=""
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release-dynamic VC_VER=8"
+ ReBuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release-dynamic VC_VER=8 /a"
+ CleanCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release-dynamic VC_VER=8 clean"
+ Output="All samples"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Dynamic|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ OutputDirectory=".\output\$(ProjectName)-wm5sp-$(PlatformName)-vs8-$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="0"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ BuildLogFile=""
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release-dynamic VC_VER=8"
+ ReBuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release-dynamic VC_VER=8 /a"
+ CleanCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release-dynamic VC_VER=8 clean"
+ Output="All samples"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Dynamic|Win32"
+ OutputDirectory=".\output\$(ProjectName)-i386-$(PlatformName)-vs8-$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="0"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ BuildLogFile=""
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug-dynamic VC_VER=8"
+ ReBuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug-dynamic VC_VER=8 /a"
+ CleanCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug-dynamic VC_VER=8 clean"
+ Output="All samples"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Dynamic|Pocket PC 2003 (ARMV4)"
+ OutputDirectory=".\output\$(ProjectName)-wm2003ppc-$(PlatformName)-vs8-$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="0"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ BuildLogFile=""
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug-dynamic VC_VER=8"
+ ReBuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug-dynamic VC_VER=8 /a"
+ CleanCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug-dynamic VC_VER=8 clean"
+ Output="All samples"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Dynamic|Smartphone 2003 (ARMV4)"
+ OutputDirectory=".\output\$(ProjectName)-wm2003sp-$(PlatformName)-vs8-$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="0"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ BuildLogFile=""
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug-dynamic VC_VER=8"
+ ReBuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug-dynamic VC_VER=8 /a"
+ CleanCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug-dynamic VC_VER=8 clean"
+ Output="All samples"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Dynamic|Windows Mobile 6 Standard SDK (ARMV4I)"
+ OutputDirectory=".\output\$(ProjectName)-wm6std-$(PlatformName)-vs8-$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="0"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ BuildLogFile=""
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug-dynamic VC_VER=8"
+ ReBuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug-dynamic VC_VER=8 /a"
+ CleanCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug-dynamic VC_VER=8 clean"
+ Output="All samples"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Dynamic|Windows Mobile 6 Professional SDK (ARMV4I)"
+ OutputDirectory=".\output\$(ProjectName)-wm6pro-$(PlatformName)-vs8-$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="0"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ BuildLogFile=""
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug-dynamic VC_VER=8"
+ ReBuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug-dynamic VC_VER=8 /a"
+ CleanCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug-dynamic VC_VER=8 clean"
+ Output="All samples"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Dynamic|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ OutputDirectory=".\output\$(ProjectName)-wm5ppc-$(PlatformName)-vs8-$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="0"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ BuildLogFile=""
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug-dynamic VC_VER=8"
+ ReBuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug-dynamic VC_VER=8 /a"
+ CleanCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug-dynamic VC_VER=8 clean"
+ Output="All samples"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Dynamic|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ OutputDirectory=".\output\$(ProjectName)-wm5sp-$(PlatformName)-vs8-$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="0"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ BuildLogFile=""
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug-dynamic VC_VER=8"
+ ReBuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug-dynamic VC_VER=8 /a"
+ CleanCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug-dynamic VC_VER=8 clean"
+ Output="All samples"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Static|Win32"
+ OutputDirectory=".\output\$(ProjectName)-i386-$(PlatformName)-vs8-$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="0"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ BuildLogFile=""
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release-static VC_VER=8"
+ ReBuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release-static VC_VER=8 /a"
+ CleanCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release-static VC_VER=8 clean"
+ Output="All samples"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Static|Pocket PC 2003 (ARMV4)"
+ OutputDirectory=".\output\$(ProjectName)-wm2003ppc-$(PlatformName)-vs8-$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="0"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ BuildLogFile=""
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release-static VC_VER=8"
+ ReBuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release-static VC_VER=8 /a"
+ CleanCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release-static VC_VER=8 clean"
+ Output="All samples"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Static|Smartphone 2003 (ARMV4)"
+ OutputDirectory=".\output\$(ProjectName)-wm2003sp-$(PlatformName)-vs8-$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="0"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ BuildLogFile=""
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release-static VC_VER=8"
+ ReBuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release-static VC_VER=8 /a"
+ CleanCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release-static VC_VER=8 clean"
+ Output="All samples"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Static|Windows Mobile 6 Standard SDK (ARMV4I)"
+ OutputDirectory=".\output\$(ProjectName)-wm6std-$(PlatformName)-vs8-$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="0"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ BuildLogFile=""
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release-static VC_VER=8"
+ ReBuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release-static VC_VER=8 /a"
+ CleanCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release-static VC_VER=8 clean"
+ Output="All samples"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Static|Windows Mobile 6 Professional SDK (ARMV4I)"
+ OutputDirectory=".\output\$(ProjectName)-wm6pro-$(PlatformName)-vs8-$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="0"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ BuildLogFile=""
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release-static VC_VER=8"
+ ReBuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release-static VC_VER=8 /a"
+ CleanCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release-static VC_VER=8 clean"
+ Output="All samples"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Static|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ OutputDirectory=".\output\$(ProjectName)-wm5ppc-$(PlatformName)-vs8-$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="0"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ BuildLogFile=""
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release-static VC_VER=8"
+ ReBuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release-static VC_VER=8 /a"
+ CleanCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release-static VC_VER=8 clean"
+ Output="All samples"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Static|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ OutputDirectory=".\output\$(ProjectName)-wm5sp-$(PlatformName)-vs8-$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="0"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ BuildLogFile=""
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release-static VC_VER=8"
+ ReBuildCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release-static VC_VER=8 /a"
+ CleanCommandLine="nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release-static VC_VER=8 clean"
+ Output="All samples"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath="..\src\samples\aectest.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\samples\auddemo.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\samples\aviplay.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\samples\confbench.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\samples\confsample.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\samples\encdec.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\samples\footprint.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\samples\httpdemo.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\samples\icedemo.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\samples\jbsim.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\samples\latency.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\samples\level.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\samples\mix.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\samples\pcaputil.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\samples\pjsip-perf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\samples\playfile.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\samples\playsine.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\samples\recfile.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\samples\resampleplay.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\samples\simple_pjsua.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\samples\simpleua.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\samples\sipecho.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\samples\siprtp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\samples\siprtp_report.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\samples\sipstateless.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\samples\sndinfo.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\samples\sndtest.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\samples\stateful_proxy.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\samples\stateless_proxy.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\samples\streamutil.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\samples\strerror.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\samples\tonegen.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\samples\vid_streamutil.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath="..\src\samples\proxy.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\samples\util.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+ >
+ </Filter>
+ <File
+ RelativePath="Samples-vc.mak"
+ >
+ </File>
+ <File
+ RelativePath="Samples.mak"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/pjsip-apps/build/vidgui.vcproj b/pjsip-apps/build/vidgui.vcproj
new file mode 100644
index 0000000..31cf7db
--- /dev/null
+++ b/pjsip-apps/build/vidgui.vcproj
@@ -0,0 +1,207 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="vidgui"
+ ProjectGUID="{A8EFA6F7-5443-46FA-9D35-2AF2668232EA}"
+ RootNamespace="vidgui"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\build\vs\pjproject-vs8-win32-common-defaults.vsprops"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../pjsip/include,../../pjlib/include,../../pjlib-util/include,../../pjmedia/include,../../pjnath/include"
+ PreprocessorDefinitions="_CONSOLE;"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="QtGui4.lib QtCore4.lib Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib"
+ GenerateDebugInformation="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath="..\src\vidgui\moc_vidgui.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\src\vidgui\moc_vidwin.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\src\vidgui\vidgui.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\src\vidgui\vidwin.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath="..\src\vidgui\vidgui.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\vidgui\vidwin.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/pjsip-apps/build/wince-evc4/output/.keep b/pjsip-apps/build/wince-evc4/output/.keep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/pjsip-apps/build/wince-evc4/output/.keep
diff --git a/pjsip-apps/build/wince-evc4/wince_demos.vcw b/pjsip-apps/build/wince-evc4/wince_demos.vcw
new file mode 100644
index 0000000..cb1f4a5
--- /dev/null
+++ b/pjsip-apps/build/wince-evc4/wince_demos.vcw
@@ -0,0 +1,305 @@
+Microsoft eMbedded Visual Tools Workspace File, Format Version 4.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "libgsmcodec"="..\..\..\THIRD_PARTY\BUILD\GSM\libgsmcodec.vcp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "libilbccodec"="..\..\..\THIRD_PARTY\BUILD\ILBC\libilbccodec.vcp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "libmilenage"="..\..\..\third_party\build\milenage\libmilenage.vcp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "libportaudio"="..\..\..\THIRD_PARTY\BUILD\PORTAUDIO\libportaudio.vcp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "libresample"="..\..\..\THIRD_PARTY\BUILD\RESAMPLE\libresample.vcp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "libspeex"="..\..\..\THIRD_PARTY\BUILD\SPEEX\libspeex.vcp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "libsrtp"="..\..\..\third_party\build\srtp\libsrtp.vcp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "pjlib_util_wince"="..\..\..\pjlib-util\build\wince-evc4\pjlib_util_wince.vcp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "pjlib_wince"="..\..\..\pjlib\build\wince-evc4\pjlib_wince.vcp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "pjmedia_auddev_wince"="..\..\..\pjmedia\build\wince-evc4\pjmedia_auddev_wince.vcp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "pjmedia_codec_wince"="..\..\..\pjmedia\build\wince-evc4\pjmedia_codec_wince.vcp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "pjmedia_wince"="..\..\..\pjmedia\build\wince-evc4\pjmedia_wince.vcp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "pjnath_wince"="..\..\..\pjnath\build\wince-evc4\pjnath_wince.vcp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "pjsip_core_wince"="..\..\..\pjsip\build\wince-evc4\pjsip_core_wince.vcp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "pjsip_simple_wince"="..\..\..\pjsip\build\wince-evc4\pjsip_simple_wince.vcp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "pjsip_ua_wince"="..\..\..\pjsip\build\wince-evc4\pjsip_ua_wince.vcp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "pjsua_lib_wince"="..\..\..\pjsip\build\wince-evc4\pjsua_lib_wince.vcp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name pjlib_util_wince
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name pjlib_wince
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name pjmedia_codec_wince
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name pjmedia_wince
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name pjsip_core_wince
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name pjsip_simple_wince
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name pjsip_ua_wince
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "pjsua_wince"="..\..\src\pjsua_wince\pjsua_wince.vcp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name pjlib_util_wince
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name pjlib_wince
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name pjmedia_codec_wince
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name pjmedia_wince
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name pjsip_core_wince
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name pjsip_simple_wince
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name pjsip_ua_wince
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name pjsua_lib_wince
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name pjnath_wince
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libgsmcodec
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libilbccodec
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libportaudio
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libresample
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libspeex
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libmilenage
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libsrtp
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name pjmedia_auddev_wince
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/pjsip-apps/docs/.keep b/pjsip-apps/docs/.keep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/pjsip-apps/docs/.keep
diff --git a/pjsip-apps/lib/.keep b/pjsip-apps/lib/.keep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/pjsip-apps/lib/.keep
diff --git a/pjsip-apps/src/3rdparty_media_sample/Makefile b/pjsip-apps/src/3rdparty_media_sample/Makefile
new file mode 100644
index 0000000..78e56fd
--- /dev/null
+++ b/pjsip-apps/src/3rdparty_media_sample/Makefile
@@ -0,0 +1,34 @@
+
+include ../../../build.mak
+
+
+###############################################################################
+# Gather all flags.
+#
+export _CFLAGS := $(PJ_CFLAGS) $(CFLAGS)
+export _CXXFLAGS:= $(PJ_CXXFLAGS)
+export _LDFLAGS := $(PJ_LDFLAGS) $(PJ_LDLIBS) $(LDFLAGS)
+
+OBJS = alt_pjsua_aud.o alt_pjsua_vid.o pjsua_app.o main.o
+
+all: alt_pjsua
+
+alt_pjsua: $(OBJS)
+ $(PJ_CC) -o $@ $(OBJS) $(_CFLAGS) $(_LDFLAGS)
+
+pjsua_app.o: ../pjsua/pjsua_app.c
+ $(PJ_CC) $(_CFLAGS) -c -o $@ $<
+
+main.o: ../pjsua/main.c
+ $(PJ_CC) $(_CFLAGS) -c -o $@ $<
+
+%.o: %.c
+ $(PJ_CC) $(_CFLAGS) -c -o $@ $<
+
+depend:
+
+clean:
+ rm -f *.o alt_pjsua
+
+distclean realclean: clean
+
diff --git a/pjsip-apps/src/3rdparty_media_sample/alt_pjsua_aud.c b/pjsip-apps/src/3rdparty_media_sample/alt_pjsua_aud.c
new file mode 100644
index 0000000..fd2bf71
--- /dev/null
+++ b/pjsip-apps/src/3rdparty_media_sample/alt_pjsua_aud.c
@@ -0,0 +1,631 @@
+/* $Id: alt_pjsua_aud.c 4174 2012-06-21 08:09:53Z bennylp $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <pjsua-lib/pjsua.h>
+#include <pjsua-lib/pjsua_internal.h>
+
+#if defined(PJSUA_MEDIA_HAS_PJMEDIA) && PJSUA_MEDIA_HAS_PJMEDIA != 0
+# error The PJSUA_MEDIA_HAS_PJMEDIA should be declared as zero
+#endif
+
+
+#define THIS_FILE "alt_pjsua_aud.c"
+#define UNIMPLEMENTED(func) PJ_LOG(2,(THIS_FILE, "*** Call to unimplemented function %s ***", #func));
+
+
+/*****************************************************************************
+ * Our dummy codecs. Since we won't use any PJMEDIA codecs, we need to declare
+ * our own codecs and register them to PJMEDIA's codec manager. We just need
+ * the info so that they can be listed in SDP. The encoding and decoding will
+ * happen in your third party media stream and will not use these codecs,
+ * hence the "dummy" name.
+ */
+static struct alt_codec
+{
+ pj_str_t encoding_name;
+ pj_uint8_t payload_type;
+ unsigned clock_rate;
+ unsigned channel_cnt;
+ unsigned frm_ptime;
+ unsigned avg_bps;
+ unsigned max_bps;
+} codec_list[] =
+{
+ /* G.729 */
+ { { "G729", 4 }, 18, 8000, 1, 10, 8000, 8000 },
+ /* PCMU */
+ { { "PCMU", 4 }, 0, 8000, 1, 10, 64000, 64000 },
+ /* Our proprietary high end low bit rate (5kbps) codec, if you wish */
+ { { "FOO", 3 }, PJMEDIA_RTP_PT_START+0, 16000, 1, 20, 5000, 5000 },
+};
+
+static struct alt_codec_factory
+{
+ pjmedia_codec_factory base;
+} alt_codec_factory;
+
+static pj_status_t alt_codec_test_alloc( pjmedia_codec_factory *factory,
+ const pjmedia_codec_info *id )
+{
+ unsigned i;
+ for (i=0; i<PJ_ARRAY_SIZE(codec_list); ++i) {
+ if (pj_stricmp(&id->encoding_name, &codec_list[i].encoding_name)==0)
+ return PJ_SUCCESS;
+ }
+ return PJ_ENOTSUP;
+}
+
+static pj_status_t alt_codec_default_attr( pjmedia_codec_factory *factory,
+ const pjmedia_codec_info *id,
+ pjmedia_codec_param *attr )
+{
+ struct alt_codec *ac;
+ unsigned i;
+
+ PJ_UNUSED_ARG(factory);
+
+ for (i=0; i<PJ_ARRAY_SIZE(codec_list); ++i) {
+ if (pj_stricmp(&id->encoding_name, &codec_list[i].encoding_name)==0)
+ break;
+ }
+ if (i == PJ_ARRAY_SIZE(codec_list))
+ return PJ_ENOTFOUND;
+
+ ac = &codec_list[i];
+
+ pj_bzero(attr, sizeof(pjmedia_codec_param));
+ attr->info.clock_rate = ac->clock_rate;
+ attr->info.channel_cnt = ac->channel_cnt;
+ attr->info.avg_bps = ac->avg_bps;
+ attr->info.max_bps = ac->max_bps;
+ attr->info.pcm_bits_per_sample = 16;
+ attr->info.frm_ptime = ac->frm_ptime;
+ attr->info.pt = ac->payload_type;
+
+ attr->setting.frm_per_pkt = 1;
+ attr->setting.vad = 1;
+ attr->setting.plc = 1;
+
+ return PJ_SUCCESS;
+}
+
+static pj_status_t alt_codec_enum_codecs(pjmedia_codec_factory *factory,
+ unsigned *count,
+ pjmedia_codec_info codecs[])
+{
+ unsigned i;
+
+ for (i=0; i<*count && i<PJ_ARRAY_SIZE(codec_list); ++i) {
+ struct alt_codec *ac = &codec_list[i];
+ pj_bzero(&codecs[i], sizeof(pjmedia_codec_info));
+ codecs[i].encoding_name = ac->encoding_name;
+ codecs[i].pt = ac->payload_type;
+ codecs[i].type = PJMEDIA_TYPE_AUDIO;
+ codecs[i].clock_rate = ac->clock_rate;
+ codecs[i].channel_cnt = ac->channel_cnt;
+ }
+
+ *count = i;
+
+ return PJ_SUCCESS;
+}
+
+static pj_status_t alt_codec_alloc_codec(pjmedia_codec_factory *factory,
+ const pjmedia_codec_info *id,
+ pjmedia_codec **p_codec)
+{
+ /* This will never get called since we won't be using this codec */
+ UNIMPLEMENTED(alt_codec_alloc_codec)
+ return PJ_ENOTSUP;
+}
+
+static pj_status_t alt_codec_dealloc_codec( pjmedia_codec_factory *factory,
+ pjmedia_codec *codec )
+{
+ /* This will never get called */
+ UNIMPLEMENTED(alt_codec_dealloc_codec)
+ return PJ_ENOTSUP;
+}
+
+static pj_status_t alt_codec_deinit(void)
+{
+ pjmedia_codec_mgr *codec_mgr;
+ codec_mgr = pjmedia_endpt_get_codec_mgr(pjsua_var.med_endpt);
+ return pjmedia_codec_mgr_unregister_factory(codec_mgr,
+ &alt_codec_factory.base);
+
+}
+
+static pjmedia_codec_factory_op alt_codec_factory_op =
+{
+ &alt_codec_test_alloc,
+ &alt_codec_default_attr,
+ &alt_codec_enum_codecs,
+ &alt_codec_alloc_codec,
+ &alt_codec_dealloc_codec,
+ &alt_codec_deinit
+};
+
+
+/*****************************************************************************
+ * API
+ */
+
+/* Initialize third party media library. */
+pj_status_t pjsua_aud_subsys_init()
+{
+ pjmedia_codec_mgr *codec_mgr;
+ pj_status_t status;
+
+ /* Register our "dummy" codecs */
+ alt_codec_factory.base.op = &alt_codec_factory_op;
+ codec_mgr = pjmedia_endpt_get_codec_mgr(pjsua_var.med_endpt);
+ status = pjmedia_codec_mgr_register_factory(codec_mgr,
+ &alt_codec_factory.base);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ /* TODO: initialize your evil library here */
+ return PJ_SUCCESS;
+}
+
+/* Start (audio) media library. */
+pj_status_t pjsua_aud_subsys_start(void)
+{
+ /* TODO: */
+ return PJ_SUCCESS;
+}
+
+/* Cleanup and deinitialize third party media library. */
+pj_status_t pjsua_aud_subsys_destroy()
+{
+ /* TODO: */
+ return PJ_SUCCESS;
+}
+
+/* Our callback to receive incoming RTP packets */
+static void aud_rtp_cb(void *user_data, void *pkt, pj_ssize_t size)
+{
+ pjsua_call_media *call_med = (pjsua_call_media*) user_data;
+
+ /* TODO: Do something with the packet */
+ PJ_LOG(4,(THIS_FILE, "RX %d bytes audio RTP packet", (int)size));
+}
+
+/* Our callback to receive RTCP packets */
+static void aud_rtcp_cb(void *user_data, void *pkt, pj_ssize_t size)
+{
+ pjsua_call_media *call_med = (pjsua_call_media*) user_data;
+
+ /* TODO: Do something with the packet here */
+ PJ_LOG(4,(THIS_FILE, "RX %d bytes audio RTCP packet", (int)size));
+}
+
+/* A demo function to send dummy "RTP" packets periodically. You would not
+ * need to have this function in the real app!
+ */
+static void timer_to_send_aud_rtp(void *user_data)
+{
+ pjsua_call_media *call_med = (pjsua_call_media*) user_data;
+ const char *pkt = "Not RTP packet";
+
+ if (!call_med->call || !call_med->call->inv || !call_med->tp) {
+ /* Call has been disconnected. There is race condition here as
+ * this cb may be called sometime after call has been disconnected */
+ return;
+ }
+
+ pjmedia_transport_send_rtp(call_med->tp, pkt, strlen(pkt));
+
+ pjsua_schedule_timer2(&timer_to_send_aud_rtp, call_med, 2000);
+}
+
+static void timer_to_send_aud_rtcp(void *user_data)
+{
+ pjsua_call_media *call_med = (pjsua_call_media*) user_data;
+ const char *pkt = "Not RTCP packet";
+
+ if (!call_med->call || !call_med->call->inv || !call_med->tp) {
+ /* Call has been disconnected. There is race condition here as
+ * this cb may be called sometime after call has been disconnected */
+ return;
+ }
+
+ pjmedia_transport_send_rtcp(call_med->tp, pkt, strlen(pkt));
+
+ pjsua_schedule_timer2(&timer_to_send_aud_rtcp, call_med, 5000);
+}
+
+/* Stop the audio stream of a call. */
+void pjsua_aud_stop_stream(pjsua_call_media *call_med)
+{
+ /* Detach our RTP/RTCP callbacks from transport */
+ pjmedia_transport_detach(call_med->tp, call_med);
+
+ /* TODO: destroy your audio stream here */
+}
+
+/*
+ * This function is called whenever SDP negotiation has completed
+ * successfully. Here you'd want to start your audio stream
+ * based on the info in the SDPs.
+ */
+pj_status_t pjsua_aud_channel_update(pjsua_call_media *call_med,
+ pj_pool_t *tmp_pool,
+ pjmedia_stream_info *si,
+ const pjmedia_sdp_session *local_sdp,
+ const pjmedia_sdp_session *remote_sdp)
+{
+ pj_status_t status = PJ_SUCCESS;
+
+ PJ_LOG(4,(THIS_FILE,"Alt audio channel update.."));
+ pj_log_push_indent();
+
+ /* Check if no media is active */
+ if (si->dir != PJMEDIA_DIR_NONE) {
+ /* Attach our RTP and RTCP callbacks to the media transport */
+ status = pjmedia_transport_attach(call_med->tp, call_med,
+ &si->rem_addr, &si->rem_rtcp,
+ pj_sockaddr_get_len(&si->rem_addr),
+ &aud_rtp_cb, &aud_rtcp_cb);
+
+ /* For a demonstration, let's use a timer to send "RTP" packet
+ * periodically.
+ */
+ pjsua_schedule_timer2(&timer_to_send_aud_rtp, call_med, 0);
+ pjsua_schedule_timer2(&timer_to_send_aud_rtcp, call_med, 2500);
+
+ /* TODO:
+ * - Create and start your media stream based on the parameters
+ * in si
+ */
+ }
+
+on_return:
+ pj_log_pop_indent();
+ return status;
+}
+
+void pjsua_check_snd_dev_idle()
+{
+}
+
+/*****************************************************************************
+ *
+ * Call API which MAY need to be re-implemented if different backend is used.
+ */
+
+/* Check if call has an active media session. */
+PJ_DEF(pj_bool_t) pjsua_call_has_media(pjsua_call_id call_id)
+{
+ UNIMPLEMENTED(pjsua_call_has_media)
+ return PJ_TRUE;
+}
+
+
+/* Get the conference port identification associated with the call. */
+PJ_DEF(pjsua_conf_port_id) pjsua_call_get_conf_port(pjsua_call_id call_id)
+{
+ UNIMPLEMENTED(pjsua_call_get_conf_port)
+ return PJSUA_INVALID_ID;
+}
+
+/* Get media stream info for the specified media index. */
+PJ_DEF(pj_status_t) pjsua_call_get_stream_info( pjsua_call_id call_id,
+ unsigned med_idx,
+ pjsua_stream_info *psi)
+{
+ pj_bzero(psi, sizeof(*psi));
+ UNIMPLEMENTED(pjsua_call_get_stream_info)
+ return PJ_ENOTSUP;
+}
+
+/* Get media stream statistic for the specified media index. */
+PJ_DEF(pj_status_t) pjsua_call_get_stream_stat( pjsua_call_id call_id,
+ unsigned med_idx,
+ pjsua_stream_stat *stat)
+{
+ pj_bzero(stat, sizeof(*stat));
+ UNIMPLEMENTED(pjsua_call_get_stream_stat)
+ return PJ_ENOTSUP;
+}
+
+/*
+ * Send DTMF digits to remote using RFC 2833 payload formats.
+ */
+PJ_DEF(pj_status_t) pjsua_call_dial_dtmf( pjsua_call_id call_id,
+ const pj_str_t *digits)
+{
+ UNIMPLEMENTED(pjsua_call_dial_dtmf)
+ return PJ_ENOTSUP;
+}
+
+/*****************************************************************************
+ * Below are auxiliary API that we don't support (feel free to implement them
+ * with the other media stack)
+ */
+
+/* Get maximum number of conference ports. */
+PJ_DEF(unsigned) pjsua_conf_get_max_ports(void)
+{
+ UNIMPLEMENTED(pjsua_conf_get_max_ports)
+ return 0xFF;
+}
+
+/* Get current number of active ports in the bridge. */
+PJ_DEF(unsigned) pjsua_conf_get_active_ports(void)
+{
+ UNIMPLEMENTED(pjsua_conf_get_active_ports)
+ return 0;
+}
+
+/* Enumerate all conference ports. */
+PJ_DEF(pj_status_t) pjsua_enum_conf_ports(pjsua_conf_port_id id[],
+ unsigned *count)
+{
+ *count = 0;
+ UNIMPLEMENTED(pjsua_enum_conf_ports)
+ return PJ_ENOTSUP;
+}
+
+/* Get information about the specified conference port */
+PJ_DEF(pj_status_t) pjsua_conf_get_port_info( pjsua_conf_port_id id,
+ pjsua_conf_port_info *info)
+{
+ UNIMPLEMENTED(pjsua_conf_get_port_info)
+ return PJ_ENOTSUP;
+}
+
+/* Add arbitrary media port to PJSUA's conference bridge. */
+PJ_DEF(pj_status_t) pjsua_conf_add_port( pj_pool_t *pool,
+ pjmedia_port *port,
+ pjsua_conf_port_id *p_id)
+{
+ *p_id = PJSUA_INVALID_ID;
+ UNIMPLEMENTED(pjsua_conf_add_port)
+ /* We should return PJ_ENOTSUP here, but this API is needed by pjsua
+ * application or otherwise it will refuse to start.
+ */
+ return PJ_SUCCESS;
+}
+
+/* Remove arbitrary slot from the conference bridge. */
+PJ_DEF(pj_status_t) pjsua_conf_remove_port(pjsua_conf_port_id id)
+{
+ UNIMPLEMENTED(pjsua_conf_remove_port)
+ return PJ_ENOTSUP;
+}
+
+/* Establish unidirectional media flow from souce to sink. */
+PJ_DEF(pj_status_t) pjsua_conf_connect( pjsua_conf_port_id source,
+ pjsua_conf_port_id sink)
+{
+ UNIMPLEMENTED(pjsua_conf_connect)
+ return PJ_ENOTSUP;
+}
+
+/* Disconnect media flow from the source to destination port. */
+PJ_DEF(pj_status_t) pjsua_conf_disconnect( pjsua_conf_port_id source,
+ pjsua_conf_port_id sink)
+{
+ UNIMPLEMENTED(pjsua_conf_disconnect)
+ return PJ_ENOTSUP;
+}
+
+/* Adjust the signal level to be transmitted from the bridge to the
+ * specified port by making it louder or quieter.
+ */
+PJ_DEF(pj_status_t) pjsua_conf_adjust_tx_level(pjsua_conf_port_id slot,
+ float level)
+{
+ UNIMPLEMENTED(pjsua_conf_adjust_tx_level)
+ return PJ_ENOTSUP;
+}
+
+/* Adjust the signal level to be received from the specified port (to
+ * the bridge) by making it louder or quieter.
+ */
+PJ_DEF(pj_status_t) pjsua_conf_adjust_rx_level(pjsua_conf_port_id slot,
+ float level)
+{
+ UNIMPLEMENTED(pjsua_conf_adjust_rx_level)
+ return PJ_ENOTSUP;
+}
+
+
+/* Get last signal level transmitted to or received from the specified port. */
+PJ_DEF(pj_status_t) pjsua_conf_get_signal_level(pjsua_conf_port_id slot,
+ unsigned *tx_level,
+ unsigned *rx_level)
+{
+ UNIMPLEMENTED(pjsua_conf_get_signal_level)
+ return PJ_ENOTSUP;
+}
+
+/* Create a file player, and automatically connect this player to
+ * the conference bridge.
+ */
+PJ_DEF(pj_status_t) pjsua_player_create( const pj_str_t *filename,
+ unsigned options,
+ pjsua_player_id *p_id)
+{
+ UNIMPLEMENTED(pjsua_player_create)
+ return PJ_ENOTSUP;
+}
+
+/* Create a file playlist media port, and automatically add the port
+ * to the conference bridge.
+ */
+PJ_DEF(pj_status_t) pjsua_playlist_create( const pj_str_t file_names[],
+ unsigned file_count,
+ const pj_str_t *label,
+ unsigned options,
+ pjsua_player_id *p_id)
+{
+ UNIMPLEMENTED(pjsua_playlist_create)
+ return PJ_ENOTSUP;
+}
+
+/* Get conference port ID associated with player. */
+PJ_DEF(pjsua_conf_port_id) pjsua_player_get_conf_port(pjsua_player_id id)
+{
+ UNIMPLEMENTED(pjsua_player_get_conf_port)
+ return -1;
+}
+
+/* Get the media port for the player. */
+PJ_DEF(pj_status_t) pjsua_player_get_port( pjsua_player_id id,
+ pjmedia_port **p_port)
+{
+ UNIMPLEMENTED(pjsua_player_get_port)
+ return PJ_ENOTSUP;
+}
+
+/* Set playback position. */
+PJ_DEF(pj_status_t) pjsua_player_set_pos( pjsua_player_id id,
+ pj_uint32_t samples)
+{
+ UNIMPLEMENTED(pjsua_player_set_pos)
+ return PJ_ENOTSUP;
+}
+
+/* Close the file, remove the player from the bridge, and free
+ * resources associated with the file player.
+ */
+PJ_DEF(pj_status_t) pjsua_player_destroy(pjsua_player_id id)
+{
+ UNIMPLEMENTED(pjsua_player_destroy)
+ return PJ_ENOTSUP;
+}
+
+/* Create a file recorder, and automatically connect this recorder to
+ * the conference bridge.
+ */
+PJ_DEF(pj_status_t) pjsua_recorder_create( const pj_str_t *filename,
+ unsigned enc_type,
+ void *enc_param,
+ pj_ssize_t max_size,
+ unsigned options,
+ pjsua_recorder_id *p_id)
+{
+ UNIMPLEMENTED(pjsua_recorder_create)
+ return PJ_ENOTSUP;
+}
+
+
+/* Get conference port associated with recorder. */
+PJ_DEF(pjsua_conf_port_id) pjsua_recorder_get_conf_port(pjsua_recorder_id id)
+{
+ UNIMPLEMENTED(pjsua_recorder_get_conf_port)
+ return -1;
+}
+
+/* Get the media port for the recorder. */
+PJ_DEF(pj_status_t) pjsua_recorder_get_port( pjsua_recorder_id id,
+ pjmedia_port **p_port)
+{
+ UNIMPLEMENTED(pjsua_recorder_get_port)
+ return PJ_ENOTSUP;
+}
+
+/* Destroy recorder (this will complete recording). */
+PJ_DEF(pj_status_t) pjsua_recorder_destroy(pjsua_recorder_id id)
+{
+ UNIMPLEMENTED(pjsua_recorder_destroy)
+ return PJ_ENOTSUP;
+}
+
+/* Enum sound devices. */
+PJ_DEF(pj_status_t) pjsua_enum_aud_devs( pjmedia_aud_dev_info info[],
+ unsigned *count)
+{
+ UNIMPLEMENTED(pjsua_enum_aud_devs)
+ return PJ_ENOTSUP;
+}
+
+PJ_DEF(pj_status_t) pjsua_enum_snd_devs( pjmedia_snd_dev_info info[],
+ unsigned *count)
+{
+ UNIMPLEMENTED(pjsua_enum_snd_devs)
+ return PJ_ENOTSUP;
+}
+
+/* Select or change sound device. */
+PJ_DEF(pj_status_t) pjsua_set_snd_dev( int capture_dev, int playback_dev)
+{
+ UNIMPLEMENTED(pjsua_set_snd_dev)
+ return PJ_SUCCESS;
+}
+
+/* Get currently active sound devices. */
+PJ_DEF(pj_status_t) pjsua_get_snd_dev(int *capture_dev, int *playback_dev)
+{
+ *capture_dev = *playback_dev = PJSUA_INVALID_ID;
+ UNIMPLEMENTED(pjsua_get_snd_dev)
+ return PJ_ENOTSUP;
+}
+
+/* Use null sound device. */
+PJ_DEF(pj_status_t) pjsua_set_null_snd_dev(void)
+{
+ UNIMPLEMENTED(pjsua_set_null_snd_dev)
+ return PJ_ENOTSUP;
+}
+
+/* Use no device! */
+PJ_DEF(pjmedia_port*) pjsua_set_no_snd_dev(void)
+{
+ UNIMPLEMENTED(pjsua_set_no_snd_dev)
+ return NULL;
+}
+
+/* Configure the AEC settings of the sound port. */
+PJ_DEF(pj_status_t) pjsua_set_ec(unsigned tail_ms, unsigned options)
+{
+ UNIMPLEMENTED(pjsua_set_ec)
+ return PJ_ENOTSUP;
+}
+
+/* Get current AEC tail length. */
+PJ_DEF(pj_status_t) pjsua_get_ec_tail(unsigned *p_tail_ms)
+{
+ UNIMPLEMENTED(pjsua_get_ec_tail)
+ return PJ_ENOTSUP;
+}
+
+/* Check whether the sound device is currently active. */
+PJ_DEF(pj_bool_t) pjsua_snd_is_active(void)
+{
+ UNIMPLEMENTED(pjsua_snd_is_active)
+ return PJ_FALSE;
+}
+
+/* Configure sound device setting to the sound device being used. */
+PJ_DEF(pj_status_t) pjsua_snd_set_setting( pjmedia_aud_dev_cap cap,
+ const void *pval, pj_bool_t keep)
+{
+ UNIMPLEMENTED(pjsua_snd_set_setting)
+ return PJ_ENOTSUP;
+}
+
+/* Retrieve a sound device setting. */
+PJ_DEF(pj_status_t) pjsua_snd_get_setting(pjmedia_aud_dev_cap cap, void *pval)
+{
+ UNIMPLEMENTED(pjsua_snd_get_setting)
+ return PJ_ENOTSUP;
+}
diff --git a/pjsip-apps/src/3rdparty_media_sample/alt_pjsua_vid.c b/pjsip-apps/src/3rdparty_media_sample/alt_pjsua_vid.c
new file mode 100644
index 0000000..08f7aff
--- /dev/null
+++ b/pjsip-apps/src/3rdparty_media_sample/alt_pjsua_vid.c
@@ -0,0 +1,602 @@
+/* $Id: alt_pjsua_vid.c 4174 2012-06-21 08:09:53Z bennylp $ */
+/*
+ * Copyright (C) 2011-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <pjsua-lib/pjsua.h>
+#include <pjsua-lib/pjsua_internal.h>
+
+#if defined(PJSUA_MEDIA_HAS_PJMEDIA) && PJSUA_MEDIA_HAS_PJMEDIA != 0
+# error The PJSUA_MEDIA_HAS_PJMEDIA should be declared as zero
+#endif
+
+#if PJSUA_HAS_VIDEO
+
+#define THIS_FILE "alt_pjsua_vid.c"
+#define UNIMPLEMENTED(func) PJ_LOG(2,(THIS_FILE, "*** Call to unimplemented function %s ***", #func));
+
+/*****************************************************************************
+ * Our video codec descriptors
+ */
+struct alt_codec_desc
+{
+ /* Predefined info */
+ pjmedia_vid_codec_info info;
+ pjmedia_format_id base_fmt_id;
+ pj_uint32_t avg_bps;
+ pj_uint32_t max_bps;
+ pjmedia_codec_fmtp dec_fmtp;
+} alt_vid_codecs[] =
+{
+ /* H.263+ */
+ {
+ {PJMEDIA_FORMAT_H263P, PJMEDIA_RTP_PT_H263P, {"H263-1998",9},
+ {"H.263 codec", 11}, 90000, PJMEDIA_DIR_ENCODING_DECODING,
+ 0, {PJMEDIA_FORMAT_RGB24}, PJMEDIA_VID_PACKING_PACKETS
+ },
+ PJMEDIA_FORMAT_H263, 256000, 512000,
+ {2, { {{"CIF",3}, {"1",1}},
+ {{"QCIF",4}, {"1",1}}, } },
+ }
+};
+
+static const struct alt_codec_desc* find_codec_desc_by_info(const pjmedia_vid_codec_info *info)
+{
+ unsigned i;
+ for (i=0; i<PJ_ARRAY_SIZE(alt_vid_codecs); ++i) {
+ struct alt_codec_desc *desc = &alt_vid_codecs[i];
+ if ((desc->info.fmt_id == info->fmt_id) &&
+ ((desc->info.dir & info->dir) == info->dir) &&
+ (desc->info.pt == info->pt) &&
+ (desc->info.packings & info->packings))
+ {
+ return desc;
+ }
+ }
+
+ return NULL;
+}
+
+static pj_status_t alt_vid_codec_test_alloc( pjmedia_vid_codec_factory *factory,
+ const pjmedia_vid_codec_info *id )
+{
+ const struct alt_codec_desc *desc = find_codec_desc_by_info(id);
+ return desc? PJ_SUCCESS : PJMEDIA_CODEC_EUNSUP;
+}
+
+static pj_status_t alt_vid_codec_default_attr( pjmedia_vid_codec_factory *factory,
+ const pjmedia_vid_codec_info *info,
+ pjmedia_vid_codec_param *attr )
+{
+ const struct alt_codec_desc *desc = find_codec_desc_by_info(info);
+ unsigned i;
+
+ if (!desc)
+ return PJMEDIA_CODEC_EUNSUP;
+
+ pj_bzero(attr, sizeof(pjmedia_vid_codec_param));
+
+ /* Scan the requested packings and use the lowest number */
+ attr->packing = 0;
+ for (i=0; i<15; ++i) {
+ unsigned packing = (1 << i);
+ if ((desc->info.packings & info->packings) & packing) {
+ attr->packing = (pjmedia_vid_packing)packing;
+ break;
+ }
+ }
+ if (attr->packing == 0) {
+ /* No supported packing in info */
+ return PJMEDIA_CODEC_EUNSUP;
+ }
+
+ /* Direction */
+ attr->dir = desc->info.dir;
+
+ /* Encoded format */
+ pjmedia_format_init_video(&attr->enc_fmt, desc->info.fmt_id,
+ 720, 480, 30000, 1001);
+
+ /* Decoded format */
+ pjmedia_format_init_video(&attr->dec_fmt, desc->info.dec_fmt_id[0],
+ //352, 288, 30000, 1001);
+ 720, 576, 30000, 1001);
+
+ /* Decoding fmtp */
+ attr->dec_fmtp = desc->dec_fmtp;
+
+ /* Bitrate */
+ attr->enc_fmt.det.vid.avg_bps = desc->avg_bps;
+ attr->enc_fmt.det.vid.max_bps = desc->max_bps;
+
+ /* MTU */
+ attr->enc_mtu = PJMEDIA_MAX_MTU;
+
+ return PJ_SUCCESS;
+}
+
+
+static pj_status_t alt_vid_codec_enum_codecs( pjmedia_vid_codec_factory *factory,
+ unsigned *count,
+ pjmedia_vid_codec_info codecs[])
+{
+ unsigned i, max_cnt;
+
+ PJ_ASSERT_RETURN(codecs && *count > 0, PJ_EINVAL);
+
+ max_cnt = PJ_MIN(*count, PJ_ARRAY_SIZE(alt_vid_codecs));
+ *count = 0;
+
+ for (i=0; i<max_cnt; ++i) {
+ pj_memcpy(&codecs[*count], &alt_vid_codecs[i].info,
+ sizeof(pjmedia_vid_codec_info));
+ (*count)++;
+ }
+
+ return PJ_SUCCESS;
+}
+
+
+static pj_status_t alt_vid_codec_alloc_codec( pjmedia_vid_codec_factory *factory,
+ const pjmedia_vid_codec_info *info,
+ pjmedia_vid_codec **p_codec)
+{
+ /* This will never get called since we won't be using this codec */
+ UNIMPLEMENTED(alt_vid_codec_alloc_codec)
+ return PJ_ENOTSUP;
+}
+
+
+static pj_status_t alt_vid_codec_dealloc_codec( pjmedia_vid_codec_factory *factory,
+ pjmedia_vid_codec *codec )
+{
+ /* This will never get called since we won't be using this codec */
+ UNIMPLEMENTED(alt_vid_codec_dealloc_codec)
+ return PJ_ENOTSUP;
+}
+
+static pjmedia_vid_codec_factory_op alt_vid_codec_factory_op =
+{
+ &alt_vid_codec_test_alloc,
+ &alt_vid_codec_default_attr,
+ &alt_vid_codec_enum_codecs,
+ &alt_vid_codec_alloc_codec,
+ &alt_vid_codec_dealloc_codec
+};
+
+static struct alt_vid_codec_factory {
+ pjmedia_vid_codec_factory base;
+} alt_vid_codec_factory;
+
+/*****************************************************************************
+ * Video API implementation
+ */
+
+/* Initialize the video library */
+pj_status_t pjsua_vid_subsys_init(void)
+{
+ pjmedia_vid_codec_mgr *mgr;
+ pj_status_t status;
+
+ /* Format manager singleton is needed */
+ status = pjmedia_video_format_mgr_create(pjsua_var.pool, 64, 0, NULL);
+ if (status != PJ_SUCCESS) {
+ PJ_PERROR(1,(THIS_FILE, status,
+ "Error creating PJMEDIA video format manager"));
+ return status;
+ }
+
+ /* Create video codec manager singleton */
+ status = pjmedia_vid_codec_mgr_create(pjsua_var.pool, &mgr);
+ if (status != PJ_SUCCESS) {
+ PJ_PERROR(1,(THIS_FILE, status,
+ "Error creating PJMEDIA video codec manager"));
+ return status;
+ }
+
+ /* Register our codecs */
+ alt_vid_codec_factory.base.op = &alt_vid_codec_factory_op;
+ alt_vid_codec_factory.base.factory_data = NULL;
+
+ status = pjmedia_vid_codec_mgr_register_factory(mgr, &alt_vid_codec_factory.base);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ /*
+ * TODO: put your 3rd party library initialization routine here
+ */
+
+ return PJ_SUCCESS;
+}
+
+/* Start the video library */
+pj_status_t pjsua_vid_subsys_start(void)
+{
+ /*
+ * TODO: put your 3rd party library startup routine here
+ */
+ return PJ_SUCCESS;
+}
+
+/* Cleanup and deinitialize the video library */
+pj_status_t pjsua_vid_subsys_destroy(void)
+{
+ if (pjmedia_vid_codec_mgr_instance())
+ pjmedia_vid_codec_mgr_destroy(NULL);
+
+ if (pjmedia_video_format_mgr_instance())
+ pjmedia_video_format_mgr_destroy(NULL);
+
+ /*
+ * TODO: put your 3rd party library cleanup routine here
+ */
+ return PJ_SUCCESS;
+}
+
+/* Initialize video call media */
+pj_status_t pjsua_vid_channel_init(pjsua_call_media *call_med)
+{
+ /*
+ * TODO: put call media initialization
+ */
+ return PJ_SUCCESS;
+}
+
+/* Internal function to stop video stream */
+void pjsua_vid_stop_stream(pjsua_call_media *call_med)
+{
+ PJ_LOG(4,(THIS_FILE, "Stopping video stream.."));
+
+ if (call_med->tp) {
+ pjmedia_transport_detach(call_med->tp, call_med);
+ }
+
+ /*
+ * TODO:
+ * - stop your video stream here
+ */
+
+}
+
+/* Our callback to receive incoming RTP packets */
+static void vid_rtp_cb(void *user_data, void *pkt, pj_ssize_t size)
+{
+ pjsua_call_media *call_med = (pjsua_call_media*) user_data;
+
+ /* TODO: Do something with the packet */
+ PJ_LOG(4,(THIS_FILE, "RX %d bytes video RTP packet", (int)size));
+}
+
+/* Our callback to receive RTCP packets */
+static void vid_rtcp_cb(void *user_data, void *pkt, pj_ssize_t size)
+{
+ pjsua_call_media *call_med = (pjsua_call_media*) user_data;
+
+ /* TODO: Do something with the packet here */
+ PJ_LOG(4,(THIS_FILE, "RX %d bytes video RTCP packet", (int)size));
+}
+
+/* A demo function to send dummy "RTP" packets periodically. You would not
+ * need to have this function in the real app!
+ */
+static void timer_to_send_vid_rtp(void *user_data)
+{
+ pjsua_call_media *call_med = (pjsua_call_media*) user_data;
+ const char *pkt = "Not RTP packet";
+
+ if (!call_med->call || !call_med->call->inv || !call_med->tp) {
+ /* Call has been disconnected. There is race condition here as
+ * this cb may be called sometime after call has been disconnected */
+ return;
+ }
+
+ pjmedia_transport_send_rtp(call_med->tp, pkt, strlen(pkt));
+
+ pjsua_schedule_timer2(&timer_to_send_vid_rtp, call_med, 2000);
+}
+
+static void timer_to_send_vid_rtcp(void *user_data)
+{
+ pjsua_call_media *call_med = (pjsua_call_media*) user_data;
+ const char *pkt = "Not RTCP packet";
+
+ if (!call_med->call || !call_med->call->inv || !call_med->tp) {
+ /* Call has been disconnected. There is race condition here as
+ * this cb may be called sometime after call has been disconnected */
+ return;
+ }
+
+ pjmedia_transport_send_rtcp(call_med->tp, pkt, strlen(pkt));
+
+ pjsua_schedule_timer2(&timer_to_send_vid_rtcp, call_med, 5000);
+}
+
+/* update video channel after SDP negotiation */
+pj_status_t pjsua_vid_channel_update(pjsua_call_media *call_med,
+ pj_pool_t *tmp_pool,
+ pjmedia_vid_stream_info *si,
+ const pjmedia_sdp_session *local_sdp,
+ const pjmedia_sdp_session *remote_sdp)
+{
+ pj_status_t status;
+
+ PJ_LOG(4,(THIS_FILE, "Video channel update.."));
+ pj_log_push_indent();
+
+ /* Check if no media is active */
+ if (si->dir != PJMEDIA_DIR_NONE) {
+ /* Attach our RTP and RTCP callbacks to the media transport */
+ status = pjmedia_transport_attach(call_med->tp, call_med,
+ &si->rem_addr, &si->rem_rtcp,
+ pj_sockaddr_get_len(&si->rem_addr),
+ &vid_rtp_cb, &vid_rtcp_cb);
+ /*
+ * TODO:
+ * - Create and start your video stream based on the parameters
+ * in si
+ */
+
+ /* For a demonstration, let's use a timer to send "RTP" packet
+ * periodically.
+ */
+ pjsua_schedule_timer2(&timer_to_send_vid_rtp, call_med, 1000);
+ pjsua_schedule_timer2(&timer_to_send_vid_rtcp, call_med, 3500);
+ }
+
+ pj_log_pop_indent();
+ return PJ_SUCCESS;
+}
+
+
+/*****************************************************************************
+ * Preview
+ */
+
+PJ_DEF(void)
+pjsua_call_vid_strm_op_param_default(pjsua_call_vid_strm_op_param *param)
+{
+ pj_bzero(param, sizeof(*param));
+ param->med_idx = -1;
+ param->dir = PJMEDIA_DIR_ENCODING_DECODING;
+ param->cap_dev = PJMEDIA_VID_DEFAULT_CAPTURE_DEV;
+}
+
+PJ_DEF(void) pjsua_vid_preview_param_default(pjsua_vid_preview_param *p)
+{
+ p->rend_id = PJMEDIA_VID_DEFAULT_RENDER_DEV;
+ p->show = PJ_TRUE;
+}
+
+PJ_DEF(pjsua_vid_win_id) pjsua_vid_preview_get_win(pjmedia_vid_dev_index id)
+{
+ UNIMPLEMENTED(pjsua_vid_preview_get_win)
+ return PJSUA_INVALID_ID;
+}
+
+/* Reset internal window structure. Not sure if this is needed?. */
+PJ_DEF(void) pjsua_vid_win_reset(pjsua_vid_win_id wid)
+{
+ pjsua_vid_win *w = &pjsua_var.win[wid];
+ pj_pool_t *pool = w->pool;
+
+ pj_bzero(w, sizeof(*w));
+ if (pool) pj_pool_reset(pool);
+ w->ref_cnt = 0;
+ w->pool = pool;
+ w->preview_cap_id = PJMEDIA_VID_INVALID_DEV;
+}
+
+/* Does it have built-in preview support. */
+PJ_DEF(pj_bool_t) pjsua_vid_preview_has_native(pjmedia_vid_dev_index id)
+{
+ UNIMPLEMENTED(pjsua_vid_preview_has_native)
+ return PJ_FALSE;
+}
+
+/* Start video preview window for the specified capture device. */
+PJ_DEF(pj_status_t) pjsua_vid_preview_start(pjmedia_vid_dev_index id,
+ const pjsua_vid_preview_param *prm)
+{
+ UNIMPLEMENTED(pjsua_vid_preview_start)
+ return PJ_ENOTSUP;
+}
+
+/* Stop video preview. */
+PJ_DEF(pj_status_t) pjsua_vid_preview_stop(pjmedia_vid_dev_index id)
+{
+ UNIMPLEMENTED(pjsua_vid_preview_stop)
+ return PJ_ENOTSUP;
+}
+
+
+/*****************************************************************************
+ * Devices.
+ */
+
+/* Get the number of video devices installed in the system. */
+PJ_DEF(unsigned) pjsua_vid_dev_count(void)
+{
+ UNIMPLEMENTED(pjsua_vid_dev_count)
+ return 0;
+}
+
+/* Retrieve the video device info for the specified device index. */
+PJ_DEF(pj_status_t) pjsua_vid_dev_get_info(pjmedia_vid_dev_index id,
+ pjmedia_vid_dev_info *vdi)
+{
+ UNIMPLEMENTED(pjsua_vid_dev_get_info)
+ return PJ_ENOTSUP;
+}
+
+/* Enum all video devices installed in the system. */
+PJ_DEF(pj_status_t) pjsua_vid_enum_devs(pjmedia_vid_dev_info info[],
+ unsigned *count)
+{
+ UNIMPLEMENTED(pjsua_vid_enum_devs)
+ return PJ_ENOTSUP;
+}
+
+
+/*****************************************************************************
+ * Codecs.
+ */
+
+/* Enum all supported video codecs in the system. */
+PJ_DEF(pj_status_t) pjsua_vid_enum_codecs( pjsua_codec_info id[],
+ unsigned *p_count )
+{
+ pjmedia_vid_codec_info info[32];
+ unsigned i, j, count, prio[32];
+ pj_status_t status;
+
+ count = PJ_ARRAY_SIZE(info);
+ status = pjmedia_vid_codec_mgr_enum_codecs(NULL, &count, info, prio);
+ if (status != PJ_SUCCESS) {
+ *p_count = 0;
+ return status;
+ }
+ for (i=0, j=0; i<count && j<*p_count; ++i) {
+ if (info[i].packings & PJMEDIA_VID_PACKING_PACKETS) {
+ pj_bzero(&id[j], sizeof(pjsua_codec_info));
+
+ pjmedia_vid_codec_info_to_id(&info[i], id[j].buf_, sizeof(id[j].buf_));
+ id[j].codec_id = pj_str(id[j].buf_);
+ id[j].priority = (pj_uint8_t) prio[i];
+
+ if (id[j].codec_id.slen < sizeof(id[j].buf_)) {
+ id[j].desc.ptr = id[j].codec_id.ptr + id[j].codec_id.slen + 1;
+ pj_strncpy(&id[j].desc, &info[i].encoding_desc,
+ sizeof(id[j].buf_) - id[j].codec_id.slen - 1);
+ }
+
+ ++j;
+ }
+ }
+
+ *p_count = j;
+ return PJ_SUCCESS;
+}
+
+/* Change video codec priority. */
+PJ_DEF(pj_status_t) pjsua_vid_codec_set_priority( const pj_str_t *codec_id,
+ pj_uint8_t priority )
+{
+ UNIMPLEMENTED(pjsua_vid_codec_set_priority)
+ return PJ_ENOTSUP;
+}
+
+/* Get video codec parameters. */
+PJ_DEF(pj_status_t) pjsua_vid_codec_get_param(
+ const pj_str_t *codec_id,
+ pjmedia_vid_codec_param *param)
+{
+ UNIMPLEMENTED(pjsua_vid_codec_get_param)
+ return PJ_ENOTSUP;
+}
+
+/* Set video codec parameters. */
+PJ_DEF(pj_status_t) pjsua_vid_codec_set_param(
+ const pj_str_t *codec_id,
+ const pjmedia_vid_codec_param *param)
+{
+ UNIMPLEMENTED(pjsua_vid_codec_set_param)
+ return PJ_ENOTSUP;
+}
+
+
+/*****************************************************************************
+ * Window
+ */
+
+/* Enumerates all video windows. */
+PJ_DEF(pj_status_t) pjsua_vid_enum_wins( pjsua_vid_win_id wids[],
+ unsigned *count)
+{
+ UNIMPLEMENTED(pjsua_vid_enum_wins)
+ return PJ_ENOTSUP;
+}
+
+/* Get window info. */
+PJ_DEF(pj_status_t) pjsua_vid_win_get_info( pjsua_vid_win_id wid,
+ pjsua_vid_win_info *wi)
+{
+ UNIMPLEMENTED(pjsua_vid_win_get_info)
+ return PJ_ENOTSUP;
+}
+
+/* Show or hide window. */
+PJ_DEF(pj_status_t) pjsua_vid_win_set_show( pjsua_vid_win_id wid,
+ pj_bool_t show)
+{
+ UNIMPLEMENTED(pjsua_vid_win_set_show)
+ return PJ_ENOTSUP;
+}
+
+/* Set video window position. */
+PJ_DEF(pj_status_t) pjsua_vid_win_set_pos( pjsua_vid_win_id wid,
+ const pjmedia_coord *pos)
+{
+ UNIMPLEMENTED(pjsua_vid_win_set_pos)
+ return PJ_ENOTSUP;
+}
+
+/* Resize window. */
+PJ_DEF(pj_status_t) pjsua_vid_win_set_size( pjsua_vid_win_id wid,
+ const pjmedia_rect_size *size)
+{
+ UNIMPLEMENTED(pjsua_vid_win_set_size)
+ return PJ_ENOTSUP;
+}
+
+/* Set video orientation. */
+PJ_DEF(pj_status_t) pjsua_vid_win_rotate( pjsua_vid_win_id wid,
+ int angle)
+{
+ UNIMPLEMENTED(pjsua_vid_win_rotate)
+ return PJ_ENOTSUP;
+}
+
+/* Start, stop, and/or manipulate video transmission for the specified call. */
+PJ_DEF(pj_status_t) pjsua_call_set_vid_strm (
+ pjsua_call_id call_id,
+ pjsua_call_vid_strm_op op,
+ const pjsua_call_vid_strm_op_param *param)
+{
+ UNIMPLEMENTED(pjsua_call_set_vid_strm)
+ return PJ_ENOTSUP;
+}
+
+
+/* Get the media stream index of the default video stream in the call. */
+PJ_DEF(int) pjsua_call_get_vid_stream_idx(pjsua_call_id call_id)
+{
+ UNIMPLEMENTED(pjsua_call_get_vid_stream_idx)
+ return -1;
+}
+
+/* Determine if video stream for the specified call is currently running
+ * for the specified direction.
+ */
+PJ_DEF(pj_bool_t) pjsua_call_vid_stream_is_running( pjsua_call_id call_id,
+ int med_idx,
+ pjmedia_dir dir)
+{
+ UNIMPLEMENTED(pjsua_call_vid_stream_is_running)
+ return PJ_FALSE;
+}
+
+#endif /* PJSUA_HAS_VIDEO */
+
diff --git a/pjsip-apps/src/3rdparty_media_sample/config_site.h b/pjsip-apps/src/3rdparty_media_sample/config_site.h
new file mode 100644
index 0000000..e883cec
--- /dev/null
+++ b/pjsip-apps/src/3rdparty_media_sample/config_site.h
@@ -0,0 +1,42 @@
+/*
+ * Put this file in pjlib/include/pj
+ */
+
+/* sample configure command:
+ CFLAGS="-g -Wno-unused-label" ./aconfigure --enable-ext-sound --disable-speex-aec --disable-g711-codec --disable-l16-codec --disable-gsm-codec --disable-g722-codec --disable-g7221-codec --disable-speex-codec --disable-ilbc-codec --disable-opencore-amrnb --disable-sdl --disable-ffmpeg --disable-v4l2
+ */
+
+#define THIRD_PARTY_MEDIA 1
+
+#if THIRD_PARTY_MEDIA
+/*
+ * Sample settings for using third party media with pjsua-lib
+ */
+# define PJSUA_MEDIA_HAS_PJMEDIA 0
+# define PJMEDIA_HAS_G711_CODEC 0
+# define PJMEDIA_HAS_ALAW_ULAW_TABLE 0
+# define PJMEDIA_RESAMPLE_IMP PJMEDIA_RESAMPLE_NONE
+# define PJMEDIA_HAS_SPEEX_AEC 0
+
+# define PJMEDIA_HAS_L16_CODEC 0
+# define PJMEDIA_HAS_GSM_CODEC 0
+# define PJMEDIA_HAS_SPEEX_CODEC 0
+# define PJMEDIA_HAS_ILBC_CODEC 0
+# define PJMEDIA_HAS_G722_CODEC 0
+# define PJMEDIA_HAS_G7221_CODEC 0
+# define PJMEDIA_HAS_OPENCORE_AMRNB_CODEC 0
+
+# define PJMEDIA_HAS_VIDEO 1
+# define PJMEDIA_HAS_FFMPEG 0
+
+# undef PJMEDIA_VIDEO_DEV_HAS_SDL
+# define PJMEDIA_VIDEO_DEV_HAS_SDL 0
+# define PJMEDIA_VIDEO_DEV_HAS_QT 0
+# define PJMEDIA_VIDEO_DEV_HAS_IOS 0
+# define PJMEDIA_VIDEO_DEV_HAS_DSHOW 0
+# define PJMEDIA_VIDEO_DEV_HAS_CBAR_SRC 0
+# define PJMEDIA_VIDEO_DEV_HAS_FFMPEG 0
+# undef PJMEDIA_VIDEO_DEV_HAS_V4L2
+# define PJMEDIA_VIDEO_DEV_HAS_V4L2 0
+#endif /* THIRD_PARTY_MEDIA */
+
diff --git a/pjsip-apps/src/confbot/confbot.py b/pjsip-apps/src/confbot/confbot.py
new file mode 100644
index 0000000..572c50c
--- /dev/null
+++ b/pjsip-apps/src/confbot/confbot.py
@@ -0,0 +1,575 @@
+# $Id: confbot.py 2912 2009-08-24 11:56:13Z bennylp $
+#
+# SIP Conference Bot
+#
+# Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+import pjsua as pj
+import string
+import sys
+
+CFG_FILE = "config"
+
+INFO = 1
+TRACE = 2
+
+# Call callback. This would just forward the event to the Member class
+class CallCb(pj.CallCallback):
+ def __init__(self, member, call=None):
+ pj.CallCallback.__init__(self, call)
+ self.member = member
+
+ def on_state(self):
+ self.member.on_call_state(self.call)
+
+ def on_media_state(self):
+ self.member.on_call_media_state(self.call)
+
+ def on_dtmf_digit(self, digits):
+ self.member.on_call_dtmf_digit(self.call, digits)
+
+ def on_transfer_request(self, dst, code):
+ return self.member.on_call_transfer_request(self.call, dst, code)
+
+ def on_transfer_status(self, code, reason, final, cont):
+ return self.member.on_call_transfer_status(self.call, code, reason, final, cont)
+
+ def on_replace_request(self, code, reason):
+ return self.member.on_call_replace_request(self.call, code, reason)
+
+ def on_replaced(self, new_call):
+ self.member.on_call_replaced(self.call, new_call)
+
+ def on_typing(self, is_typing):
+ self.member.on_typing(is_typing, call=self.call)
+
+ def on_pager(self, mime_type, body):
+ self.member.on_pager(mime_type, body, call=self.call)
+
+ def on_pager_status(self, body, im_id, code, reason):
+ self.member.on_pager_status(body, im_id, code, reason, call=self.call)
+
+# Buddy callback. This would just forward the event to Member class
+class BuddyCb(pj.BuddyCallback):
+ def __init__(self, member, buddy=None):
+ pj.BuddyCallback.__init__(self, buddy)
+ self.member = member
+
+ def on_pager(self, mime_type, body):
+ self.member.on_pager(mime_type, body, buddy=self.buddy)
+
+ def on_pager_status(self, body, im_id, code, reason):
+ self.member.on_pager_status(body, im_id, code, reason, buddy=self.buddy)
+
+ def on_state(self):
+ self.member.on_pres_state(self.buddy)
+
+ def on_typing(self, is_typing):
+ self.member.on_typing(is_typing, buddy=self.buddy)
+
+
+
+
+##############################################################################
+#
+#
+# This class represents individual room member (either/both chat and voice conf)
+#
+#
+class Member:
+ def __init__(self, bot, uri):
+ self.uri = uri
+ self.bot = bot
+ self.call = None
+ self.buddy = None
+ self.bi = pj.BuddyInfo()
+ self.in_chat = False
+ self.in_voice = False
+ self.im_error = False
+ self.html = False
+
+ def __str__(self):
+ str = string.ljust(self.uri, 30) + " -- "
+ if self.buddy:
+ bi = self.buddy.info()
+ str = str + bi.online_text
+ else:
+ str = str + "Offline"
+ str = str + " ["
+ if (self.in_voice):
+ str = str + " voice"
+ if (self.in_chat):
+ str = str + " chat"
+ if (self.html):
+ str = str + " html"
+ else:
+ str = str + " plain"
+
+ if (self.im_error):
+ str = str + " im_error"
+ str = str + "]"
+ return str
+
+ def join_call(self, call):
+ if self.call:
+ self.call.hangup(603, "You have been disconnected for making another call")
+ self.call = call
+ call.set_callback(CallCb(self, call))
+ msg = "%(uri)s is attempting to join the voice conference" % \
+ {'uri': self.uri}
+ self.bot.DEBUG(msg + "\n", INFO)
+ self.bot.broadcast_pager(None, msg)
+
+ def join_chat(self):
+ if not self.buddy:
+ self.bot.DEBUG(self.uri + " joining chatroom...\n", INFO)
+ self.buddy = self.bot.acc.add_buddy(self.uri)
+ self.buddy.set_callback(BuddyCb(self, self.buddy))
+ self.buddy.subscribe()
+ else:
+ self.bot.DEBUG(self.uri + " already in chatroom, resubscribing..\n", INFO)
+ self.buddy.subscribe()
+
+ def send_pager(self, body, mime="text/plain"):
+ self.bot.DEBUG("send_pager() to " + self.uri)
+ if self.in_chat and not self.im_error and self.buddy:
+ if self.html:
+ #This will make us receive html!
+ #mime = "text/html"
+ body = body.replace("<", "&lt;")
+ body = body.replace(">", "&gt;")
+ body = body.replace('"', "&quot;")
+ body = body.replace("\n", "<BR>\n")
+ self.buddy.send_pager(body, content_type=mime)
+ self.bot.DEBUG("..sent\n")
+ else:
+ self.bot.DEBUG("..not sent!\n")
+
+ def on_call_state(self, call):
+ ci = call.info()
+ if ci.state==pj.CallState.DISCONNECTED:
+ if self.in_voice:
+ msg = "%(uri)s has left the voice conference (%(1)d/%(2)s)" % \
+ {'uri': self.uri, '1': ci.last_code, '2': ci.last_reason}
+ self.bot.DEBUG(msg + "\n", INFO)
+ self.bot.broadcast_pager(None, msg)
+ self.in_voice = False
+ self.call = None
+ self.bot.on_member_left(self)
+ elif ci.state==pj.CallState.CONFIRMED:
+ msg = "%(uri)s has joined the voice conference" % \
+ {'uri': self.uri}
+ self.bot.DEBUG(msg + "\n", INFO)
+ self.bot.broadcast_pager(None, msg)
+
+ def on_call_media_state(self, call):
+ self.bot.DEBUG("Member.on_call_media_state\n")
+ ci = call.info()
+ if ci.conf_slot!=-1:
+ if not self.in_voice:
+ msg = self.uri + " call media is active"
+ self.bot.broadcast_pager(None, msg)
+ self.in_voice = True
+ self.bot.add_to_voice_conf(self)
+ else:
+ if self.in_voice:
+ msg = self.uri + " call media is inactive"
+ self.bot.broadcast_pager(None, msg)
+ self.in_voice = False
+
+ def on_call_dtmf_digit(self, call, digits):
+ msg = "%(uri)s sent DTMF digits %(dig)s" % \
+ {'uri': self.uri, 'dig': digits}
+ self.bot.broadcast_pager(None, msg)
+
+ def on_call_transfer_request(self, call, dst, code):
+ msg = "%(uri)s is transfering the call to %(dst)s" % \
+ {'uri': self.uri, 'dst': dst}
+ self.bot.broadcast_pager(None, msg)
+ return 202
+
+ def on_call_transfer_status(self, call, code, reason, final, cont):
+ msg = "%(uri)s call transfer status is %(code)d/%(res)s" % \
+ {'uri': self.uri, 'code': code, 'res': reason}
+ self.bot.broadcast_pager(None, msg)
+ return True
+
+ def on_call_replace_request(self, call, code, reason):
+ msg = "%(uri)s is requesting call replace" % \
+ {'uri': self.uri}
+ self.bot.broadcast_pager(None, msg)
+ return (code, reason)
+
+ def on_call_replaced(self, call, new_call):
+ msg = "%(uri)s call is replaced" % \
+ {'uri': self.uri}
+ self.bot.broadcast_pager(None, msg)
+
+ def on_pres_state(self, buddy):
+ old_bi = self.bi
+ self.bi = buddy.info()
+ msg = "%(uri)s status is %(st)s" % \
+ {'uri': self.uri, 'st': self.bi.online_text}
+ self.bot.DEBUG(msg + "\n", INFO)
+ self.bot.broadcast_pager(self, msg)
+
+ if self.bi.sub_state==pj.SubscriptionState.ACTIVE:
+ if not self.in_chat:
+ self.in_chat = True
+ buddy.send_pager("Welcome to chatroom")
+ self.bot.broadcast_pager(self, self.uri + " has joined the chat room")
+ else:
+ self.in_chat = True
+ elif self.bi.sub_state==pj.SubscriptionState.NULL or \
+ self.bi.sub_state==pj.SubscriptionState.TERMINATED or \
+ self.bi.sub_state==pj.SubscriptionState.UNKNOWN:
+ self.buddy.delete()
+ self.buddy = None
+ if self.in_chat:
+ self.in_chat = False
+ self.bot.broadcast_pager(self, self.uri + " has left the chat room")
+ else:
+ self.in_chat = False
+ self.bot.on_member_left(self)
+
+ def on_typing(self, is_typing, call=None, buddy=None):
+ if is_typing:
+ msg = self.uri + " is typing..."
+ else:
+ msg = self.uri + " has stopped typing"
+ self.bot.broadcast_pager(self, msg)
+
+ def on_pager(self, mime_type, body, call=None, buddy=None):
+ if not self.bot.handle_cmd(self, None, body):
+ msg = self.uri + ": " + body
+ self.bot.broadcast_pager(self, msg, mime_type)
+
+ def on_pager_status(self, body, im_id, code, reason, call=None, buddy=None):
+ self.im_error = (code/100 != 2)
+
+
+
+##############################################################################
+#
+#
+# The Bot instance (singleton)
+#
+#
+class Bot(pj.AccountCallback):
+ def __init__(self):
+ pj.AccountCallback.__init__(self, None)
+ self.lib = pj.Lib()
+ self.acc = None
+ self.calls = []
+ self.members = {}
+ self.cfg = None
+
+ def DEBUG(self, msg, level=TRACE):
+ print msg,
+
+ def helpstring(self):
+ return """
+--h[elp] Display this help screen
+--j[oin] Join the chat room
+--html on|off Set to receive HTML or plain text
+
+Participant commands:
+--s[how] Show confbot settings
+--leave Leave the chatroom
+--l[ist] List all members
+
+Admin commands:
+--a[dmin] <CMD> Where <CMD> are:
+ list List the admins
+ add <URI> Add URI as admin
+ del <URI> Remove URI as admin
+ rr Reregister account to server
+ call <URI> Make call to the URI and add to voice conf
+ dc <URI> Disconnect call to URI
+ hold <URI> Hold call with that URI
+ update <URI> Send UPDATE to call with that URI
+ reinvite <URI> Send re-INVITE to call with that URI
+"""
+
+ def listmembers(self):
+ msg = ""
+ for uri, m in self.members.iteritems():
+ msg = msg + str(m) + "\n"
+ return msg
+
+ def showsettings(self):
+ ai = self.acc.info()
+ msg = """
+ConfBot status and settings:
+ URI: %(uri)s
+ Status: %(pres)s
+ Reg Status: %(reg_st)d
+ Reg Reason: %(reg_res)s
+""" % {'uri': ai.uri, 'pres': ai.online_text, \
+ 'reg_st': ai.reg_status, 'reg_res': ai.reg_reason}
+ return msg
+
+ def main(self, cfg_file):
+ try:
+ cfg = self.cfg = __import__(cfg_file)
+
+ self.lib.init(ua_cfg=cfg.ua_cfg, log_cfg=cfg.log_cfg, media_cfg=cfg.media_cfg)
+ self.lib.set_null_snd_dev()
+
+ transport = None
+ if cfg.udp_cfg:
+ transport = self.lib.create_transport(pj.TransportType.UDP, cfg.udp_cfg)
+ if cfg.tcp_cfg:
+ t = self.lib.create_transport(pj.TransportType.TCP, cfg.tcp_cfg)
+ if not transport:
+ transport = t
+
+ self.lib.start()
+
+ if cfg.acc_cfg:
+ self.DEBUG("Creating account %(uri)s..\n" % {'uri': cfg.acc_cfg.id}, INFO)
+ self.acc = self.lib.create_account(cfg.acc_cfg, cb=self)
+ else:
+ self.DEBUG("Creating account for %(t)s..\n" % \
+ {'t': transport.info().description}, INFO)
+ self.acc = self.lib.create_account_for_transport(transport, cb=self)
+
+ self.acc.set_basic_status(True)
+
+ # Wait for ENTER before quitting
+ print "Press q to quit or --help/--h for help"
+ while True:
+ input = sys.stdin.readline().strip(" \t\r\n")
+ if not self.handle_cmd(None, None, input):
+ if input=="q":
+ break
+
+ self.lib.destroy()
+ self.lib = None
+
+ except pj.Error, e:
+ print "Exception: " + str(e)
+ if self.lib:
+ self.lib.destroy()
+ self.lib = None
+
+ def broadcast_pager(self, exclude_member, body, mime_type="text/plain"):
+ self.DEBUG("Broadcast: " + body + "\n")
+ for uri, m in self.members.iteritems():
+ if m != exclude_member:
+ m.send_pager(body, mime_type)
+
+ def add_to_voice_conf(self, member):
+ if not member.call:
+ return
+ src_ci = member.call.info()
+ self.DEBUG("bot.add_to_voice_conf\n")
+ for uri, m in self.members.iteritems():
+ if m==member:
+ continue
+ if not m.call:
+ continue
+ dst_ci = m.call.info()
+ if dst_ci.media_state==pj.MediaState.ACTIVE and dst_ci.conf_slot!=-1:
+ self.lib.conf_connect(src_ci.conf_slot, dst_ci.conf_slot)
+ self.lib.conf_connect(dst_ci.conf_slot, src_ci.conf_slot)
+
+ def on_member_left(self, member):
+ if not member.call and not member.buddy:
+ del self.members[member.uri]
+ del member
+
+ def handle_admin_cmd(self, member, body):
+ if member and self.cfg.admins and not member.uri in self.cfg.admins:
+ member.send_pager("You are not admin")
+ return
+ args = body.split()
+ msg = ""
+
+ if len(args)==1:
+ args.append(" ")
+
+ if args[1]=="list":
+ if not self.cfg.admins:
+ msg = "Everyone is admin!"
+ else:
+ msg = str(self.cfg.admins)
+ elif args[1]=="add":
+ if len(args)!=3:
+ msg = "Usage: add <URI>"
+ else:
+ self.cfg.admins.append(args[2])
+ msg = args[2] + " added as admin"
+ elif args[1]=="del":
+ if len(args)!=3:
+ msg = "Usage: del <URI>"
+ elif args[2] not in self.cfg.admins:
+ msg = args[2] + " is not admin"
+ else:
+ self.cfg.admins.remove(args[2])
+ msg = args[2] + " has been removed from admins"
+ elif args[1]=="rr":
+ msg = "Reregistering.."
+ self.acc.set_registration(True)
+ elif args[1]=="call":
+ if len(args)!=3:
+ msg = "Usage: call <URI>"
+ else:
+ uri = args[2]
+ try:
+ call = self.acc.make_call(uri)
+ except pj.Error, e:
+ msg = "Error: " + str(e)
+ call = None
+
+ if call:
+ if not uri in self.members:
+ m = Member(self, uri)
+ self.members[m.uri] = m
+ else:
+ m = self.members[uri]
+ msg = "Adding " + m.uri + " to voice conference.."
+ m.join_call(call)
+ elif args[1]=="dc" or args[1]=="hold" or args[1]=="update" or args[1]=="reinvite":
+ if len(args)!=3:
+ msg = "Usage: " + args[1] + " <URI>"
+ else:
+ uri = args[2]
+ if not uri in self.members:
+ msg = "Member not found/URI doesn't match (note: case matters!)"
+ else:
+ m = self.members[uri]
+ if m.call:
+ if args[1]=="dc":
+ msg = "Disconnecting.."
+ m.call.hangup(603, "You're disconnected by admin")
+ elif args[1]=="hold":
+ msg = "Holding the call"
+ m.call.hold()
+ elif args[1]=="update":
+ msg = "Sending UPDATE"
+ m.call.update()
+ elif args[1]=="reinvite":
+ msg = "Sending re-INVITE"
+ m.call.reinvite()
+ else:
+ msg = "He is not in call"
+ else:
+ msg = "Unknown admin command " + body
+
+ #print "msg is '%(msg)s'" % {'msg': msg}
+
+ if True:
+ if member:
+ member.send_pager(msg)
+ else:
+ print msg
+
+ def handle_cmd(self, member, from_uri, body):
+ body = body.strip(" \t\r\n")
+ msg = ""
+ handled = True
+ if body=="--l" or body=="--list":
+ msg = self.listmembers()
+ if msg=="":
+ msg = "Nobody is here"
+ elif body[0:3]=="--s":
+ msg = self.showsettings()
+ elif body[0:6]=="--html" and member:
+ if body[8:11]=="off":
+ member.html = False
+ else:
+ member.html = True
+ elif body=="--h" or body=="--help":
+ msg = self.helpstring()
+ elif body=="--leave":
+ if not member or not member.buddy:
+ msg = "You are not in chatroom"
+ else:
+ member.buddy.unsubscribe()
+ elif body[0:3]=="--j":
+ if not from_uri in self.members:
+ m = Member(self, from_uri)
+ self.members[m.uri] = m
+ self.DEBUG("Adding " + m.uri + " to chatroom\n")
+ m.join_chat()
+ else:
+ m = self.members[from_uri]
+ self.DEBUG("Adding " + m.uri + " to chatroom\n")
+ m.join_chat()
+ elif body[0:3]=="--a":
+ self.handle_admin_cmd(member, body)
+ handled = True
+ else:
+ handled = False
+
+ if msg:
+ if member:
+ member.send_pager(msg)
+ elif from_uri:
+ self.acc.send_pager(from_uri, msg);
+ else:
+ print msg
+ return handled
+
+ def on_incoming_call(self, call):
+ self.DEBUG("on_incoming_call from %(uri)s\n" % {'uri': call.info().remote_uri}, INFO)
+ ci = call.info()
+ if not ci.remote_uri in self.members:
+ m = Member(self, ci.remote_uri)
+ self.members[m.uri] = m
+ m.join_call(call)
+ else:
+ m = self.members[ci.remote_uri]
+ m.join_call(call)
+ call.answer(200)
+
+ def on_incoming_subscribe(self, buddy, from_uri, contact_uri, pres_obj):
+ self.DEBUG("on_incoming_subscribe from %(uri)s\n" % from_uri, INFO)
+ return (200, 'OK')
+
+ def on_reg_state(self):
+ ai = self.acc.info()
+ self.DEBUG("Registration state: %(code)d/%(reason)s\n" % \
+ {'code': ai.reg_status, 'reason': ai.reg_reason}, INFO)
+ if ai.reg_status/100==2 and ai.reg_expires > 0:
+ self.acc.set_basic_status(True)
+
+ def on_pager(self, from_uri, contact, mime_type, body):
+ body = body.strip(" \t\r\n")
+ if not self.handle_cmd(None, from_uri, body):
+ self.acc.send_pager(from_uri, "You have not joined the chat room. Type '--join' to join or '--help' for the help")
+
+ def on_pager_status(self, to_uri, body, im_id, code, reason):
+ pass
+
+ def on_typing(self, from_uri, contact, is_typing):
+ pass
+
+
+
+
+##############################################################################
+#
+#
+# main()
+#
+#
+if __name__ == "__main__":
+ bot = Bot()
+ bot.main(CFG_FILE)
+
diff --git a/pjsip-apps/src/confbot/config.py b/pjsip-apps/src/confbot/config.py
new file mode 100644
index 0000000..9dd31b4
--- /dev/null
+++ b/pjsip-apps/src/confbot/config.py
@@ -0,0 +1,41 @@
+# $Id: config.py 2912 2009-08-24 11:56:13Z bennylp $
+#
+# Confbot settings
+#
+import pjsua as pj
+
+# Set of admins. If empty then everyone is admin!
+admins = set([])
+
+# acc_cfg holds the account config (set it to None to disable account)
+acc_cfg = None
+acc_cfg = pj.AccountConfig()
+if acc_cfg:
+ acc_cfg.id = "sip:bot@pjsip.org"
+ acc_cfg.reg_uri = "sip:pjsip.org"
+ acc_cfg.proxy = [ "sip:pjsip.org;lr;transport=tcp" ]
+ acc_cfg.auth_cred = [ pj.AuthCred("*", "bot", "secretpass") ]
+ acc_cfg.publish_enabled = True
+ #acc_cfg.require_timer = True
+
+# Transport configs (set them to None to disable the transport)
+udp_cfg = pj.TransportConfig(5080)
+tcp_cfg = pj.TransportConfig(0)
+#tcp_cfg = None
+
+# Logging Config (you can also set it to None to use default values)
+def log_cb(level, str, len):
+ print str,
+
+log_cfg = pj.LogConfig()
+#log_cfg.callback = log_cb
+
+# UA Config (you can also set it to None to use default values)
+ua_cfg = pj.UAConfig()
+ua_cfg.user_agent = "PJSIP ConfBot"
+ua_cfg.stun_host = "stun.pjsip.org"
+
+# Media config (you can also set it to None to use default values)
+media_cfg = pj.MediaConfig()
+media_cfg.enable_ice = True
+media_cfg.max_calls = 20
diff --git a/pjsip-apps/src/ipjsua/Classes/ConfigViewController.h b/pjsip-apps/src/ipjsua/Classes/ConfigViewController.h
new file mode 100644
index 0000000..7764e65
--- /dev/null
+++ b/pjsip-apps/src/ipjsua/Classes/ConfigViewController.h
@@ -0,0 +1,32 @@
+/* $Id: ConfigViewController.h 3550 2011-05-05 05:33:27Z nanang $ */
+/*
+ * Copyright (C) 2010-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#import <UIKit/UIKit.h>
+
+
+@interface ConfigViewController : UIViewController {
+ IBOutlet UITextView *textView;
+ IBOutlet UIButton *button1;
+ IBOutlet UIButton *button2;
+}
+
+@property (nonatomic, retain) IBOutlet UITextView *textView;
+@property (nonatomic, retain) IBOutlet UIButton *button1;
+@property (nonatomic, retain) IBOutlet UIButton *button2;
+
+@end
diff --git a/pjsip-apps/src/ipjsua/Classes/ConfigViewController.m b/pjsip-apps/src/ipjsua/Classes/ConfigViewController.m
new file mode 100644
index 0000000..686ad44
--- /dev/null
+++ b/pjsip-apps/src/ipjsua/Classes/ConfigViewController.m
@@ -0,0 +1,158 @@
+/* $Id: ConfigViewController.m 3550 2011-05-05 05:33:27Z nanang $ */
+/*
+ * Copyright (C) 2010-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#import "ConfigViewController.h"
+#import "ipjsuaAppDelegate.h"
+
+
+@implementation ConfigViewController
+@synthesize textView;
+@synthesize button1;
+@synthesize button2;
+
+bool kshow = false;
+
+/*
+ // The designated initializer. Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
+- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
+ if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
+ // Custom initialization
+ }
+ return self;
+}
+*/
+
+/*
+// Implement loadView to create a view hierarchy programmatically, without using a nib.
+- (void)loadView {
+}
+*/
+
+- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
+{
+ // Dismiss the keyboard when the view outside the text view is touched.
+ [textView resignFirstResponder];
+ [super touchesBegan:touches withEvent:event];
+}
+
+// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ [textView setFont:[UIFont fontWithName:@"Courier" size:10]];
+ ipjsuaAppDelegate *appd = (ipjsuaAppDelegate *)[[UIApplication sharedApplication] delegate];
+ appd.cfgView = self;
+
+ /* Load config file and display it in the text view */
+ NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
+ NSString *cfgPath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"/config.cfg"];
+ textView.text = [NSMutableString stringWithContentsOfFile:cfgPath encoding:NSASCIIStringEncoding error:NULL];
+
+ /* Add keyboard show/hide notifications so that we can resize the text view */
+ kshow = false;
+ NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
+ [nc addObserver:self selector:@selector(keyboardWillShow:) name: UIKeyboardWillShowNotification object:nil];
+ [nc addObserver:self selector:@selector(keyboardWillHide:) name: UIKeyboardWillHideNotification object:nil];
+
+ /* Add button press event-handlers */
+ [self.button1 addTarget:self action:@selector(button1Pressed:) forControlEvents:(UIControlEvents)UIControlEventTouchDown];
+ [self.button2 addTarget:self action:@selector(button2Pressed:) forControlEvents:(UIControlEvents)UIControlEventTouchDown];
+}
+
+-(void) keyboardWillShow:(NSNotification *) note
+{
+ if (kshow) return;
+
+ /* Shrink the text view area when the keyboard appears */
+ [UIView beginAnimations:nil context:NULL];
+ [UIView setAnimationDuration:0.3];
+ CGRect r = self.textView.frame, t;
+ [[note.userInfo valueForKey:UIKeyboardBoundsUserInfoKey] getValue: &t];
+ r.size.height -= t.size.height - 51;
+ self.textView.frame = r;
+ [UIView commitAnimations];
+ kshow = true;
+
+ [self.button1 setEnabled:true];
+ [self.button1.titleLabel setEnabled:true];
+ [self.button2 setEnabled:true];
+ [self.button2.titleLabel setEnabled:true];
+}
+
+-(void) keyboardWillHide:(NSNotification *) note
+{
+ CGRect r = self.textView.frame, t;
+ [[note.userInfo valueForKey:UIKeyboardBoundsUserInfoKey] getValue: &t];
+ r.size.height += t.size.height - 51;
+ self.textView.frame = r;
+ kshow = false;
+}
+
+- (void)button1Pressed:(id)sender {
+ /* Save the config file */
+ NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
+ NSString *cfgPath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"/config.cfg"];
+ [self.textView.text writeToFile:cfgPath atomically:NO encoding:NSASCIIStringEncoding error:NULL];
+
+ [self.textView resignFirstResponder];
+ [self.button1 setEnabled:false];
+ [self.button1.titleLabel setEnabled:false];
+ [self.button2 setEnabled:false];
+ [self.button2.titleLabel setEnabled:false];
+}
+
+- (void)button2Pressed:(id)sender {
+ /* Reload the config file */
+ NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
+ NSString *cfgPath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"/config.cfg"];
+ self.textView.text = [NSMutableString stringWithContentsOfFile:cfgPath encoding:NSASCIIStringEncoding error:NULL];
+
+ [self.textView resignFirstResponder];
+ [self.button1 setEnabled:false];
+ [self.button1.titleLabel setEnabled:false];
+ [self.button2 setEnabled:false];
+ [self.button2.titleLabel setEnabled:false];
+}
+
+/*
+// Override to allow orientations other than the default portrait orientation.
+- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
+ // Return YES for supported orientations
+ return (interfaceOrientation == UIInterfaceOrientationPortrait);
+}
+*/
+
+- (void)didReceiveMemoryWarning {
+ // Releases the view if it doesn't have a superview.
+ [super didReceiveMemoryWarning];
+
+ // Release any cached data, images, etc that aren't in use.
+}
+
+- (void)viewDidUnload {
+ // Release any retained subviews of the main view.
+ // e.g. self.myOutlet = nil;
+}
+
+
+- (void)dealloc {
+ [super dealloc];
+}
+
+
+@end
diff --git a/pjsip-apps/src/ipjsua/Classes/FirstViewController.h b/pjsip-apps/src/ipjsua/Classes/FirstViewController.h
new file mode 100644
index 0000000..e418a1c
--- /dev/null
+++ b/pjsip-apps/src/ipjsua/Classes/FirstViewController.h
@@ -0,0 +1,37 @@
+/* $Id: FirstViewController.h 3550 2011-05-05 05:33:27Z nanang $ */
+/*
+ * Copyright (C) 2010-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#import <UIKit/UIKit.h>
+
+
+@interface FirstViewController : UIViewController<UITextFieldDelegate> {
+ IBOutlet UITextField *textField;
+ IBOutlet UITextView *textView;
+ IBOutlet UIButton *button1;
+
+ NSString *text;
+ bool hasInput;
+}
+
+@property (nonatomic, retain) IBOutlet UITextField *textField;
+@property (nonatomic, retain) IBOutlet UITextView *textView;
+@property (nonatomic, retain) IBOutlet UIButton *button1;
+@property (nonatomic, retain) NSString *text;
+@property (nonatomic) bool hasInput;
+
+@end
diff --git a/pjsip-apps/src/ipjsua/Classes/FirstViewController.m b/pjsip-apps/src/ipjsua/Classes/FirstViewController.m
new file mode 100644
index 0000000..8edbb05
--- /dev/null
+++ b/pjsip-apps/src/ipjsua/Classes/FirstViewController.m
@@ -0,0 +1,107 @@
+/* $Id: FirstViewController.m 3550 2011-05-05 05:33:27Z nanang $ */
+/*
+ * Copyright (C) 2010-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#import "FirstViewController.h"
+#import "ipjsuaAppDelegate.h"
+
+
+@implementation FirstViewController
+@synthesize textField;
+@synthesize textView;
+@synthesize button1;
+@synthesize text;
+@synthesize hasInput;
+
+- (BOOL)textFieldShouldReturn:(UITextField *)theTextField {
+ // When the user presses return, take focus away from the text field so that the keyboard is dismissed.
+ if (theTextField == textField) {
+ [self.textField resignFirstResponder];
+ self.hasInput = true;
+ self.text = [textField.text stringByAppendingString:@"\n"];
+ textField.text = @"";
+ }
+ return YES;
+}
+
+
+- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
+{
+ // Dismiss the keyboard when the view outside the text field is touched.
+ [textField resignFirstResponder];
+ [super touchesBegan:touches withEvent:event];
+}
+
+/*
+// The designated initializer. Override to perform setup that is required before the view is loaded.
+- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
+ if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
+ // Custom initialization
+ }
+ return self;
+}
+*/
+
+/*
+// Implement loadView to create a view hierarchy programmatically, without using a nib.
+- (void)loadView {
+}
+*/
+
+// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
+
+ ipjsuaAppDelegate *appd = (ipjsuaAppDelegate *)[[UIApplication sharedApplication] delegate];
+ appd.mainView = self;
+ textField.delegate = self;
+ [self.textView setFont:[UIFont fontWithName:@"Courier New" size:8.9]];
+ [self.textField setEnabled: false];
+ [button1 addTarget:self action:@selector(button1Pressed:) forControlEvents:(UIControlEvents)UIControlEventTouchDown];
+}
+
+- (void)button1Pressed:(id)sender {
+ /* Clear the text view */
+ self.textView.text = @"";
+}
+
+// Override to allow orientations other than the default portrait orientation.
+- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
+ // Return YES for supported orientations
+ return (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
+}
+
+- (void)didReceiveMemoryWarning {
+ // Releases the view if it doesn't have a superview.
+ [super didReceiveMemoryWarning];
+
+ // Release any cached data, images, etc that aren't in use.
+}
+
+- (void)viewDidUnload {
+ // Release any retained subviews of the main view.
+ // e.g. self.myOutlet = nil;
+}
+
+
+- (void)dealloc {
+ [super dealloc];
+}
+
+@end
diff --git a/pjsip-apps/src/ipjsua/Classes/TabBarController.h b/pjsip-apps/src/ipjsua/Classes/TabBarController.h
new file mode 100644
index 0000000..d960f99
--- /dev/null
+++ b/pjsip-apps/src/ipjsua/Classes/TabBarController.h
@@ -0,0 +1,26 @@
+/* $Id: TabBarController.h 3550 2011-05-05 05:33:27Z nanang $ */
+/*
+ * Copyright (C) 2010-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#import <UIKit/UIKit.h>
+
+
+@interface TabBarController : UITabBarController {
+
+}
+
+@end
diff --git a/pjsip-apps/src/ipjsua/Classes/TabBarController.m b/pjsip-apps/src/ipjsua/Classes/TabBarController.m
new file mode 100644
index 0000000..96b6279
--- /dev/null
+++ b/pjsip-apps/src/ipjsua/Classes/TabBarController.m
@@ -0,0 +1,30 @@
+/* $Id: TabBarController.m 3550 2011-05-05 05:33:27Z nanang $ */
+/*
+ * Copyright (C) 2010-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#import "TabBarController.h"
+
+
+@implementation TabBarController
+
+// Override to allow orientations other than the default portrait orientation.
+- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
+ // Return YES for supported orientations
+ return (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
+}
+
+@end
diff --git a/pjsip-apps/src/ipjsua/Classes/ipjsuaAppDelegate.h b/pjsip-apps/src/ipjsua/Classes/ipjsuaAppDelegate.h
new file mode 100644
index 0000000..caf2f5d
--- /dev/null
+++ b/pjsip-apps/src/ipjsua/Classes/ipjsuaAppDelegate.h
@@ -0,0 +1,37 @@
+/* $Id: ipjsuaAppDelegate.h 3550 2011-05-05 05:33:27Z nanang $ */
+/*
+ * Copyright (C) 2010-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#import <UIKit/UIKit.h>
+#import "ConfigViewController.h"
+#import "FirstViewController.h"
+#import "TabBarController.h"
+
+@interface ipjsuaAppDelegate : NSObject <UIApplicationDelegate, UITabBarControllerDelegate> {
+ UIWindow *window;
+ ConfigViewController *cfgView;
+ FirstViewController *mainView;
+ TabBarController *tabBarController;
+}
+
+@property (nonatomic, retain) IBOutlet UIWindow *window;
+@property (nonatomic, retain) IBOutlet TabBarController *tabBarController;
+@property (nonatomic, retain) IBOutlet ConfigViewController *cfgView;
+@property (nonatomic, retain) FirstViewController *mainView;
+
+
+@end
diff --git a/pjsip-apps/src/ipjsua/Classes/ipjsuaAppDelegate.m b/pjsip-apps/src/ipjsua/Classes/ipjsuaAppDelegate.m
new file mode 100644
index 0000000..c60084d
--- /dev/null
+++ b/pjsip-apps/src/ipjsua/Classes/ipjsuaAppDelegate.m
@@ -0,0 +1,252 @@
+/* $Id: ipjsuaAppDelegate.m 3550 2011-05-05 05:33:27Z nanang $ */
+/*
+ * Copyright (C) 2010-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#import <pjlib.h>
+#import <pjsua.h>
+#import "ipjsuaAppDelegate.h"
+
+extern pj_log_func *log_cb;
+
+@implementation ipjsuaAppDelegate
+@synthesize window;
+@synthesize tabBarController;
+@synthesize mainView;
+@synthesize cfgView;
+
+/* Sleep interval duration */
+#define SLEEP_INTERVAL 0.5
+/* Determine whether we should print the messages in the debugger
+ * console as well
+ */
+#define DEBUGGER_PRINT 1
+/* Whether we should show pj log messages in the text area */
+#define SHOW_LOG 1
+#define PATH_LENGTH PJ_MAXPATH
+#define KEEP_ALIVE_INTERVAL 600
+
+extern pj_bool_t app_restart;
+
+char argv_buf[PATH_LENGTH];
+char *argv[] = {"", "--config-file", argv_buf};
+
+ipjsuaAppDelegate *app;
+
+bool app_running;
+bool thread_quit;
+NSMutableString *mstr;
+pj_thread_desc a_thread_desc;
+pj_thread_t *a_thread;
+pjsua_call_id ccall_id;
+
+pj_status_t app_init(int argc, char *argv[]);
+pj_status_t app_main(void);
+pj_status_t app_destroy(void);
+void keepAliveFunction(int timeout);
+
+void showMsg(const char *format, ...)
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ va_list arg;
+
+ va_start(arg, format);
+ NSString *str = [[NSString alloc] initWithFormat:[NSString stringWithFormat:@"%s", format] arguments: arg];
+#if DEBUGGER_PRINT
+ NSLog(@"%@", str);
+#endif
+ va_end(arg);
+
+ [mstr appendString:str];
+ [pool release];
+}
+
+char * getInput(char *s, int n, FILE *stream)
+{
+ if (stream != stdin) {
+ return fgets(s, n, stream);
+ }
+
+ app.mainView.hasInput = false;
+ [app.mainView.textField setEnabled: true];
+ [app performSelectorOnMainThread:@selector(displayMsg:) withObject:mstr waitUntilDone:YES];
+ [mstr setString:@""];
+
+ while (!thread_quit && !app.mainView.hasInput) {
+ int ctr = 0;
+ [NSThread sleepForTimeInterval:SLEEP_INTERVAL];
+ if (ctr == 4) {
+ [app performSelectorOnMainThread:@selector(displayMsg:) withObject:mstr waitUntilDone:YES];
+ [mstr setString:@""];
+ ctr = 0;
+ }
+ ctr++;
+ }
+
+ [app.mainView.text getCString:s maxLength:n encoding:NSASCIIStringEncoding];
+ [app.mainView.textField setEnabled: false];
+ [app performSelectorOnMainThread:@selector(displayMsg:) withObject:app.mainView.text waitUntilDone:NO];
+
+ return s;
+}
+
+void showLog(int level, const char *data, int len)
+{
+ showMsg("%s", data);
+}
+
+pj_bool_t showNotification(pjsua_call_id call_id)
+{
+#ifdef __IPHONE_4_0
+ ccall_id = call_id;
+
+ // Create a new notification
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ UILocalNotification* alert = [[[UILocalNotification alloc] init] autorelease];
+ if (alert)
+ {
+ alert.repeatInterval = 0;
+ alert.alertBody = @"Incoming call received...";
+ alert.alertAction = @"Answer";
+
+ [[UIApplication sharedApplication] presentLocalNotificationNow:alert];
+ }
+
+ [pool release];
+
+ return PJ_FALSE;
+#else
+ return PJ_TRUE;
+#endif
+}
+
+- (void)answer_call {
+ if (!pj_thread_is_registered())
+ {
+ pj_thread_register("ipjsua", a_thread_desc, &a_thread);
+ }
+ pjsua_call_answer(ccall_id, 200, NULL, NULL);
+}
+
+#ifdef __IPHONE_4_0
+- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
+ [app performSelectorOnMainThread:@selector(answer_call) withObject:nil waitUntilDone:YES];
+}
+
+- (void)keepAlive {
+ if (!pj_thread_is_registered())
+ {
+ pj_thread_register("ipjsua", a_thread_desc, &a_thread);
+ }
+ keepAliveFunction(KEEP_ALIVE_INTERVAL);
+}
+
+- (void)applicationDidEnterBackground:(UIApplication *)application
+{
+ [app performSelectorOnMainThread:@selector(keepAlive) withObject:nil waitUntilDone:YES];
+ [application setKeepAliveTimeout:KEEP_ALIVE_INTERVAL handler: ^{
+ [app performSelectorOnMainThread:@selector(keepAlive) withObject:nil waitUntilDone:YES];
+ }];
+}
+
+#endif
+
+- (void)start_app {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ /* Wait until the view is ready */
+ while (self.mainView == nil) {
+ [NSThread sleepForTimeInterval:SLEEP_INTERVAL];
+ }
+
+ [NSThread setThreadPriority:1.0];
+ mstr = [NSMutableString stringWithCapacity:4196];
+#if SHOW_LOG
+ pj_log_set_log_func(&showLog);
+ log_cb = &showLog;
+#endif
+
+ do {
+ app_restart = PJ_FALSE;
+ if (app_init(3, argv) != PJ_SUCCESS) {
+ NSString *str = @"Failed to initialize pjsua\n";
+ [app performSelectorOnMainThread:@selector(displayMsg:) withObject:str waitUntilDone:YES];
+ } else {
+ app_running = true;
+ app_main();
+
+ app_destroy();
+ /* This is on purpose */
+ app_destroy();
+ }
+
+ [app performSelectorOnMainThread:@selector(displayMsg:) withObject:mstr waitUntilDone:YES];
+ [mstr setString:@""];
+ } while (app_restart);
+
+ [pool release];
+}
+
+- (void)displayMsg:(NSString *)str {
+ self.mainView.textView.text = [self.mainView.textView.text stringByAppendingString:str];
+ [self.mainView.textView scrollRangeToVisible:NSMakeRange([self.mainView.textView.text length] - 1, 1)];
+}
+
+- (void)applicationDidFinishLaunching:(UIApplication *)application {
+ /* If there is no config file in the document dir, copy the default config file into the directory */
+ NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
+ NSString *cfgPath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"/config.cfg"];
+ if (![[NSFileManager defaultManager] fileExistsAtPath:cfgPath]) {
+ NSString *resPath = [[NSBundle mainBundle] pathForResource:@"config" ofType:@"cfg"];
+ NSString *cfg = [NSString stringWithContentsOfFile:resPath encoding:NSASCIIStringEncoding error:NULL];
+ [cfg writeToFile:cfgPath atomically:NO encoding:NSASCIIStringEncoding error:NULL];
+ }
+ [cfgPath getCString:argv[2] maxLength:PATH_LENGTH encoding:NSASCIIStringEncoding];
+
+ // Add the tab bar controller's current view as a subview of the window
+ [window addSubview:tabBarController.view];
+ [window makeKeyAndVisible];
+
+ app = self;
+ app_running = false;
+ thread_quit = false;
+ /* Start pjsua thread */
+ [NSThread detachNewThreadSelector:@selector(start_app) toTarget:self withObject:nil];
+}
+
+/*
+// Optional UITabBarControllerDelegate method
+- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
+}
+*/
+
+/*
+// Optional UITabBarControllerDelegate method
+- (void)tabBarController:(UITabBarController *)tabBarController didEndCustomizingViewControllers:(NSArray *)viewControllers changed:(BOOL)changed {
+}
+*/
+
+
+- (void)dealloc {
+ thread_quit = true;
+ [NSThread sleepForTimeInterval:SLEEP_INTERVAL];
+
+ [tabBarController release];
+ [window release];
+ [super dealloc];
+}
+
+@end
+
diff --git a/pjsip-apps/src/ipjsua/MainWindow.xib b/pjsip-apps/src/ipjsua/MainWindow.xib
new file mode 100644
index 0000000..dfdc90f
--- /dev/null
+++ b/pjsip-apps/src/ipjsua/MainWindow.xib
@@ -0,0 +1,780 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="7.10">
+ <data>
+ <int key="IBDocument.SystemTarget">784</int>
+ <string key="IBDocument.SystemVersion">10C540</string>
+ <string key="IBDocument.InterfaceBuilderVersion">740</string>
+ <string key="IBDocument.AppKitVersion">1038.25</string>
+ <string key="IBDocument.HIToolboxVersion">458.00</string>
+ <object class="NSMutableDictionary" key="IBDocument.PluginVersions">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string key="NS.object.0">62</string>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <integer value="106"/>
+ </object>
+ <object class="NSArray" key="IBDocument.PluginDependencies">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.Metadata">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys" id="0">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBProxyObject" id="841351856">
+ <string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
+ </object>
+ <object class="IBProxyObject" id="532797962">
+ <string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
+ </object>
+ <object class="IBUICustomObject" id="664661524"/>
+ <object class="IBUIWindow" id="380026005">
+ <nil key="NSNextResponder"/>
+ <int key="NSvFlags">1316</int>
+ <object class="NSPSMatrix" key="NSFrameMatrix"/>
+ <string key="NSFrameSize">{320, 480}</string>
+ <object class="NSColor" key="IBUIBackgroundColor">
+ <int key="NSColorSpace">1</int>
+ <bytes key="NSRGB">MSAxIDEAA</bytes>
+ </object>
+ <bool key="IBUIOpaque">NO</bool>
+ <bool key="IBUIClearsContextBeforeDrawing">NO</bool>
+ <object class="IBUISimulatedStatusBarMetrics" key="IBUISimulatedStatusBarMetrics"/>
+ <bool key="IBUIVisibleAtLaunch">YES</bool>
+ </object>
+ <object class="IBUITabBarController" id="1034742383">
+ <object class="IBUISimulatedTabBarMetrics" key="IBUISimulatedBottomBarMetrics"/>
+ <object class="IBUISimulatedNavigationBarMetrics" key="IBUISimulatedTopBarMetrics">
+ <int key="IBUIBarStyle">2</int>
+ <bool key="IBUIPrompted">NO</bool>
+ </object>
+ <object class="IBUISimulatedStatusBarMetrics" key="IBUISimulatedStatusBarMetrics">
+ <int key="IBUIStatusBarStyle">2</int>
+ </object>
+ <bool key="IBUIHorizontal">YES</bool>
+ <object class="IBUIViewController" key="IBUISelectedViewController" id="1024858337">
+ <object class="IBUIView" key="IBUIView" id="434903890">
+ <reference key="NSNextResponder"/>
+ <int key="NSvFlags">274</int>
+ <object class="NSMutableArray" key="NSSubviews">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBUITextView" id="876077251">
+ <reference key="NSNextResponder" ref="434903890"/>
+ <int key="NSvFlags">306</int>
+ <string key="NSFrame">{{0, 34}, {480, 217}}</string>
+ <reference key="NSSuperview" ref="434903890"/>
+ <object class="NSColor" key="IBUIBackgroundColor">
+ <int key="NSColorSpace">1</int>
+ <bytes key="NSRGB">MC45ODE5Mjc3MTA4IDAuOTYzODU1NDIxNyAxIDAAA</bytes>
+ </object>
+ <bool key="IBUIOpaque">NO</bool>
+ <bool key="IBUIClipsSubviews">YES</bool>
+ <bool key="IBUIMultipleTouchEnabled">YES</bool>
+ <bool key="IBUIDelaysContentTouches">NO</bool>
+ <bool key="IBUICanCancelContentTouches">NO</bool>
+ <float key="IBUIMinimumZoomScale">0.0</float>
+ <float key="IBUIMaximumZoomScale">0.0</float>
+ <bool key="IBUIBouncesZoom">NO</bool>
+ <bool key="IBUIEditable">NO</bool>
+ <string key="IBUIText"/>
+ <object class="IBUITextInputTraits" key="IBUITextInputTraits"/>
+ </object>
+ <object class="IBUITextField" id="625972407">
+ <reference key="NSNextResponder" ref="434903890"/>
+ <int key="NSvFlags">292</int>
+ <string key="NSFrame">{{7, 0}, {323, 31}}</string>
+ <reference key="NSSuperview" ref="434903890"/>
+ <bool key="IBUIOpaque">NO</bool>
+ <bool key="IBUIClearsContextBeforeDrawing">NO</bool>
+ <int key="IBUIContentVerticalAlignment">0</int>
+ <string key="IBUIText"/>
+ <int key="IBUIBorderStyle">3</int>
+ <string key="IBUIPlaceholder">Insert command here</string>
+ <object class="NSColor" key="IBUITextColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MAA</bytes>
+ <object class="NSColorSpace" key="NSCustomColorSpace">
+ <int key="NSID">2</int>
+ </object>
+ </object>
+ <bool key="IBUIAdjustsFontSizeToFit">YES</bool>
+ <float key="IBUIMinimumFontSize">17</float>
+ <object class="IBUITextInputTraits" key="IBUITextInputTraits">
+ <int key="IBUIAutocorrectionType">1</int>
+ <int key="IBUIKeyboardType">1</int>
+ <int key="IBUIReturnKeyType">1</int>
+ </object>
+ <int key="IBUIClearButtonMode">1</int>
+ </object>
+ <object class="IBUIButton" id="808516100">
+ <reference key="NSNextResponder" ref="434903890"/>
+ <int key="NSvFlags">292</int>
+ <string key="NSFrame">{{351, 0}, {90, 32}}</string>
+ <reference key="NSSuperview" ref="434903890"/>
+ <bool key="IBUIOpaque">NO</bool>
+ <bool key="IBUIClearsContextBeforeDrawing">NO</bool>
+ <int key="IBUIContentHorizontalAlignment">0</int>
+ <int key="IBUIContentVerticalAlignment">0</int>
+ <object class="NSFont" key="IBUIFont">
+ <string key="NSName">Helvetica-Bold</string>
+ <double key="NSSize">15</double>
+ <int key="NSfFlags">16</int>
+ </object>
+ <int key="IBUIButtonType">1</int>
+ <string key="IBUINormalTitle">Clear view</string>
+ <object class="NSColor" key="IBUIHighlightedTitleColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MQA</bytes>
+ </object>
+ <object class="NSColor" key="IBUINormalTitleColor">
+ <int key="NSColorSpace">1</int>
+ <bytes key="NSRGB">MC4xOTYwNzg0MyAwLjMwOTgwMzkzIDAuNTIxNTY4NjYAA</bytes>
+ </object>
+ <object class="NSColor" key="IBUINormalTitleShadowColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MC41AA</bytes>
+ </object>
+ </object>
+ </object>
+ <string key="NSFrameSize">{480, 251}</string>
+ <reference key="NSSuperview"/>
+ <object class="NSColor" key="IBUIBackgroundColor">
+ <int key="NSColorSpace">1</int>
+ <bytes key="NSRGB">MC42NDQxOTgyNzA4IDAuNzgwNDMyODUxOSAwLjg2NDEzMDQzNDgAA</bytes>
+ </object>
+ <bool key="IBUIClearsContextBeforeDrawing">NO</bool>
+ </object>
+ <object class="IBUITabBarItem" key="IBUITabBarItem" id="765670903">
+ <string key="IBUITitle">ipjsua</string>
+ <reference key="IBUITabBar"/>
+ </object>
+ <reference key="IBUIParentViewController" ref="1034742383"/>
+ </object>
+ <object class="NSMutableArray" key="IBUIViewControllers">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="1024858337"/>
+ <object class="IBUIViewController" id="268481961">
+ <object class="IBUITabBarItem" key="IBUITabBarItem" id="807309489">
+ <string key="IBUITitle">Config</string>
+ <reference key="IBUITabBar"/>
+ </object>
+ <reference key="IBUIParentViewController" ref="1034742383"/>
+ <string key="IBUINibName">SecondView</string>
+ </object>
+ </object>
+ <object class="IBUITabBar" key="IBUITabBar" id="795333663">
+ <nil key="NSNextResponder"/>
+ <int key="NSvFlags">266</int>
+ <string key="NSFrame">{{129, 330}, {163, 49}}</string>
+ <object class="NSColor" key="IBUIBackgroundColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MCAwAA</bytes>
+ </object>
+ <bool key="IBUIClearsContextBeforeDrawing">NO</bool>
+ </object>
+ </object>
+ </object>
+ <object class="IBObjectContainer" key="IBDocument.Objects">
+ <object class="NSMutableArray" key="connectionRecords">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">window</string>
+ <reference key="source" ref="664661524"/>
+ <reference key="destination" ref="380026005"/>
+ </object>
+ <int key="connectionID">9</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">delegate</string>
+ <reference key="source" ref="841351856"/>
+ <reference key="destination" ref="664661524"/>
+ </object>
+ <int key="connectionID">99</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">tabBarController</string>
+ <reference key="source" ref="664661524"/>
+ <reference key="destination" ref="1034742383"/>
+ </object>
+ <int key="connectionID">113</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">textField</string>
+ <reference key="source" ref="1024858337"/>
+ <reference key="destination" ref="625972407"/>
+ </object>
+ <int key="connectionID">129</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">textView</string>
+ <reference key="source" ref="1024858337"/>
+ <reference key="destination" ref="876077251"/>
+ </object>
+ <int key="connectionID">135</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">delegate</string>
+ <reference key="source" ref="1034742383"/>
+ <reference key="destination" ref="664661524"/>
+ </object>
+ <int key="connectionID">136</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">button1</string>
+ <reference key="source" ref="1024858337"/>
+ <reference key="destination" ref="808516100"/>
+ </object>
+ <int key="connectionID">140</int>
+ </object>
+ </object>
+ <object class="IBMutableOrderedSet" key="objectRecords">
+ <object class="NSArray" key="orderedObjects">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBObjectRecord">
+ <int key="objectID">0</int>
+ <reference key="object" ref="0"/>
+ <reference key="children" ref="1000"/>
+ <nil key="parent"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">2</int>
+ <reference key="object" ref="380026005"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-1</int>
+ <reference key="object" ref="841351856"/>
+ <reference key="parent" ref="0"/>
+ <string key="objectName">File's Owner</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">3</int>
+ <reference key="object" ref="664661524"/>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">106</int>
+ <reference key="object" ref="1034742383"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="795333663"/>
+ <reference ref="1024858337"/>
+ <reference ref="268481961"/>
+ </object>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">107</int>
+ <reference key="object" ref="795333663"/>
+ <reference key="parent" ref="1034742383"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">108</int>
+ <reference key="object" ref="1024858337"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="765670903"/>
+ <reference ref="434903890"/>
+ </object>
+ <reference key="parent" ref="1034742383"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">109</int>
+ <reference key="object" ref="268481961"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="807309489"/>
+ </object>
+ <reference key="parent" ref="1034742383"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">110</int>
+ <reference key="object" ref="807309489"/>
+ <reference key="parent" ref="268481961"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">111</int>
+ <reference key="object" ref="765670903"/>
+ <reference key="parent" ref="1024858337"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-2</int>
+ <reference key="object" ref="532797962"/>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">119</int>
+ <reference key="object" ref="434903890"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="625972407"/>
+ <reference ref="876077251"/>
+ <reference ref="808516100"/>
+ </object>
+ <reference key="parent" ref="1024858337"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">123</int>
+ <reference key="object" ref="876077251"/>
+ <reference key="parent" ref="434903890"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">126</int>
+ <reference key="object" ref="625972407"/>
+ <reference key="parent" ref="434903890"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">139</int>
+ <reference key="object" ref="808516100"/>
+ <reference key="parent" ref="434903890"/>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="flattenedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>-1.CustomClassName</string>
+ <string>-2.CustomClassName</string>
+ <string>106.CustomClassName</string>
+ <string>106.IBEditorWindowLastContentRect</string>
+ <string>106.IBPluginDependency</string>
+ <string>107.IBPluginDependency</string>
+ <string>108.CustomClassName</string>
+ <string>108.IBPluginDependency</string>
+ <string>109.CustomClassName</string>
+ <string>109.IBPluginDependency</string>
+ <string>110.IBPluginDependency</string>
+ <string>111.IBPluginDependency</string>
+ <string>119.IBPluginDependency</string>
+ <string>123.IBPluginDependency</string>
+ <string>126.IBPluginDependency</string>
+ <string>139.IBPluginDependency</string>
+ <string>2.IBAttributePlaceholdersKey</string>
+ <string>2.IBEditorWindowLastContentRect</string>
+ <string>2.IBPluginDependency</string>
+ <string>3.CustomClassName</string>
+ <string>3.IBPluginDependency</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>UIApplication</string>
+ <string>UIResponder</string>
+ <string>TabBarController</string>
+ <string>{{702, 231}, {480, 320}}</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>FirstViewController</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>ConfigViewController</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <object class="NSMutableDictionary">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <string>{{229, 373}, {320, 480}}</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>ipjsuaAppDelegate</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="unlocalizedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="activeLocalization"/>
+ <object class="NSMutableDictionary" key="localizations">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="sourceID"/>
+ <int key="maxID">140</int>
+ </object>
+ <object class="IBClassDescriber" key="IBDocument.Classes">
+ <object class="NSMutableArray" key="referencedPartialClassDescriptions">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBPartialClassDescription">
+ <string key="className">ConfigViewController</string>
+ <string key="superclassName">UIViewController</string>
+ <object class="NSMutableDictionary" key="outlets">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>button1</string>
+ <string>button2</string>
+ <string>textView</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>UIButton</string>
+ <string>UIButton</string>
+ <string>UITextView</string>
+ </object>
+ </object>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">Classes/ConfigViewController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">FirstViewController</string>
+ <string key="superclassName">UIViewController</string>
+ <object class="NSMutableDictionary" key="outlets">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>button1</string>
+ <string>textField</string>
+ <string>textView</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>UIButton</string>
+ <string>UITextField</string>
+ <string>UITextView</string>
+ </object>
+ </object>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">Classes/FirstViewController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">TabBarController</string>
+ <string key="superclassName">UITabBarController</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">Classes/TabBarController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">ipjsuaAppDelegate</string>
+ <string key="superclassName">NSObject</string>
+ <object class="NSMutableDictionary" key="outlets">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>cfgView</string>
+ <string>tabBarController</string>
+ <string>window</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>ConfigViewController</string>
+ <string>TabBarController</string>
+ <string>UIWindow</string>
+ </object>
+ </object>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">Classes/ipjsuaAppDelegate.h</string>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSError.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSFileManager.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSKeyValueCoding.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSKeyValueObserving.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSKeyedArchiver.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSNetServices.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSObject.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSPort.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSRunLoop.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSStream.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSThread.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSURL.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSURLConnection.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSXMLParser.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIAccessibility.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UINibLoading.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier" id="539560514">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIResponder.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIApplication</string>
+ <string key="superclassName">UIResponder</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIApplication.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIBarItem</string>
+ <string key="superclassName">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIBarItem.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIButton</string>
+ <string key="superclassName">UIControl</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIButton.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIControl</string>
+ <string key="superclassName">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIControl.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIResponder</string>
+ <string key="superclassName">NSObject</string>
+ <reference key="sourceIdentifier" ref="539560514"/>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIScrollView</string>
+ <string key="superclassName">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIScrollView.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UISearchBar</string>
+ <string key="superclassName">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UISearchBar.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UISearchDisplayController</string>
+ <string key="superclassName">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UISearchDisplayController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UITabBar</string>
+ <string key="superclassName">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UITabBar.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UITabBarController</string>
+ <string key="superclassName">UIViewController</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier" id="53818940">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UITabBarController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UITabBarItem</string>
+ <string key="superclassName">UIBarItem</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UITabBarItem.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UITextField</string>
+ <string key="superclassName">UIControl</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier" id="1015289008">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UITextField.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UITextView</string>
+ <string key="superclassName">UIScrollView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UITextView.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIView</string>
+ <reference key="sourceIdentifier" ref="1015289008"/>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIView</string>
+ <string key="superclassName">UIResponder</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIView.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIViewController</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UINavigationController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIViewController</string>
+ <reference key="sourceIdentifier" ref="53818940"/>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIViewController</string>
+ <string key="superclassName">UIResponder</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIViewController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIWindow</string>
+ <string key="superclassName">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIWindow.h</string>
+ </object>
+ </object>
+ </object>
+ </object>
+ <int key="IBDocument.localizationMode">0</int>
+ <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3</string>
+ <integer value="3100" key="NS.object.0"/>
+ </object>
+ <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
+ <string key="IBDocument.LastKnownRelativeProjectPath">ipjsua.xcodeproj</string>
+ <int key="IBDocument.defaultPropertyAccessControl">3</int>
+ <string key="IBCocoaTouchPluginVersion">3.1</string>
+ </data>
+</archive>
diff --git a/pjsip-apps/src/ipjsua/Resources-iPad/MainWindow-iPad.xib b/pjsip-apps/src/ipjsua/Resources-iPad/MainWindow-iPad.xib
new file mode 100644
index 0000000..ca7f70a
--- /dev/null
+++ b/pjsip-apps/src/ipjsua/Resources-iPad/MainWindow-iPad.xib
@@ -0,0 +1,913 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.CocoaTouch.iPad.XIB" version="7.10">
+ <data>
+ <int key="IBDocument.SystemTarget">800</int>
+ <string key="IBDocument.SystemVersion">10C540</string>
+ <string key="IBDocument.InterfaceBuilderVersion">788</string>
+ <string key="IBDocument.AppKitVersion">1038.25</string>
+ <string key="IBDocument.HIToolboxVersion">458.00</string>
+ <object class="NSMutableDictionary" key="IBDocument.PluginVersions">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string key="NS.object.0">117</string>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <integer value="109"/>
+ </object>
+ <object class="NSArray" key="IBDocument.PluginDependencies">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.Metadata">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys" id="0">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBProxyObject" id="841351856">
+ <string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
+ <string key="targetRuntimeIdentifier">IBIPadFramework</string>
+ </object>
+ <object class="IBProxyObject" id="532797962">
+ <string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
+ <string key="targetRuntimeIdentifier">IBIPadFramework</string>
+ </object>
+ <object class="IBUICustomObject" id="664661524">
+ <string key="targetRuntimeIdentifier">IBIPadFramework</string>
+ </object>
+ <object class="IBUIWindow" id="380026005">
+ <nil key="NSNextResponder"/>
+ <int key="NSvFlags">1316</int>
+ <object class="NSPSMatrix" key="NSFrameMatrix"/>
+ <string key="NSFrameSize">{768, 1024}</string>
+ <object class="NSColor" key="IBUIBackgroundColor">
+ <int key="NSColorSpace">1</int>
+ <bytes key="NSRGB">MSAxIDEAA</bytes>
+ </object>
+ <bool key="IBUIOpaque">NO</bool>
+ <bool key="IBUIClearsContextBeforeDrawing">NO</bool>
+ <object class="IBUISimulatedStatusBarMetrics" key="IBUISimulatedStatusBarMetrics">
+ <int key="IBUIStatusBarStyle">2</int>
+ </object>
+ <string key="targetRuntimeIdentifier">IBIPadFramework</string>
+ <bool key="IBUIVisibleAtLaunch">YES</bool>
+ <bool key="IBUIResizesToFullScreen">YES</bool>
+ </object>
+ <object class="IBUITabBarController" id="1034742383">
+ <object class="IBUISimulatedTabBarMetrics" key="IBUISimulatedBottomBarMetrics"/>
+ <object class="IBUISimulatedNavigationBarMetrics" key="IBUISimulatedTopBarMetrics">
+ <int key="IBUIBarStyle">2</int>
+ <bool key="IBUIPrompted">NO</bool>
+ </object>
+ <object class="IBUISimulatedStatusBarMetrics" key="IBUISimulatedStatusBarMetrics">
+ <int key="IBUIStatusBarStyle">2</int>
+ </object>
+ <object class="IBUISimulatedOrientationMetrics" key="IBUISimulatedOrientationMetrics">
+ <int key="interfaceOrientation">3</int>
+ </object>
+ <string key="targetRuntimeIdentifier">IBIPadFramework</string>
+ <bool key="IBUIHorizontal">YES</bool>
+ <object class="IBUIViewController" key="IBUISelectedViewController" id="268481961">
+ <object class="IBUITabBarItem" key="IBUITabBarItem" id="807309489">
+ <string key="IBUITitle">Config</string>
+ <string key="targetRuntimeIdentifier">IBIPadFramework</string>
+ <reference key="IBUITabBar"/>
+ </object>
+ <reference key="IBUIParentViewController" ref="1034742383"/>
+ <string key="IBUINibName">SecondView-iPad</string>
+ <object class="IBUISimulatedOrientationMetrics" key="IBUISimulatedOrientationMetrics">
+ <int key="interfaceOrientation">1</int>
+ </object>
+ <string key="targetRuntimeIdentifier">IBIPadFramework</string>
+ <bool key="IBUIHorizontal">NO</bool>
+ </object>
+ <object class="NSMutableArray" key="IBUIViewControllers">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBUIViewController" id="1024858337">
+ <object class="IBUIView" key="IBUIView" id="434903890">
+ <nil key="NSNextResponder"/>
+ <int key="NSvFlags">274</int>
+ <object class="NSMutableArray" key="NSSubviews">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBUITextView" id="876077251">
+ <reference key="NSNextResponder" ref="434903890"/>
+ <int key="NSvFlags">306</int>
+ <string key="NSFrame">{{8, 57}, {1001, 622}}</string>
+ <reference key="NSSuperview" ref="434903890"/>
+ <object class="NSColor" key="IBUIBackgroundColor">
+ <int key="NSColorSpace">1</int>
+ <bytes key="NSRGB">MC45ODE5Mjc3MTA4IDAuOTYzODU1NDIxNyAxIDAAA</bytes>
+ </object>
+ <bool key="IBUIOpaque">NO</bool>
+ <bool key="IBUIClipsSubviews">YES</bool>
+ <bool key="IBUIMultipleTouchEnabled">YES</bool>
+ <string key="targetRuntimeIdentifier">IBIPadFramework</string>
+ <bool key="IBUIDelaysContentTouches">NO</bool>
+ <bool key="IBUICanCancelContentTouches">NO</bool>
+ <float key="IBUIMinimumZoomScale">0.0</float>
+ <float key="IBUIMaximumZoomScale">0.0</float>
+ <bool key="IBUIBouncesZoom">NO</bool>
+ <bool key="IBUIEditable">NO</bool>
+ <string key="IBUIText"/>
+ <object class="IBUITextInputTraits" key="IBUITextInputTraits">
+ <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+ </object>
+ </object>
+ <object class="IBUITextField" id="625972407">
+ <reference key="NSNextResponder" ref="434903890"/>
+ <int key="NSvFlags">292</int>
+ <string key="NSFrame">{{8, 8}, {844, 31}}</string>
+ <reference key="NSSuperview" ref="434903890"/>
+ <bool key="IBUIOpaque">NO</bool>
+ <bool key="IBUIClearsContextBeforeDrawing">NO</bool>
+ <string key="targetRuntimeIdentifier">IBIPadFramework</string>
+ <int key="IBUIContentVerticalAlignment">0</int>
+ <string key="IBUIText"/>
+ <int key="IBUIBorderStyle">3</int>
+ <string key="IBUIPlaceholder">Insert command here</string>
+ <object class="NSColor" key="IBUITextColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MAA</bytes>
+ <object class="NSColorSpace" key="NSCustomColorSpace">
+ <int key="NSID">2</int>
+ </object>
+ </object>
+ <bool key="IBUIAdjustsFontSizeToFit">YES</bool>
+ <float key="IBUIMinimumFontSize">17</float>
+ <object class="IBUITextInputTraits" key="IBUITextInputTraits">
+ <int key="IBUIAutocorrectionType">1</int>
+ <int key="IBUIKeyboardType">1</int>
+ <int key="IBUIReturnKeyType">1</int>
+ <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+ </object>
+ <int key="IBUIClearButtonMode">1</int>
+ </object>
+ <object class="IBUIButton" id="808516100">
+ <reference key="NSNextResponder" ref="434903890"/>
+ <int key="NSvFlags">292</int>
+ <string key="NSFrame">{{882, 7}, {127, 32}}</string>
+ <reference key="NSSuperview" ref="434903890"/>
+ <bool key="IBUIOpaque">NO</bool>
+ <bool key="IBUIClearsContextBeforeDrawing">NO</bool>
+ <string key="targetRuntimeIdentifier">IBIPadFramework</string>
+ <int key="IBUIContentHorizontalAlignment">0</int>
+ <int key="IBUIContentVerticalAlignment">0</int>
+ <object class="NSFont" key="IBUIFont">
+ <string key="NSName">Helvetica-Bold</string>
+ <double key="NSSize">15</double>
+ <int key="NSfFlags">16</int>
+ </object>
+ <int key="IBUIButtonType">1</int>
+ <string key="IBUINormalTitle">Clear view</string>
+ <object class="NSColor" key="IBUIHighlightedTitleColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MQA</bytes>
+ </object>
+ <object class="NSColor" key="IBUINormalTitleColor">
+ <int key="NSColorSpace">1</int>
+ <bytes key="NSRGB">MC4xOTYwNzg0MyAwLjMwOTgwMzkzIDAuNTIxNTY4NjYAA</bytes>
+ </object>
+ <object class="NSColor" key="IBUINormalTitleShadowColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MC41AA</bytes>
+ </object>
+ </object>
+ </object>
+ <string key="NSFrameSize">{1024, 699}</string>
+ <object class="NSColor" key="IBUIBackgroundColor">
+ <int key="NSColorSpace">1</int>
+ <bytes key="NSRGB">MC42NDQxOTgyNzA4IDAuNzgwNDMyODUxOSAwLjg2NDEzMDQzNDgAA</bytes>
+ </object>
+ <bool key="IBUIClearsContextBeforeDrawing">NO</bool>
+ <string key="targetRuntimeIdentifier">IBIPadFramework</string>
+ </object>
+ <object class="IBUITabBarItem" key="IBUITabBarItem" id="765670903">
+ <string key="IBUITitle">ipjsua</string>
+ <string key="targetRuntimeIdentifier">IBIPadFramework</string>
+ <reference key="IBUITabBar"/>
+ </object>
+ <reference key="IBUIParentViewController" ref="1034742383"/>
+ <object class="IBUISimulatedOrientationMetrics" key="IBUISimulatedOrientationMetrics">
+ <int key="interfaceOrientation">1</int>
+ </object>
+ <string key="targetRuntimeIdentifier">IBIPadFramework</string>
+ <bool key="IBUIHorizontal">NO</bool>
+ </object>
+ <reference ref="268481961"/>
+ </object>
+ <object class="IBUITabBar" key="IBUITabBar" id="795333663">
+ <nil key="NSNextResponder"/>
+ <int key="NSvFlags">266</int>
+ <string key="NSFrame">{{129, 330}, {163, 49}}</string>
+ <object class="NSColor" key="IBUIBackgroundColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MCAwAA</bytes>
+ </object>
+ <bool key="IBUIClearsContextBeforeDrawing">NO</bool>
+ <string key="IBUIContentStretch">{{1.38778e-17, 0}, {1, 1}}</string>
+ <string key="targetRuntimeIdentifier">IBIPadFramework</string>
+ </object>
+ </object>
+ </object>
+ <object class="IBObjectContainer" key="IBDocument.Objects">
+ <object class="NSMutableArray" key="connectionRecords">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">window</string>
+ <reference key="source" ref="664661524"/>
+ <reference key="destination" ref="380026005"/>
+ </object>
+ <int key="connectionID">9</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">delegate</string>
+ <reference key="source" ref="841351856"/>
+ <reference key="destination" ref="664661524"/>
+ </object>
+ <int key="connectionID">99</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">tabBarController</string>
+ <reference key="source" ref="664661524"/>
+ <reference key="destination" ref="1034742383"/>
+ </object>
+ <int key="connectionID">113</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">textView</string>
+ <reference key="source" ref="1024858337"/>
+ <reference key="destination" ref="876077251"/>
+ </object>
+ <int key="connectionID">135</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">delegate</string>
+ <reference key="source" ref="1034742383"/>
+ <reference key="destination" ref="664661524"/>
+ </object>
+ <int key="connectionID">136</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">button1</string>
+ <reference key="source" ref="1024858337"/>
+ <reference key="destination" ref="808516100"/>
+ </object>
+ <int key="connectionID">141</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">textField</string>
+ <reference key="source" ref="1024858337"/>
+ <reference key="destination" ref="625972407"/>
+ </object>
+ <int key="connectionID">142</int>
+ </object>
+ </object>
+ <object class="IBMutableOrderedSet" key="objectRecords">
+ <object class="NSArray" key="orderedObjects">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBObjectRecord">
+ <int key="objectID">0</int>
+ <reference key="object" ref="0"/>
+ <reference key="children" ref="1000"/>
+ <nil key="parent"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">2</int>
+ <reference key="object" ref="380026005"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-1</int>
+ <reference key="object" ref="841351856"/>
+ <reference key="parent" ref="0"/>
+ <string key="objectName">File's Owner</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">3</int>
+ <reference key="object" ref="664661524"/>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">106</int>
+ <reference key="object" ref="1034742383"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="795333663"/>
+ <reference ref="268481961"/>
+ <reference ref="1024858337"/>
+ </object>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">107</int>
+ <reference key="object" ref="795333663"/>
+ <reference key="parent" ref="1034742383"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">108</int>
+ <reference key="object" ref="1024858337"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="765670903"/>
+ <reference ref="434903890"/>
+ </object>
+ <reference key="parent" ref="1034742383"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">109</int>
+ <reference key="object" ref="268481961"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="807309489"/>
+ </object>
+ <reference key="parent" ref="1034742383"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">110</int>
+ <reference key="object" ref="807309489"/>
+ <reference key="parent" ref="268481961"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">111</int>
+ <reference key="object" ref="765670903"/>
+ <reference key="parent" ref="1024858337"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-2</int>
+ <reference key="object" ref="532797962"/>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">119</int>
+ <reference key="object" ref="434903890"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="876077251"/>
+ <reference ref="808516100"/>
+ <reference ref="625972407"/>
+ </object>
+ <reference key="parent" ref="1024858337"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">123</int>
+ <reference key="object" ref="876077251"/>
+ <reference key="parent" ref="434903890"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">126</int>
+ <reference key="object" ref="625972407"/>
+ <reference key="parent" ref="434903890"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">139</int>
+ <reference key="object" ref="808516100"/>
+ <reference key="parent" ref="434903890"/>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="flattenedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>-1.CustomClassName</string>
+ <string>-2.CustomClassName</string>
+ <string>106.CustomClassName</string>
+ <string>106.IBEditorWindowLastContentRect</string>
+ <string>106.IBLastUsedUIStatusBarStylesToTargetRuntimesMap</string>
+ <string>106.IBPluginDependency</string>
+ <string>107.IBPluginDependency</string>
+ <string>108.CustomClassName</string>
+ <string>108.IBPluginDependency</string>
+ <string>109.CustomClassName</string>
+ <string>109.IBPluginDependency</string>
+ <string>110.IBPluginDependency</string>
+ <string>111.IBPluginDependency</string>
+ <string>119.IBPluginDependency</string>
+ <string>123.IBPluginDependency</string>
+ <string>126.IBPluginDependency</string>
+ <string>139.IBPluginDependency</string>
+ <string>2.IBAttributePlaceholdersKey</string>
+ <string>2.IBEditorWindowLastContentRect</string>
+ <string>2.IBLastUsedUIStatusBarStylesToTargetRuntimesMap</string>
+ <string>2.IBPluginDependency</string>
+ <string>3.CustomClassName</string>
+ <string>3.IBPluginDependency</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>UIApplication</string>
+ <string>UIResponder</string>
+ <string>TabBarController</string>
+ <string>{{197, 109}, {1039, 747}}</string>
+ <object class="NSMutableDictionary">
+ <string key="NS.key.0">IBCocoaTouchFramework</string>
+ <integer value="2" key="NS.object.0"/>
+ </object>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>FirstViewController</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>ConfigViewController</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <object class="NSMutableDictionary">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <string>{{528, 373}, {320, 480}}</string>
+ <object class="NSMutableDictionary">
+ <string key="NS.key.0">IBCocoaTouchFramework</string>
+ <integer value="0" key="NS.object.0"/>
+ </object>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>ipjsuaAppDelegate</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="unlocalizedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="activeLocalization"/>
+ <object class="NSMutableDictionary" key="localizations">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="sourceID"/>
+ <int key="maxID">142</int>
+ </object>
+ <object class="IBClassDescriber" key="IBDocument.Classes">
+ <object class="NSMutableArray" key="referencedPartialClassDescriptions">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBPartialClassDescription">
+ <string key="className">ConfigViewController</string>
+ <string key="superclassName">UIViewController</string>
+ <object class="NSMutableDictionary" key="outlets">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>button1</string>
+ <string>button2</string>
+ <string>textView</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>UIButton</string>
+ <string>UIButton</string>
+ <string>UITextView</string>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="toOneOutletInfosByName">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>button1</string>
+ <string>button2</string>
+ <string>textView</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBToOneOutletInfo">
+ <string key="name">button1</string>
+ <string key="candidateClassName">UIButton</string>
+ </object>
+ <object class="IBToOneOutletInfo">
+ <string key="name">button2</string>
+ <string key="candidateClassName">UIButton</string>
+ </object>
+ <object class="IBToOneOutletInfo">
+ <string key="name">textView</string>
+ <string key="candidateClassName">UITextView</string>
+ </object>
+ </object>
+ </object>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">Classes/ConfigViewController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">FirstViewController</string>
+ <string key="superclassName">UIViewController</string>
+ <object class="NSMutableDictionary" key="outlets">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>button1</string>
+ <string>textField</string>
+ <string>textView</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>UIButton</string>
+ <string>UITextField</string>
+ <string>UITextView</string>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="toOneOutletInfosByName">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>button1</string>
+ <string>textField</string>
+ <string>textView</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBToOneOutletInfo">
+ <string key="name">button1</string>
+ <string key="candidateClassName">UIButton</string>
+ </object>
+ <object class="IBToOneOutletInfo">
+ <string key="name">textField</string>
+ <string key="candidateClassName">UITextField</string>
+ </object>
+ <object class="IBToOneOutletInfo">
+ <string key="name">textView</string>
+ <string key="candidateClassName">UITextView</string>
+ </object>
+ </object>
+ </object>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">Classes/FirstViewController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">TabBarController</string>
+ <string key="superclassName">UITabBarController</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">Classes/TabBarController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">ipjsuaAppDelegate</string>
+ <string key="superclassName">NSObject</string>
+ <object class="NSMutableDictionary" key="outlets">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>cfgView</string>
+ <string>tabBarController</string>
+ <string>window</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>ConfigViewController</string>
+ <string>TabBarController</string>
+ <string>UIWindow</string>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="toOneOutletInfosByName">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>cfgView</string>
+ <string>tabBarController</string>
+ <string>window</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBToOneOutletInfo">
+ <string key="name">cfgView</string>
+ <string key="candidateClassName">ConfigViewController</string>
+ </object>
+ <object class="IBToOneOutletInfo">
+ <string key="name">tabBarController</string>
+ <string key="candidateClassName">TabBarController</string>
+ </object>
+ <object class="IBToOneOutletInfo">
+ <string key="name">window</string>
+ <string key="candidateClassName">UIWindow</string>
+ </object>
+ </object>
+ </object>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">Classes/ipjsuaAppDelegate.h</string>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSError.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSFileManager.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSKeyValueCoding.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSKeyValueObserving.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSKeyedArchiver.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSNetServices.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSObject.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSPort.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSRunLoop.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSStream.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSThread.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSURL.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSURLConnection.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSXMLParser.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIAccessibility.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UINibLoading.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier" id="539560514">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIResponder.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIApplication</string>
+ <string key="superclassName">UIResponder</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIApplication.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIBarItem</string>
+ <string key="superclassName">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIBarItem.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIButton</string>
+ <string key="superclassName">UIControl</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIButton.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIControl</string>
+ <string key="superclassName">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIControl.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIResponder</string>
+ <string key="superclassName">NSObject</string>
+ <reference key="sourceIdentifier" ref="539560514"/>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIScrollView</string>
+ <string key="superclassName">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIScrollView.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UISearchBar</string>
+ <string key="superclassName">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UISearchBar.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UISearchDisplayController</string>
+ <string key="superclassName">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UISearchDisplayController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UITabBar</string>
+ <string key="superclassName">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UITabBar.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UITabBarController</string>
+ <string key="superclassName">UIViewController</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier" id="53818940">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UITabBarController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UITabBarItem</string>
+ <string key="superclassName">UIBarItem</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UITabBarItem.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UITextField</string>
+ <string key="superclassName">UIControl</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier" id="1015289008">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UITextField.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UITextView</string>
+ <string key="superclassName">UIScrollView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UITextView.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIView</string>
+ <reference key="sourceIdentifier" ref="1015289008"/>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIView</string>
+ <string key="superclassName">UIResponder</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIView.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIViewController</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UINavigationController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIViewController</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIPopoverController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIViewController</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UISplitViewController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIViewController</string>
+ <reference key="sourceIdentifier" ref="53818940"/>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIViewController</string>
+ <string key="superclassName">UIResponder</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIViewController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIWindow</string>
+ <string key="superclassName">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIWindow.h</string>
+ </object>
+ </object>
+ </object>
+ </object>
+ <int key="IBDocument.localizationMode">0</int>
+ <string key="IBDocument.TargetRuntimeIdentifier">IBIPadFramework</string>
+ <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS</string>
+ <integer value="800" key="NS.object.0"/>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3</string>
+ <integer value="3100" key="NS.object.0"/>
+ </object>
+ <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
+ <string key="IBDocument.LastKnownRelativeProjectPath">../ipjsua.xcodeproj</string>
+ <int key="IBDocument.defaultPropertyAccessControl">3</int>
+ <string key="IBCocoaTouchPluginVersion">117</string>
+ </data>
+</archive>
diff --git a/pjsip-apps/src/ipjsua/Resources-iPad/SecondView-iPad.xib b/pjsip-apps/src/ipjsua/Resources-iPad/SecondView-iPad.xib
new file mode 100644
index 0000000..9b59476
--- /dev/null
+++ b/pjsip-apps/src/ipjsua/Resources-iPad/SecondView-iPad.xib
@@ -0,0 +1,561 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.CocoaTouch.iPad.XIB" version="7.10">
+ <data>
+ <int key="IBDocument.SystemTarget">800</int>
+ <string key="IBDocument.SystemVersion">10C540</string>
+ <string key="IBDocument.InterfaceBuilderVersion">788</string>
+ <string key="IBDocument.AppKitVersion">1038.25</string>
+ <string key="IBDocument.HIToolboxVersion">458.00</string>
+ <object class="NSMutableDictionary" key="IBDocument.PluginVersions">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string key="NS.object.0">117</string>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <integer value="1"/>
+ </object>
+ <object class="NSArray" key="IBDocument.PluginDependencies">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.Metadata">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys" id="0">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBProxyObject" id="372490531">
+ <string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
+ <string key="targetRuntimeIdentifier">IBIPadFramework</string>
+ </object>
+ <object class="IBProxyObject" id="263589821">
+ <string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
+ <string key="targetRuntimeIdentifier">IBIPadFramework</string>
+ </object>
+ <object class="IBUIView" id="191373211">
+ <reference key="NSNextResponder"/>
+ <int key="NSvFlags">274</int>
+ <object class="NSMutableArray" key="NSSubviews">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBUITextView" id="255779567">
+ <reference key="NSNextResponder" ref="191373211"/>
+ <int key="NSvFlags">306</int>
+ <string key="NSFrame">{{20, 15}, {825, 664}}</string>
+ <reference key="NSSuperview" ref="191373211"/>
+ <object class="NSColor" key="IBUIBackgroundColor">
+ <int key="NSColorSpace">1</int>
+ <bytes key="NSRGB">MSAwLjkzNzA0OTE0MTggMC45NDg5MTUzMDc3AA</bytes>
+ </object>
+ <bool key="IBUIOpaque">NO</bool>
+ <bool key="IBUIClipsSubviews">YES</bool>
+ <bool key="IBUIMultipleTouchEnabled">YES</bool>
+ <string key="targetRuntimeIdentifier">IBIPadFramework</string>
+ <bool key="IBUIShowsHorizontalScrollIndicator">NO</bool>
+ <bool key="IBUIDelaysContentTouches">NO</bool>
+ <bool key="IBUICanCancelContentTouches">NO</bool>
+ <float key="IBUIMinimumZoomScale">0.0</float>
+ <float key="IBUIMaximumZoomScale">0.0</float>
+ <bool key="IBUIBouncesZoom">NO</bool>
+ <string key="IBUIText">Config</string>
+ <object class="IBUITextInputTraits" key="IBUITextInputTraits">
+ <int key="IBUIAutocorrectionType">1</int>
+ <int key="IBUIKeyboardType">1</int>
+ <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+ </object>
+ </object>
+ <object class="IBUIButton" id="11217163">
+ <reference key="NSNextResponder" ref="191373211"/>
+ <int key="NSvFlags">292</int>
+ <string key="NSFrame">{{853, 15}, {151, 37}}</string>
+ <reference key="NSSuperview" ref="191373211"/>
+ <bool key="IBUIOpaque">NO</bool>
+ <bool key="IBUIClearsContextBeforeDrawing">NO</bool>
+ <string key="targetRuntimeIdentifier">IBIPadFramework</string>
+ <int key="IBUIContentHorizontalAlignment">0</int>
+ <int key="IBUIContentVerticalAlignment">0</int>
+ <object class="NSFont" key="IBUIFont" id="1008892202">
+ <string key="NSName">Helvetica-Bold</string>
+ <double key="NSSize">15</double>
+ <int key="NSfFlags">16</int>
+ </object>
+ <int key="IBUIButtonType">1</int>
+ <string key="IBUINormalTitle">Save</string>
+ <object class="NSColor" key="IBUIHighlightedTitleColor" id="700997684">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MQA</bytes>
+ </object>
+ <object class="NSColor" key="IBUINormalTitleColor">
+ <int key="NSColorSpace">1</int>
+ <bytes key="NSRGB">MC4xOTYwNzg0MyAwLjMwOTgwMzkzIDAuNTIxNTY4NjYAA</bytes>
+ </object>
+ <object class="NSColor" key="IBUINormalTitleShadowColor" id="201718988">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MC41AA</bytes>
+ </object>
+ </object>
+ <object class="IBUIButton" id="944403502">
+ <reference key="NSNextResponder" ref="191373211"/>
+ <int key="NSvFlags">292</int>
+ <string key="NSFrame">{{853, 75}, {151, 37}}</string>
+ <reference key="NSSuperview" ref="191373211"/>
+ <bool key="IBUIOpaque">NO</bool>
+ <bool key="IBUIClearsContextBeforeDrawing">NO</bool>
+ <string key="targetRuntimeIdentifier">IBIPadFramework</string>
+ <int key="IBUIContentHorizontalAlignment">0</int>
+ <int key="IBUIContentVerticalAlignment">0</int>
+ <reference key="IBUIFont" ref="1008892202"/>
+ <int key="IBUIButtonType">1</int>
+ <string key="IBUINormalTitle">Revert</string>
+ <reference key="IBUIHighlightedTitleColor" ref="700997684"/>
+ <object class="NSColor" key="IBUINormalTitleColor">
+ <int key="NSColorSpace">1</int>
+ <bytes key="NSRGB">MC4xOTYwNzg0MyAwLjMwOTgwMzkzIDAuNTIxNTY4NjYAA</bytes>
+ </object>
+ <reference key="IBUINormalTitleShadowColor" ref="201718988"/>
+ </object>
+ </object>
+ <string key="NSFrameSize">{1024, 699}</string>
+ <reference key="NSSuperview"/>
+ <object class="NSColor" key="IBUIBackgroundColor">
+ <int key="NSColorSpace">1</int>
+ <bytes key="NSRGB">MC41NjQxMjQ1MDA4IDAuNzUyMzk5ODQ5NyAwLjg1NzE0Mjg1NzEAA</bytes>
+ </object>
+ <object class="IBUISimulatedStatusBarMetrics" key="IBUISimulatedStatusBarMetrics">
+ <int key="IBUIStatusBarStyle">2</int>
+ </object>
+ <object class="IBUISimulatedTabBarMetrics" key="IBUISimulatedBottomBarMetrics"/>
+ <object class="IBUISimulatedOrientationMetrics" key="IBUISimulatedOrientationMetrics">
+ <int key="interfaceOrientation">3</int>
+ </object>
+ <string key="targetRuntimeIdentifier">IBIPadFramework</string>
+ </object>
+ </object>
+ <object class="IBObjectContainer" key="IBDocument.Objects">
+ <object class="NSMutableArray" key="connectionRecords">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">view</string>
+ <reference key="source" ref="372490531"/>
+ <reference key="destination" ref="191373211"/>
+ </object>
+ <int key="connectionID">3</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">textView</string>
+ <reference key="source" ref="372490531"/>
+ <reference key="destination" ref="255779567"/>
+ </object>
+ <int key="connectionID">8</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">button1</string>
+ <reference key="source" ref="372490531"/>
+ <reference key="destination" ref="11217163"/>
+ </object>
+ <int key="connectionID">11</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">button2</string>
+ <reference key="source" ref="372490531"/>
+ <reference key="destination" ref="944403502"/>
+ </object>
+ <int key="connectionID">12</int>
+ </object>
+ </object>
+ <object class="IBMutableOrderedSet" key="objectRecords">
+ <object class="NSArray" key="orderedObjects">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBObjectRecord">
+ <int key="objectID">0</int>
+ <reference key="object" ref="0"/>
+ <reference key="children" ref="1000"/>
+ <nil key="parent"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">1</int>
+ <reference key="object" ref="191373211"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="255779567"/>
+ <reference ref="944403502"/>
+ <reference ref="11217163"/>
+ </object>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-1</int>
+ <reference key="object" ref="372490531"/>
+ <reference key="parent" ref="0"/>
+ <string key="objectName">File's Owner</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-2</int>
+ <reference key="object" ref="263589821"/>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">7</int>
+ <reference key="object" ref="255779567"/>
+ <reference key="parent" ref="191373211"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">9</int>
+ <reference key="object" ref="11217163"/>
+ <reference key="parent" ref="191373211"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">10</int>
+ <reference key="object" ref="944403502"/>
+ <reference key="parent" ref="191373211"/>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="flattenedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>-1.CustomClassName</string>
+ <string>-2.CustomClassName</string>
+ <string>1.IBEditorWindowLastContentRect</string>
+ <string>1.IBLastUsedUIStatusBarStylesToTargetRuntimesMap</string>
+ <string>1.IBPluginDependency</string>
+ <string>10.IBPluginDependency</string>
+ <string>7.IBPluginDependency</string>
+ <string>9.IBPluginDependency</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>ConfigViewController</string>
+ <string>UIResponder</string>
+ <string>{{41, 113}, {1116, 709}}</string>
+ <object class="NSMutableDictionary">
+ <string key="NS.key.0">IBCocoaTouchFramework</string>
+ <integer value="0" key="NS.object.0"/>
+ </object>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="unlocalizedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="activeLocalization"/>
+ <object class="NSMutableDictionary" key="localizations">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="sourceID"/>
+ <int key="maxID">12</int>
+ </object>
+ <object class="IBClassDescriber" key="IBDocument.Classes">
+ <object class="NSMutableArray" key="referencedPartialClassDescriptions">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBPartialClassDescription">
+ <string key="className">ConfigViewController</string>
+ <string key="superclassName">UIViewController</string>
+ <object class="NSMutableDictionary" key="outlets">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>button1</string>
+ <string>button2</string>
+ <string>textView</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>UIButton</string>
+ <string>UIButton</string>
+ <string>UITextView</string>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="toOneOutletInfosByName">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>button1</string>
+ <string>button2</string>
+ <string>textView</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBToOneOutletInfo">
+ <string key="name">button1</string>
+ <string key="candidateClassName">UIButton</string>
+ </object>
+ <object class="IBToOneOutletInfo">
+ <string key="name">button2</string>
+ <string key="candidateClassName">UIButton</string>
+ </object>
+ <object class="IBToOneOutletInfo">
+ <string key="name">textView</string>
+ <string key="candidateClassName">UITextView</string>
+ </object>
+ </object>
+ </object>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">Classes/ConfigViewController.h</string>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSError.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSFileManager.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSKeyValueCoding.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSKeyValueObserving.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSKeyedArchiver.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSNetServices.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSObject.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSPort.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSRunLoop.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSStream.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSThread.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSURL.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSURLConnection.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSXMLParser.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIAccessibility.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UINibLoading.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier" id="518071601">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIResponder.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIButton</string>
+ <string key="superclassName">UIControl</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIButton.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIControl</string>
+ <string key="superclassName">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIControl.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIResponder</string>
+ <string key="superclassName">NSObject</string>
+ <reference key="sourceIdentifier" ref="518071601"/>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIScrollView</string>
+ <string key="superclassName">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIScrollView.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UISearchBar</string>
+ <string key="superclassName">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UISearchBar.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UISearchDisplayController</string>
+ <string key="superclassName">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UISearchDisplayController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UITextView</string>
+ <string key="superclassName">UIScrollView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UITextView.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UITextField.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIView</string>
+ <string key="superclassName">UIResponder</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIView.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIViewController</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UINavigationController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIViewController</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIPopoverController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIViewController</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UISplitViewController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIViewController</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UITabBarController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIViewController</string>
+ <string key="superclassName">UIResponder</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIViewController.h</string>
+ </object>
+ </object>
+ </object>
+ </object>
+ <int key="IBDocument.localizationMode">0</int>
+ <string key="IBDocument.TargetRuntimeIdentifier">IBIPadFramework</string>
+ <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS</string>
+ <integer value="800" key="NS.object.0"/>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3</string>
+ <integer value="3100" key="NS.object.0"/>
+ </object>
+ <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
+ <string key="IBDocument.LastKnownRelativeProjectPath">ipjsua.xcodeproj</string>
+ <int key="IBDocument.defaultPropertyAccessControl">3</int>
+ <string key="IBCocoaTouchPluginVersion">117</string>
+ </data>
+</archive>
diff --git a/pjsip-apps/src/ipjsua/SecondView.xib b/pjsip-apps/src/ipjsua/SecondView.xib
new file mode 100644
index 0000000..dc43b74
--- /dev/null
+++ b/pjsip-apps/src/ipjsua/SecondView.xib
@@ -0,0 +1,501 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="7.10">
+ <data>
+ <int key="IBDocument.SystemTarget">784</int>
+ <string key="IBDocument.SystemVersion">10C540</string>
+ <string key="IBDocument.InterfaceBuilderVersion">740</string>
+ <string key="IBDocument.AppKitVersion">1038.25</string>
+ <string key="IBDocument.HIToolboxVersion">458.00</string>
+ <object class="NSMutableDictionary" key="IBDocument.PluginVersions">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string key="NS.object.0">62</string>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <integer value="1"/>
+ </object>
+ <object class="NSArray" key="IBDocument.PluginDependencies">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.Metadata">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys" id="0">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBProxyObject" id="372490531">
+ <string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
+ </object>
+ <object class="IBProxyObject" id="263589821">
+ <string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
+ </object>
+ <object class="IBUIView" id="191373211">
+ <reference key="NSNextResponder"/>
+ <int key="NSvFlags">274</int>
+ <object class="NSMutableArray" key="NSSubviews">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBUITextView" id="255779567">
+ <reference key="NSNextResponder" ref="191373211"/>
+ <int key="NSvFlags">306</int>
+ <string key="NSFrameSize">{375, 251}</string>
+ <reference key="NSSuperview" ref="191373211"/>
+ <object class="NSColor" key="IBUIBackgroundColor">
+ <int key="NSColorSpace">1</int>
+ <bytes key="NSRGB">MSAwLjkzNzA0OTE0MTggMC45NDg5MTUzMDc3AA</bytes>
+ </object>
+ <bool key="IBUIOpaque">NO</bool>
+ <bool key="IBUIClipsSubviews">YES</bool>
+ <bool key="IBUIMultipleTouchEnabled">YES</bool>
+ <bool key="IBUIShowsHorizontalScrollIndicator">NO</bool>
+ <bool key="IBUIDelaysContentTouches">NO</bool>
+ <bool key="IBUICanCancelContentTouches">NO</bool>
+ <float key="IBUIMinimumZoomScale">0.0</float>
+ <float key="IBUIMaximumZoomScale">0.0</float>
+ <bool key="IBUIBouncesZoom">NO</bool>
+ <string key="IBUIText">Config</string>
+ <object class="IBUITextInputTraits" key="IBUITextInputTraits">
+ <int key="IBUIAutocorrectionType">1</int>
+ <int key="IBUIKeyboardType">1</int>
+ </object>
+ </object>
+ <object class="IBUIButton" id="11217163">
+ <reference key="NSNextResponder" ref="191373211"/>
+ <int key="NSvFlags">292</int>
+ <string key="NSFrame">{{376, 6}, {104, 37}}</string>
+ <reference key="NSSuperview" ref="191373211"/>
+ <bool key="IBUIOpaque">NO</bool>
+ <bool key="IBUIClearsContextBeforeDrawing">NO</bool>
+ <int key="IBUIContentHorizontalAlignment">0</int>
+ <int key="IBUIContentVerticalAlignment">0</int>
+ <object class="NSFont" key="IBUIFont" id="1008892202">
+ <string key="NSName">Helvetica-Bold</string>
+ <double key="NSSize">15</double>
+ <int key="NSfFlags">16</int>
+ </object>
+ <int key="IBUIButtonType">1</int>
+ <string key="IBUINormalTitle">Save</string>
+ <object class="NSColor" key="IBUIHighlightedTitleColor" id="700997684">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MQA</bytes>
+ </object>
+ <object class="NSColor" key="IBUINormalTitleColor">
+ <int key="NSColorSpace">1</int>
+ <bytes key="NSRGB">MC4xOTYwNzg0MyAwLjMwOTgwMzkzIDAuNTIxNTY4NjYAA</bytes>
+ </object>
+ <object class="NSColor" key="IBUINormalTitleShadowColor" id="201718988">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MC41AA</bytes>
+ </object>
+ </object>
+ <object class="IBUIButton" id="944403502">
+ <reference key="NSNextResponder" ref="191373211"/>
+ <int key="NSvFlags">292</int>
+ <string key="NSFrame">{{376, 51}, {104, 37}}</string>
+ <reference key="NSSuperview" ref="191373211"/>
+ <bool key="IBUIOpaque">NO</bool>
+ <bool key="IBUIClearsContextBeforeDrawing">NO</bool>
+ <int key="IBUIContentHorizontalAlignment">0</int>
+ <int key="IBUIContentVerticalAlignment">0</int>
+ <reference key="IBUIFont" ref="1008892202"/>
+ <int key="IBUIButtonType">1</int>
+ <string key="IBUINormalTitle">Revert</string>
+ <reference key="IBUIHighlightedTitleColor" ref="700997684"/>
+ <object class="NSColor" key="IBUINormalTitleColor">
+ <int key="NSColorSpace">1</int>
+ <bytes key="NSRGB">MC4xOTYwNzg0MyAwLjMwOTgwMzkzIDAuNTIxNTY4NjYAA</bytes>
+ </object>
+ <reference key="IBUINormalTitleShadowColor" ref="201718988"/>
+ </object>
+ </object>
+ <string key="NSFrameSize">{480, 251}</string>
+ <reference key="NSSuperview"/>
+ <object class="NSColor" key="IBUIBackgroundColor">
+ <int key="NSColorSpace">1</int>
+ <bytes key="NSRGB">MC41NjQxMjQ1MDA4IDAuNzUyMzk5ODQ5NyAwLjg1NzE0Mjg1NzEAA</bytes>
+ </object>
+ <object class="IBUISimulatedStatusBarMetrics" key="IBUISimulatedStatusBarMetrics"/>
+ <object class="IBUISimulatedTabBarMetrics" key="IBUISimulatedBottomBarMetrics"/>
+ </object>
+ </object>
+ <object class="IBObjectContainer" key="IBDocument.Objects">
+ <object class="NSMutableArray" key="connectionRecords">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">view</string>
+ <reference key="source" ref="372490531"/>
+ <reference key="destination" ref="191373211"/>
+ </object>
+ <int key="connectionID">3</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">textView</string>
+ <reference key="source" ref="372490531"/>
+ <reference key="destination" ref="255779567"/>
+ </object>
+ <int key="connectionID">8</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">button1</string>
+ <reference key="source" ref="372490531"/>
+ <reference key="destination" ref="11217163"/>
+ </object>
+ <int key="connectionID">11</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">button2</string>
+ <reference key="source" ref="372490531"/>
+ <reference key="destination" ref="944403502"/>
+ </object>
+ <int key="connectionID">12</int>
+ </object>
+ </object>
+ <object class="IBMutableOrderedSet" key="objectRecords">
+ <object class="NSArray" key="orderedObjects">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBObjectRecord">
+ <int key="objectID">0</int>
+ <reference key="object" ref="0"/>
+ <reference key="children" ref="1000"/>
+ <nil key="parent"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">1</int>
+ <reference key="object" ref="191373211"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="255779567"/>
+ <reference ref="944403502"/>
+ <reference ref="11217163"/>
+ </object>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-1</int>
+ <reference key="object" ref="372490531"/>
+ <reference key="parent" ref="0"/>
+ <string key="objectName">File's Owner</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-2</int>
+ <reference key="object" ref="263589821"/>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">7</int>
+ <reference key="object" ref="255779567"/>
+ <reference key="parent" ref="191373211"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">9</int>
+ <reference key="object" ref="11217163"/>
+ <reference key="parent" ref="191373211"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">10</int>
+ <reference key="object" ref="944403502"/>
+ <reference key="parent" ref="191373211"/>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="flattenedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>-1.CustomClassName</string>
+ <string>-2.CustomClassName</string>
+ <string>1.IBEditorWindowLastContentRect</string>
+ <string>1.IBPluginDependency</string>
+ <string>10.IBPluginDependency</string>
+ <string>7.IBPluginDependency</string>
+ <string>9.IBPluginDependency</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>ConfigViewController</string>
+ <string>UIResponder</string>
+ <string>{{530, 459}, {480, 320}}</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="unlocalizedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="activeLocalization"/>
+ <object class="NSMutableDictionary" key="localizations">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="sourceID"/>
+ <int key="maxID">12</int>
+ </object>
+ <object class="IBClassDescriber" key="IBDocument.Classes">
+ <object class="NSMutableArray" key="referencedPartialClassDescriptions">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBPartialClassDescription">
+ <string key="className">ConfigViewController</string>
+ <string key="superclassName">UIViewController</string>
+ <object class="NSMutableDictionary" key="outlets">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>button1</string>
+ <string>button2</string>
+ <string>textView</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>UIButton</string>
+ <string>UIButton</string>
+ <string>UITextView</string>
+ </object>
+ </object>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">Classes/ConfigViewController.h</string>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSError.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSFileManager.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSKeyValueCoding.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSKeyValueObserving.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSKeyedArchiver.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSNetServices.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSObject.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSPort.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSRunLoop.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSStream.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSThread.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSURL.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSURLConnection.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSXMLParser.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIAccessibility.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UINibLoading.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier" id="518071601">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIResponder.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIButton</string>
+ <string key="superclassName">UIControl</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIButton.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIControl</string>
+ <string key="superclassName">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIControl.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIResponder</string>
+ <string key="superclassName">NSObject</string>
+ <reference key="sourceIdentifier" ref="518071601"/>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIScrollView</string>
+ <string key="superclassName">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIScrollView.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UISearchBar</string>
+ <string key="superclassName">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UISearchBar.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UISearchDisplayController</string>
+ <string key="superclassName">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UISearchDisplayController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UITextView</string>
+ <string key="superclassName">UIScrollView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UITextView.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UITextField.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIView</string>
+ <string key="superclassName">UIResponder</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIView.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIViewController</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UINavigationController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIViewController</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UITabBarController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIViewController</string>
+ <string key="superclassName">UIResponder</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIViewController.h</string>
+ </object>
+ </object>
+ </object>
+ </object>
+ <int key="IBDocument.localizationMode">0</int>
+ <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3</string>
+ <integer value="3100" key="NS.object.0"/>
+ </object>
+ <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
+ <string key="IBDocument.LastKnownRelativeProjectPath">ipjsua.xcodeproj</string>
+ <int key="IBDocument.defaultPropertyAccessControl">3</int>
+ <string key="IBCocoaTouchPluginVersion">3.1</string>
+ </data>
+</archive>
diff --git a/pjsip-apps/src/ipjsua/config.cfg b/pjsip-apps/src/ipjsua/config.cfg
new file mode 100644
index 0000000..776fb03
--- /dev/null
+++ b/pjsip-apps/src/ipjsua/config.cfg
@@ -0,0 +1,2 @@
+--auto-answer=200
+--clock-rate=8000
diff --git a/pjsip-apps/src/ipjsua/ipjsua-Info.plist b/pjsip-apps/src/ipjsua/ipjsua-Info.plist
new file mode 100644
index 0000000..b57ad6d
--- /dev/null
+++ b/pjsip-apps/src/ipjsua/ipjsua-Info.plist
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleDisplayName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+ <key>CFBundleIconFile</key>
+ <string></string>
+ <key>CFBundleIdentifier</key>
+ <string>com.teluu.${PRODUCT_NAME:rfc1034identifier}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+ <key>LSRequiresIPhoneOS</key>
+ <true/>
+ <key>NSMainNibFile</key>
+ <string>MainWindow</string>
+ <key>NSMainNibFile~ipad</key>
+ <string>MainWindow-iPad</string>
+ <key>UIBackgroundModes</key>
+ <array>
+ <string>audio</string>
+ <string>voip</string>
+ </array>
+ <key>UIInterfaceOrientation</key>
+ <string>UIInterfaceOrientationLandscapeRight</string>
+</dict>
+</plist>
diff --git a/pjsip-apps/src/ipjsua/ipjsua.xcodeproj/project.pbxproj b/pjsip-apps/src/ipjsua/ipjsua.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..fe5e11b
--- /dev/null
+++ b/pjsip-apps/src/ipjsua/ipjsua.xcodeproj/project.pbxproj
@@ -0,0 +1,492 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 45;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 1D3623260D0F684500981E51 /* ipjsuaAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D3623250D0F684500981E51 /* ipjsuaAppDelegate.m */; };
+ 1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; };
+ 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; };
+ 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; };
+ 28216C970DB411BC00E5133A /* FirstViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 28216C960DB411BC00E5133A /* FirstViewController.m */; };
+ 282CCBFE0DB6C98000C4EA27 /* SecondView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 282CCBFD0DB6C98000C4EA27 /* SecondView.xib */; };
+ 288765080DF74369002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765070DF74369002DB57D /* CoreGraphics.framework */; };
+ 28AD73880D9D96C1002E5188 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD73870D9D96C1002E5188 /* MainWindow.xib */; };
+ 3A0D789F121E324E009D5030 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A0D789E121E324E009D5030 /* CFNetwork.framework */; };
+ 3A0D7ECD123DD46C009D5030 /* MainWindow-iPad.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3A0D7ECC123DD46C009D5030 /* MainWindow-iPad.xib */; };
+ 3A0D7F20123F2254009D5030 /* SecondView-iPad.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3A0D7F1F123F2254009D5030 /* SecondView-iPad.xib */; };
+ 3AE06674138E6C25008EE71A /* libpjmedia-videodev-arm-apple-darwin9.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AE06673138E6C25008EE71A /* libpjmedia-videodev-arm-apple-darwin9.a */; };
+ 3AE06681138E6F88008EE71A /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AE06680138E6F88008EE71A /* AVFoundation.framework */; };
+ 3AE06693138E7056008EE71A /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AE06692138E7056008EE71A /* OpenGLES.framework */; };
+ 3AE06695138E70B9008EE71A /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AE06694138E70B9008EE71A /* libz.dylib */; };
+ 3AE06699138E70F0008EE71A /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AE06696138E70F0008EE71A /* CoreGraphics.framework */; };
+ 3AE0669A138E70F0008EE71A /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AE06697138E70F0008EE71A /* CoreMedia.framework */; };
+ 3AE0669B138E70F0008EE71A /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AE06698138E70F0008EE71A /* CoreVideo.framework */; };
+ 3AE0669D138E710C008EE71A /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AE0669C138E710C008EE71A /* QuartzCore.framework */; };
+ 3AE9099D11587BB900FAEAA5 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AE9099C11587BB900FAEAA5 /* AudioToolbox.framework */; };
+ 3AE90A2D1158B52500FAEAA5 /* pjsua_app.c in Sources */ = {isa = PBXBuildFile; fileRef = 3AE90A2C1158B52500FAEAA5 /* pjsua_app.c */; };
+ 3AE90A6A1158C6B400FAEAA5 /* libgsmcodec-arm-apple-darwin9.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AE90A691158C6B400FAEAA5 /* libgsmcodec-arm-apple-darwin9.a */; };
+ 3AE90A6C1158C6B400FAEAA5 /* libpj-arm-apple-darwin9.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AE90A6B1158C6B400FAEAA5 /* libpj-arm-apple-darwin9.a */; };
+ 3AE90A6E1158C6B400FAEAA5 /* libpjlib-util-arm-apple-darwin9.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AE90A6D1158C6B400FAEAA5 /* libpjlib-util-arm-apple-darwin9.a */; };
+ 3AE90A701158C6B400FAEAA5 /* libpjmedia-arm-apple-darwin9.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AE90A6F1158C6B400FAEAA5 /* libpjmedia-arm-apple-darwin9.a */; };
+ 3AE90A721158C6B400FAEAA5 /* libpjmedia-audiodev-arm-apple-darwin9.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AE90A711158C6B400FAEAA5 /* libpjmedia-audiodev-arm-apple-darwin9.a */; };
+ 3AE90A741158C6B400FAEAA5 /* libpjmedia-codec-arm-apple-darwin9.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AE90A731158C6B400FAEAA5 /* libpjmedia-codec-arm-apple-darwin9.a */; };
+ 3AE90A761158C6B400FAEAA5 /* libpjnath-arm-apple-darwin9.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AE90A751158C6B400FAEAA5 /* libpjnath-arm-apple-darwin9.a */; };
+ 3AE90A781158C6B400FAEAA5 /* libpjsip-arm-apple-darwin9.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AE90A771158C6B400FAEAA5 /* libpjsip-arm-apple-darwin9.a */; };
+ 3AE90A7A1158C6B400FAEAA5 /* libpjsip-simple-arm-apple-darwin9.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AE90A791158C6B400FAEAA5 /* libpjsip-simple-arm-apple-darwin9.a */; };
+ 3AE90A7C1158C6B400FAEAA5 /* libpjsip-ua-arm-apple-darwin9.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AE90A7B1158C6B400FAEAA5 /* libpjsip-ua-arm-apple-darwin9.a */; };
+ 3AE90A7E1158C6B400FAEAA5 /* libpjsua-arm-apple-darwin9.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AE90A7D1158C6B400FAEAA5 /* libpjsua-arm-apple-darwin9.a */; };
+ 3AE90A801158C6B400FAEAA5 /* libresample-arm-apple-darwin9.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AE90A7F1158C6B400FAEAA5 /* libresample-arm-apple-darwin9.a */; };
+ 3AE90AC01158F0C400FAEAA5 /* config.cfg in Resources */ = {isa = PBXBuildFile; fileRef = 3AE90ABF1158F0C400FAEAA5 /* config.cfg */; };
+ 3AE90C51115A35BB00FAEAA5 /* TabBarController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3AE90C50115A35BB00FAEAA5 /* TabBarController.m */; };
+ 3AE90DAD115BB1CF00FAEAA5 /* ConfigViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3AE90DAC115BB1CF00FAEAA5 /* ConfigViewController.m */; };
+ 3AE90EB7115F7BCE00FAEAA5 /* libg7221codec-arm-apple-darwin9.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AE90EB1115F7BCE00FAEAA5 /* libg7221codec-arm-apple-darwin9.a */; };
+ 3AE90EB8115F7BCE00FAEAA5 /* libilbccodec-arm-apple-darwin9.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AE90EB2115F7BCE00FAEAA5 /* libilbccodec-arm-apple-darwin9.a */; };
+ 3AE90EB9115F7BCE00FAEAA5 /* libmilenage-arm-apple-darwin9.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AE90EB3115F7BCE00FAEAA5 /* libmilenage-arm-apple-darwin9.a */; };
+ 3AE90EBA115F7BCE00FAEAA5 /* libpjsdp-arm-apple-darwin9.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AE90EB4115F7BCE00FAEAA5 /* libpjsdp-arm-apple-darwin9.a */; };
+ 3AE90EBB115F7BCE00FAEAA5 /* libspeex-arm-apple-darwin9.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AE90EB5115F7BCE00FAEAA5 /* libspeex-arm-apple-darwin9.a */; };
+ 3AE90EBC115F7BCE00FAEAA5 /* libsrtp-arm-apple-darwin9.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AE90EB6115F7BCE00FAEAA5 /* libsrtp-arm-apple-darwin9.a */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+ 1D3623240D0F684500981E51 /* ipjsuaAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ipjsuaAppDelegate.h; sourceTree = "<group>"; };
+ 1D3623250D0F684500981E51 /* ipjsuaAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ipjsuaAppDelegate.m; sourceTree = "<group>"; };
+ 1D6058910D05DD3D006BFB54 /* ipjsua.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ipjsua.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
+ 28216C950DB411BC00E5133A /* FirstViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FirstViewController.h; sourceTree = "<group>"; };
+ 28216C960DB411BC00E5133A /* FirstViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FirstViewController.m; sourceTree = "<group>"; };
+ 282CCBFD0DB6C98000C4EA27 /* SecondView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = SecondView.xib; sourceTree = "<group>"; };
+ 288765070DF74369002DB57D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
+ 28A0AB4B0D9B1048005BE974 /* ipjsua_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ipjsua_Prefix.pch; sourceTree = "<group>"; };
+ 28AD73870D9D96C1002E5188 /* MainWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainWindow.xib; sourceTree = "<group>"; };
+ 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
+ 3A0D789E121E324E009D5030 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; };
+ 3A0D7ECC123DD46C009D5030 /* MainWindow-iPad.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "MainWindow-iPad.xib"; path = "Resources-iPad/MainWindow-iPad.xib"; sourceTree = "<group>"; };
+ 3A0D7F1F123F2254009D5030 /* SecondView-iPad.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "SecondView-iPad.xib"; path = "Resources-iPad/SecondView-iPad.xib"; sourceTree = "<group>"; };
+ 3AE06673138E6C25008EE71A /* libpjmedia-videodev-arm-apple-darwin9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libpjmedia-videodev-arm-apple-darwin9.a"; path = "../../../pjmedia/lib/libpjmedia-videodev-arm-apple-darwin9.a"; sourceTree = "<group>"; };
+ 3AE06680138E6F88008EE71A /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; };
+ 3AE06692138E7056008EE71A /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; };
+ 3AE06694138E70B9008EE71A /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };
+ 3AE06696138E70F0008EE71A /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
+ 3AE06697138E70F0008EE71A /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; };
+ 3AE06698138E70F0008EE71A /* CoreVideo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreVideo.framework; path = System/Library/Frameworks/CoreVideo.framework; sourceTree = SDKROOT; };
+ 3AE0669C138E710C008EE71A /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
+ 3AE9099C11587BB900FAEAA5 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
+ 3AE90A2C1158B52500FAEAA5 /* pjsua_app.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pjsua_app.c; path = ../pjsua/pjsua_app.c; sourceTree = SOURCE_ROOT; };
+ 3AE90A691158C6B400FAEAA5 /* libgsmcodec-arm-apple-darwin9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libgsmcodec-arm-apple-darwin9.a"; path = "../../../third_party/lib/libgsmcodec-arm-apple-darwin9.a"; sourceTree = SOURCE_ROOT; };
+ 3AE90A6B1158C6B400FAEAA5 /* libpj-arm-apple-darwin9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libpj-arm-apple-darwin9.a"; path = "../../../pjlib/lib/libpj-arm-apple-darwin9.a"; sourceTree = SOURCE_ROOT; };
+ 3AE90A6D1158C6B400FAEAA5 /* libpjlib-util-arm-apple-darwin9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libpjlib-util-arm-apple-darwin9.a"; path = "../../../pjlib-util/lib/libpjlib-util-arm-apple-darwin9.a"; sourceTree = SOURCE_ROOT; };
+ 3AE90A6F1158C6B400FAEAA5 /* libpjmedia-arm-apple-darwin9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libpjmedia-arm-apple-darwin9.a"; path = "../../../pjmedia/lib/libpjmedia-arm-apple-darwin9.a"; sourceTree = SOURCE_ROOT; };
+ 3AE90A711158C6B400FAEAA5 /* libpjmedia-audiodev-arm-apple-darwin9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libpjmedia-audiodev-arm-apple-darwin9.a"; path = "../../../pjmedia/lib/libpjmedia-audiodev-arm-apple-darwin9.a"; sourceTree = SOURCE_ROOT; };
+ 3AE90A731158C6B400FAEAA5 /* libpjmedia-codec-arm-apple-darwin9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libpjmedia-codec-arm-apple-darwin9.a"; path = "../../../pjmedia/lib/libpjmedia-codec-arm-apple-darwin9.a"; sourceTree = SOURCE_ROOT; };
+ 3AE90A751158C6B400FAEAA5 /* libpjnath-arm-apple-darwin9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libpjnath-arm-apple-darwin9.a"; path = "../../../pjnath/lib/libpjnath-arm-apple-darwin9.a"; sourceTree = SOURCE_ROOT; };
+ 3AE90A771158C6B400FAEAA5 /* libpjsip-arm-apple-darwin9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libpjsip-arm-apple-darwin9.a"; path = "../../../pjsip/lib/libpjsip-arm-apple-darwin9.a"; sourceTree = SOURCE_ROOT; };
+ 3AE90A791158C6B400FAEAA5 /* libpjsip-simple-arm-apple-darwin9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libpjsip-simple-arm-apple-darwin9.a"; path = "../../../pjsip/lib/libpjsip-simple-arm-apple-darwin9.a"; sourceTree = SOURCE_ROOT; };
+ 3AE90A7B1158C6B400FAEAA5 /* libpjsip-ua-arm-apple-darwin9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libpjsip-ua-arm-apple-darwin9.a"; path = "../../../pjsip/lib/libpjsip-ua-arm-apple-darwin9.a"; sourceTree = SOURCE_ROOT; };
+ 3AE90A7D1158C6B400FAEAA5 /* libpjsua-arm-apple-darwin9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libpjsua-arm-apple-darwin9.a"; path = "../../../pjsip/lib/libpjsua-arm-apple-darwin9.a"; sourceTree = SOURCE_ROOT; };
+ 3AE90A7F1158C6B400FAEAA5 /* libresample-arm-apple-darwin9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libresample-arm-apple-darwin9.a"; path = "../../../third_party/lib/libresample-arm-apple-darwin9.a"; sourceTree = SOURCE_ROOT; };
+ 3AE90ABF1158F0C400FAEAA5 /* config.cfg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = config.cfg; sourceTree = "<group>"; };
+ 3AE90B131159D38400FAEAA5 /* gui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = gui.h; path = ../pjsua/gui.h; sourceTree = SOURCE_ROOT; };
+ 3AE90C4F115A35BB00FAEAA5 /* TabBarController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TabBarController.h; sourceTree = "<group>"; };
+ 3AE90C50115A35BB00FAEAA5 /* TabBarController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TabBarController.m; sourceTree = "<group>"; };
+ 3AE90DAB115BB1CF00FAEAA5 /* ConfigViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConfigViewController.h; sourceTree = "<group>"; };
+ 3AE90DAC115BB1CF00FAEAA5 /* ConfigViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ConfigViewController.m; sourceTree = "<group>"; };
+ 3AE90EB1115F7BCE00FAEAA5 /* libg7221codec-arm-apple-darwin9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libg7221codec-arm-apple-darwin9.a"; path = "../../../third_party/lib/libg7221codec-arm-apple-darwin9.a"; sourceTree = SOURCE_ROOT; };
+ 3AE90EB2115F7BCE00FAEAA5 /* libilbccodec-arm-apple-darwin9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libilbccodec-arm-apple-darwin9.a"; path = "../../../third_party/lib/libilbccodec-arm-apple-darwin9.a"; sourceTree = SOURCE_ROOT; };
+ 3AE90EB3115F7BCE00FAEAA5 /* libmilenage-arm-apple-darwin9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libmilenage-arm-apple-darwin9.a"; path = "../../../third_party/lib/libmilenage-arm-apple-darwin9.a"; sourceTree = SOURCE_ROOT; };
+ 3AE90EB4115F7BCE00FAEAA5 /* libpjsdp-arm-apple-darwin9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libpjsdp-arm-apple-darwin9.a"; path = "../../../pjmedia/lib/libpjsdp-arm-apple-darwin9.a"; sourceTree = SOURCE_ROOT; };
+ 3AE90EB5115F7BCE00FAEAA5 /* libspeex-arm-apple-darwin9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libspeex-arm-apple-darwin9.a"; path = "../../../third_party/lib/libspeex-arm-apple-darwin9.a"; sourceTree = SOURCE_ROOT; };
+ 3AE90EB6115F7BCE00FAEAA5 /* libsrtp-arm-apple-darwin9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libsrtp-arm-apple-darwin9.a"; path = "../../../third_party/lib/libsrtp-arm-apple-darwin9.a"; sourceTree = SOURCE_ROOT; };
+ 8D1107310486CEB800E47090 /* ipjsua-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "ipjsua-Info.plist"; plistStructureDefinitionIdentifier = "com.apple.xcode.plist.structure-definition.iphone.info-plist"; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 1D60588F0D05DD3D006BFB54 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */,
+ 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */,
+ 288765080DF74369002DB57D /* CoreGraphics.framework in Frameworks */,
+ 3AE9099D11587BB900FAEAA5 /* AudioToolbox.framework in Frameworks */,
+ 3AE90A6A1158C6B400FAEAA5 /* libgsmcodec-arm-apple-darwin9.a in Frameworks */,
+ 3AE90A6C1158C6B400FAEAA5 /* libpj-arm-apple-darwin9.a in Frameworks */,
+ 3AE90A6E1158C6B400FAEAA5 /* libpjlib-util-arm-apple-darwin9.a in Frameworks */,
+ 3AE90A701158C6B400FAEAA5 /* libpjmedia-arm-apple-darwin9.a in Frameworks */,
+ 3AE90A721158C6B400FAEAA5 /* libpjmedia-audiodev-arm-apple-darwin9.a in Frameworks */,
+ 3AE90A741158C6B400FAEAA5 /* libpjmedia-codec-arm-apple-darwin9.a in Frameworks */,
+ 3AE90A761158C6B400FAEAA5 /* libpjnath-arm-apple-darwin9.a in Frameworks */,
+ 3AE90A781158C6B400FAEAA5 /* libpjsip-arm-apple-darwin9.a in Frameworks */,
+ 3AE90A7A1158C6B400FAEAA5 /* libpjsip-simple-arm-apple-darwin9.a in Frameworks */,
+ 3AE90A7C1158C6B400FAEAA5 /* libpjsip-ua-arm-apple-darwin9.a in Frameworks */,
+ 3AE90A7E1158C6B400FAEAA5 /* libpjsua-arm-apple-darwin9.a in Frameworks */,
+ 3AE90A801158C6B400FAEAA5 /* libresample-arm-apple-darwin9.a in Frameworks */,
+ 3AE90EB7115F7BCE00FAEAA5 /* libg7221codec-arm-apple-darwin9.a in Frameworks */,
+ 3AE90EB8115F7BCE00FAEAA5 /* libilbccodec-arm-apple-darwin9.a in Frameworks */,
+ 3AE90EB9115F7BCE00FAEAA5 /* libmilenage-arm-apple-darwin9.a in Frameworks */,
+ 3AE90EBA115F7BCE00FAEAA5 /* libpjsdp-arm-apple-darwin9.a in Frameworks */,
+ 3AE90EBB115F7BCE00FAEAA5 /* libspeex-arm-apple-darwin9.a in Frameworks */,
+ 3AE90EBC115F7BCE00FAEAA5 /* libsrtp-arm-apple-darwin9.a in Frameworks */,
+ 3A0D789F121E324E009D5030 /* CFNetwork.framework in Frameworks */,
+ 3AE06674138E6C25008EE71A /* libpjmedia-videodev-arm-apple-darwin9.a in Frameworks */,
+ 3AE06681138E6F88008EE71A /* AVFoundation.framework in Frameworks */,
+ 3AE06693138E7056008EE71A /* OpenGLES.framework in Frameworks */,
+ 3AE06695138E70B9008EE71A /* libz.dylib in Frameworks */,
+ 3AE06699138E70F0008EE71A /* CoreGraphics.framework in Frameworks */,
+ 3AE0669A138E70F0008EE71A /* CoreMedia.framework in Frameworks */,
+ 3AE0669B138E70F0008EE71A /* CoreVideo.framework in Frameworks */,
+ 3AE0669D138E710C008EE71A /* QuartzCore.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 080E96DDFE201D6D7F000001 /* Classes */ = {
+ isa = PBXGroup;
+ children = (
+ 3AE90DAB115BB1CF00FAEAA5 /* ConfigViewController.h */,
+ 3AE90DAC115BB1CF00FAEAA5 /* ConfigViewController.m */,
+ 28216C950DB411BC00E5133A /* FirstViewController.h */,
+ 28216C960DB411BC00E5133A /* FirstViewController.m */,
+ 3AE90C4F115A35BB00FAEAA5 /* TabBarController.h */,
+ 3AE90C50115A35BB00FAEAA5 /* TabBarController.m */,
+ 1D3623240D0F684500981E51 /* ipjsuaAppDelegate.h */,
+ 1D3623250D0F684500981E51 /* ipjsuaAppDelegate.m */,
+ );
+ path = Classes;
+ sourceTree = "<group>";
+ };
+ 19C28FACFE9D520D11CA2CBB /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 1D6058910D05DD3D006BFB54 /* ipjsua.app */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 29B97314FDCFA39411CA2CEA /* ipjsua */ = {
+ isa = PBXGroup;
+ children = (
+ 080E96DDFE201D6D7F000001 /* Classes */,
+ 29B97315FDCFA39411CA2CEA /* Other Sources */,
+ 29B97317FDCFA39411CA2CEA /* Resources */,
+ 3A0D7ECB123DD46C009D5030 /* Resources-iPad */,
+ 29B97323FDCFA39411CA2CEA /* Frameworks */,
+ 3AE909B211587D2700FAEAA5 /* Libraries */,
+ 19C28FACFE9D520D11CA2CBB /* Products */,
+ );
+ name = ipjsua;
+ sourceTree = "<group>";
+ };
+ 29B97315FDCFA39411CA2CEA /* Other Sources */ = {
+ isa = PBXGroup;
+ children = (
+ 3AE90B131159D38400FAEAA5 /* gui.h */,
+ 3AE90ABF1158F0C400FAEAA5 /* config.cfg */,
+ 3AE90A2C1158B52500FAEAA5 /* pjsua_app.c */,
+ 28A0AB4B0D9B1048005BE974 /* ipjsua_Prefix.pch */,
+ 29B97316FDCFA39411CA2CEA /* main.m */,
+ );
+ name = "Other Sources";
+ sourceTree = "<group>";
+ };
+ 29B97317FDCFA39411CA2CEA /* Resources */ = {
+ isa = PBXGroup;
+ children = (
+ 282CCBFD0DB6C98000C4EA27 /* SecondView.xib */,
+ 28AD73870D9D96C1002E5188 /* MainWindow.xib */,
+ 8D1107310486CEB800E47090 /* ipjsua-Info.plist */,
+ );
+ name = Resources;
+ sourceTree = "<group>";
+ };
+ 29B97323FDCFA39411CA2CEA /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 3AE06694138E70B9008EE71A /* libz.dylib */,
+ 3AE0669C138E710C008EE71A /* QuartzCore.framework */,
+ 3AE06696138E70F0008EE71A /* CoreGraphics.framework */,
+ 3AE06697138E70F0008EE71A /* CoreMedia.framework */,
+ 3AE06698138E70F0008EE71A /* CoreVideo.framework */,
+ 3AE06692138E7056008EE71A /* OpenGLES.framework */,
+ 3AE06680138E6F88008EE71A /* AVFoundation.framework */,
+ 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */,
+ 1D30AB110D05D00D00671497 /* Foundation.framework */,
+ 288765070DF74369002DB57D /* CoreGraphics.framework */,
+ 3AE9099C11587BB900FAEAA5 /* AudioToolbox.framework */,
+ 3A0D789E121E324E009D5030 /* CFNetwork.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+ 3A0D7ECB123DD46C009D5030 /* Resources-iPad */ = {
+ isa = PBXGroup;
+ children = (
+ 3A0D7F1F123F2254009D5030 /* SecondView-iPad.xib */,
+ 3A0D7ECC123DD46C009D5030 /* MainWindow-iPad.xib */,
+ );
+ name = "Resources-iPad";
+ sourceTree = "<group>";
+ };
+ 3AE909B211587D2700FAEAA5 /* Libraries */ = {
+ isa = PBXGroup;
+ children = (
+ 3AE90EB1115F7BCE00FAEAA5 /* libg7221codec-arm-apple-darwin9.a */,
+ 3AE90EB2115F7BCE00FAEAA5 /* libilbccodec-arm-apple-darwin9.a */,
+ 3AE90EB3115F7BCE00FAEAA5 /* libmilenage-arm-apple-darwin9.a */,
+ 3AE90EB4115F7BCE00FAEAA5 /* libpjsdp-arm-apple-darwin9.a */,
+ 3AE90EB5115F7BCE00FAEAA5 /* libspeex-arm-apple-darwin9.a */,
+ 3AE90EB6115F7BCE00FAEAA5 /* libsrtp-arm-apple-darwin9.a */,
+ 3AE90A691158C6B400FAEAA5 /* libgsmcodec-arm-apple-darwin9.a */,
+ 3AE90A6B1158C6B400FAEAA5 /* libpj-arm-apple-darwin9.a */,
+ 3AE90A6D1158C6B400FAEAA5 /* libpjlib-util-arm-apple-darwin9.a */,
+ 3AE90A6F1158C6B400FAEAA5 /* libpjmedia-arm-apple-darwin9.a */,
+ 3AE90A711158C6B400FAEAA5 /* libpjmedia-audiodev-arm-apple-darwin9.a */,
+ 3AE90A731158C6B400FAEAA5 /* libpjmedia-codec-arm-apple-darwin9.a */,
+ 3AE06673138E6C25008EE71A /* libpjmedia-videodev-arm-apple-darwin9.a */,
+ 3AE90A751158C6B400FAEAA5 /* libpjnath-arm-apple-darwin9.a */,
+ 3AE90A771158C6B400FAEAA5 /* libpjsip-arm-apple-darwin9.a */,
+ 3AE90A791158C6B400FAEAA5 /* libpjsip-simple-arm-apple-darwin9.a */,
+ 3AE90A7B1158C6B400FAEAA5 /* libpjsip-ua-arm-apple-darwin9.a */,
+ 3AE90A7D1158C6B400FAEAA5 /* libpjsua-arm-apple-darwin9.a */,
+ 3AE90A7F1158C6B400FAEAA5 /* libresample-arm-apple-darwin9.a */,
+ );
+ name = Libraries;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 1D6058900D05DD3D006BFB54 /* ipjsua */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "ipjsua" */;
+ buildPhases = (
+ 1D60588D0D05DD3D006BFB54 /* Resources */,
+ 1D60588E0D05DD3D006BFB54 /* Sources */,
+ 1D60588F0D05DD3D006BFB54 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = ipjsua;
+ productName = ipjsua;
+ productReference = 1D6058910D05DD3D006BFB54 /* ipjsua.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 29B97313FDCFA39411CA2CEA /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ ORGANIZATIONNAME = "Teluu Inc. (http://www.teluu.com)";
+ };
+ buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ipjsua" */;
+ compatibilityVersion = "Xcode 3.1";
+ developmentRegion = English;
+ hasScannedForEncodings = 1;
+ knownRegions = (
+ en,
+ );
+ mainGroup = 29B97314FDCFA39411CA2CEA /* ipjsua */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 1D6058900D05DD3D006BFB54 /* ipjsua */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 1D60588D0D05DD3D006BFB54 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 28AD73880D9D96C1002E5188 /* MainWindow.xib in Resources */,
+ 282CCBFE0DB6C98000C4EA27 /* SecondView.xib in Resources */,
+ 3AE90AC01158F0C400FAEAA5 /* config.cfg in Resources */,
+ 3A0D7ECD123DD46C009D5030 /* MainWindow-iPad.xib in Resources */,
+ 3A0D7F20123F2254009D5030 /* SecondView-iPad.xib in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 1D60588E0D05DD3D006BFB54 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 1D60589B0D05DD56006BFB54 /* main.m in Sources */,
+ 1D3623260D0F684500981E51 /* ipjsuaAppDelegate.m in Sources */,
+ 28216C970DB411BC00E5133A /* FirstViewController.m in Sources */,
+ 3AE90A2D1158B52500FAEAA5 /* pjsua_app.c in Sources */,
+ 3AE90C51115A35BB00FAEAA5 /* TabBarController.m in Sources */,
+ 3AE90DAD115BB1CF00FAEAA5 /* ConfigViewController.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 1D6058940D05DD3E006BFB54 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+ COPY_PHASE_STRIP = NO;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = ipjsua_Prefix.pch;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "PJ_AUTOCONF=1",
+ USE_GUI,
+ );
+ INFOPLIST_FILE = "ipjsua-Info.plist";
+ IPHONEOS_DEPLOYMENT_TARGET = 3.2;
+ LIBRARY_SEARCH_PATHS = (
+ "$(inherited)",
+ "\"$(SRCROOT)/../../../third_party/lib\"",
+ "\"$(SRCROOT)/../../../pjlib/lib\"",
+ "\"$(SRCROOT)/../../../pjlib-util/lib\"",
+ "\"$(SRCROOT)/../../../pjmedia/lib\"",
+ "\"$(SRCROOT)/../../../pjnath/lib\"",
+ "\"$(SRCROOT)/../../../pjsip/lib\"",
+ "\"$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/AVFoundation.framework\"",
+ "\"$(SRCROOT)/../../../../../Library/Developer/Xcode/DerivedData/SDLiPhoneOS-fyjdxvchuwlpnghehmebkvasdrke/Build/Products/Debug-iphoneos\"",
+ "\"$(SRCROOT)/../../../../video/ffmpeg-iphone/lib\"",
+ );
+ ONLY_ACTIVE_ARCH = YES;
+ PRODUCT_NAME = ipjsua;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 1D6058950D05DD3E006BFB54 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+ COPY_PHASE_STRIP = YES;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = ipjsua_Prefix.pch;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "PJ_AUTOCONF=1",
+ USE_GUI,
+ );
+ INFOPLIST_FILE = "ipjsua-Info.plist";
+ IPHONEOS_DEPLOYMENT_TARGET = 3.2;
+ LIBRARY_SEARCH_PATHS = (
+ "$(inherited)",
+ "\"$(SRCROOT)/../../../third_party/lib\"",
+ "\"$(SRCROOT)/../../../pjlib/lib\"",
+ "\"$(SRCROOT)/../../../pjlib-util/lib\"",
+ "\"$(SRCROOT)/../../../pjmedia/lib\"",
+ "\"$(SRCROOT)/../../../pjnath/lib\"",
+ "\"$(SRCROOT)/../../../pjsip/lib\"",
+ "\"$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/AVFoundation.framework\"",
+ "\"$(SRCROOT)/../../../../../Library/Developer/Xcode/DerivedData/SDLiPhoneOS-fyjdxvchuwlpnghehmebkvasdrke/Build/Products/Debug-iphoneos\"",
+ "\"$(SRCROOT)/../../../../video/ffmpeg-iphone/lib\"",
+ );
+ ONLY_ACTIVE_ARCH = YES;
+ PRODUCT_NAME = ipjsua;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Release;
+ };
+ C01FCF4F08A954540054247B /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ GCC_C_LANGUAGE_STANDARD = c99;
+ GCC_PREPROCESSOR_DEFINITIONS = USE_GUI;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = (
+ ../../../pjsip/include,
+ ../../../pjlib/include,
+ "../../../pjlib-util/include",
+ ../../../pjnath/include,
+ ../../../pjmedia/include,
+ );
+ LIBRARY_SEARCH_PATHS = (
+ ../../../pjlib/lib,
+ "../../../pjlib-util/lib",
+ ../../../pjnath/lib,
+ ../../../pjmedia/lib,
+ ../../../pjsip/lib,
+ ../../../third_party/lib,
+ );
+ ONLY_ACTIVE_ARCH = NO;
+ OTHER_CFLAGS = "";
+ PREBINDING = NO;
+ SDKROOT = iphoneos;
+ };
+ name = Debug;
+ };
+ C01FCF5008A954540054247B /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ GCC_C_LANGUAGE_STANDARD = c99;
+ GCC_PREPROCESSOR_DEFINITIONS = USE_GUI;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = (
+ ../../../pjsip/include,
+ ../../../pjlib/include,
+ "../../../pjlib-util/include",
+ ../../../pjnath/include,
+ ../../../pjmedia/include,
+ );
+ LIBRARY_SEARCH_PATHS = (
+ ../../../pjlib/lib,
+ "../../../pjlib-util/lib",
+ ../../../pjnath/lib,
+ ../../../pjmedia/lib,
+ ../../../pjsip/lib,
+ ../../../third_party/lib,
+ );
+ ONLY_ACTIVE_ARCH = NO;
+ OTHER_CFLAGS = "";
+ PREBINDING = NO;
+ SDKROOT = iphoneos;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "ipjsua" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1D6058940D05DD3E006BFB54 /* Debug */,
+ 1D6058950D05DD3E006BFB54 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ipjsua" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ C01FCF4F08A954540054247B /* Debug */,
+ C01FCF5008A954540054247B /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 29B97313FDCFA39411CA2CEA /* Project object */;
+}
diff --git a/pjsip-apps/src/ipjsua/ipjsua_Prefix.pch b/pjsip-apps/src/ipjsua/ipjsua_Prefix.pch
new file mode 100644
index 0000000..2fe1856
--- /dev/null
+++ b/pjsip-apps/src/ipjsua/ipjsua_Prefix.pch
@@ -0,0 +1,8 @@
+//
+// Prefix header for all source files of the 'ipjsua' target in the 'ipjsua' project
+//
+
+#ifdef __OBJC__
+ #import <Foundation/Foundation.h>
+ #import <UIKit/UIKit.h>
+#endif
diff --git a/pjsip-apps/src/ipjsua/main.m b/pjsip-apps/src/ipjsua/main.m
new file mode 100644
index 0000000..f656b63
--- /dev/null
+++ b/pjsip-apps/src/ipjsua/main.m
@@ -0,0 +1,27 @@
+/* $Id: main.m 3550 2011-05-05 05:33:27Z nanang $ */
+/*
+ * Copyright (C) 2010-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#import <UIKit/UIKit.h>
+
+int main(int argc, char *argv[]) {
+ NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+ int retVal = UIApplicationMain(argc, argv, nil, nil);
+ [pool release];
+ return retVal;
+}
+
diff --git a/pjsip-apps/src/ipjsystest/Classes/RootViewController.h b/pjsip-apps/src/ipjsystest/Classes/RootViewController.h
new file mode 100644
index 0000000..72627d2
--- /dev/null
+++ b/pjsip-apps/src/ipjsystest/Classes/RootViewController.h
@@ -0,0 +1,32 @@
+/* $Id: RootViewController.h 3552 2011-05-05 05:50:48Z nanang $ */
+/*
+ * Copyright (C) 2010-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#import "TestViewController.h"
+
+@interface RootViewController : UITableViewController {
+ NSMutableArray *titles;
+ NSMutableArray *menus;
+
+ TestViewController *testView;
+}
+
+@property (nonatomic, retain) NSMutableArray *titles;
+@property (nonatomic, retain) NSMutableArray *menus;
+@property (nonatomic, retain) TestViewController *testView;
+
+@end
diff --git a/pjsip-apps/src/ipjsystest/Classes/RootViewController.m b/pjsip-apps/src/ipjsystest/Classes/RootViewController.m
new file mode 100644
index 0000000..e4cfab0
--- /dev/null
+++ b/pjsip-apps/src/ipjsystest/Classes/RootViewController.m
@@ -0,0 +1,335 @@
+/* $Id: RootViewController.m 3552 2011-05-05 05:50:48Z nanang $ */
+/*
+ * Copyright (C) 2010-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#import "RootViewController.h"
+#import "gui.h"
+#import "systest.h"
+
+/* Sleep interval duration, change to shorter duration for better
+ * interaction but make sure there is enough time for the other
+ * thread to do what it's supposed to do
+ */
+#define SLEEP_INTERVAL 0.5
+
+@implementation RootViewController
+@synthesize titles;
+@synthesize menus;
+@synthesize testView;
+
+RootViewController *view;
+
+bool systest_initialized;
+bool thread_quit;
+gui_menu *gmenu;
+int section;
+int row;
+const char *ctitle;
+const char *cmsg;
+enum gui_flag cflag;
+
+pj_status_t gui_init(gui_menu *menu)
+{
+ PJ_UNUSED_ARG(menu);
+ return PJ_SUCCESS;
+}
+
+/* Run GUI main loop */
+pj_status_t gui_start(gui_menu *menu)
+{
+ view.titles = [NSMutableArray arrayWithCapacity:menu->submenu_cnt];
+ view.menus = [NSMutableArray arrayWithCapacity:menu->submenu_cnt];
+ NSMutableArray *smenu;
+ for (int i = 0; i < menu->submenu_cnt; i++) {
+ NSString *str = [NSString stringWithFormat:@"%s" , menu->submenus[i]->title];
+ [view.titles addObject: str];
+ smenu = [NSMutableArray arrayWithCapacity:menu->submenus[i]->submenu_cnt];
+ /* We do not need the last two menus of the "Tests" menu (NULL and "Exit"),
+ * so subtract by 2
+ */
+ for (int j = 0; j < menu->submenus[i]->submenu_cnt - (i==0? 2: 0); j++) {
+ str = [NSString stringWithFormat:@"%s" , menu->submenus[i]->submenus[j]->title];
+ [smenu addObject:str];
+ }
+ [view.menus addObject:smenu];
+ }
+ gmenu = menu;
+
+ return PJ_SUCCESS;
+}
+
+/* Signal GUI mainloop to stop */
+void gui_destroy(void)
+{
+}
+
+/* AUX: display messagebox */
+enum gui_key gui_msgbox(const char *title, const char *message, enum gui_flag flag)
+{
+ ctitle = title;
+ cmsg = message;
+ cflag = flag;
+ [view performSelectorOnMainThread:@selector(showMsg) withObject:nil waitUntilDone:YES];
+
+ view.testView.key = 0;
+ while(view.testView.key == 0) {
+ /* Let the main thread do its job (refresh the view) while we wait for
+ * user interaction (button click)
+ */
+ [NSThread sleepForTimeInterval:SLEEP_INTERVAL];
+ }
+
+ if (view.testView.key == 1)
+ return KEY_OK;
+ else
+ return (flag == WITH_YESNO? KEY_NO: KEY_CANCEL);
+}
+
+/* AUX: sleep */
+void gui_sleep(unsigned sec)
+{
+ [NSThread sleepForTimeInterval:sec];
+}
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ view = self;
+
+ /* Get a writable path for output files */
+ NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
+ NSString *documentsDirectory = [paths objectAtIndex:0];
+ [documentsDirectory getCString:doc_path maxLength:PATH_LENGTH encoding:NSASCIIStringEncoding];
+ strncat(doc_path, "/", PATH_LENGTH);
+
+ /* Get path for our test resources (the wav files) */
+ NSString *resPath = [[NSBundle mainBundle] resourcePath];
+ [resPath getCString:res_path maxLength:PATH_LENGTH encoding:NSASCIIStringEncoding];
+ strncat(res_path, "/", PATH_LENGTH);
+
+ systest_initialized = false;
+ thread_quit = false;
+ [NSThread detachNewThreadSelector:@selector(startTest) toTarget:self withObject:nil];
+ /* Let our new thread initialize */
+ while (!systest_initialized) {
+ [NSThread sleepForTimeInterval:SLEEP_INTERVAL];
+ }
+
+ // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
+ // self.navigationItem.rightBarButtonItem = self.editButtonItem;
+}
+
+/*
+ - (void)viewWillAppear:(BOOL)animated {
+ [super viewWillAppear:animated];
+ }
+ */
+/*
+ - (void)viewDidAppear:(BOOL)animated {
+ [super viewDidAppear:animated];
+ }
+ */
+/*
+ - (void)viewWillDisappear:(BOOL)animated {
+ [super viewWillDisappear:animated];
+ }
+ */
+/*
+ - (void)viewDidDisappear:(BOOL)animated {
+ [super viewDidDisappear:animated];
+ }
+ */
+
+/*
+ // Override to allow orientations other than the default portrait orientation.
+ - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
+ // Return YES for supported orientations.
+ return (interfaceOrientation == UIInterfaceOrientationPortrait);
+ }
+ */
+
+- (void)didReceiveMemoryWarning {
+ // Releases the view if it doesn't have a superview.
+ [super didReceiveMemoryWarning];
+
+ // Release any cached data, images, etc that aren't in use.
+}
+
+- (void)viewDidUnload {
+ // Release anything that can be recreated in viewDidLoad or on demand.
+ // e.g. self.myOutlet = nil;
+ self.titles = nil;
+ self.menus = nil;
+
+ thread_quit = true;
+ [NSThread sleepForTimeInterval:SLEEP_INTERVAL];
+}
+
+
+#pragma mark Table view methods
+
+
+- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
+ return [titles count];
+}
+
+
+// Customize the number of rows in the table view.
+- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
+ return [[menus objectAtIndex:section] count];
+}
+
+
+- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
+ // The header for the section is the region name -- get this from the region at the section index.
+ return [titles objectAtIndex:section];
+}
+
+// Customize the appearance of table view cells.
+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
+
+ static NSString *CellIdentifier = @"Cell";
+
+ UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
+ if (cell == nil) {
+ cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
+ }
+
+ // Configure the cell.
+ cell.textLabel.text = [[menus objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
+
+ return cell;
+}
+
+- (void)startTest {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ if (systest_init() != PJ_SUCCESS) {
+ [pool release];
+ return;
+ }
+
+ systest_run();
+
+ systest_initialized = 1;
+ while(!thread_quit) {
+ section = -1;
+ while (section == -1) {
+ [NSThread sleepForTimeInterval:SLEEP_INTERVAL];
+ }
+ (*gmenu->submenus[section]->submenus[row]->handler)();
+ cmsg = NULL;
+ [view performSelectorOnMainThread:@selector(showMsg) withObject:nil waitUntilDone:YES];
+ }
+
+ systest_deinit();
+ [pool release];
+}
+
+- (void)showMsg {
+ if (cmsg == NULL) {
+ self.testView.testDesc.text = [self.testView.testDesc.text stringByAppendingString: @"Finished"];
+ [self.testView.testDesc scrollRangeToVisible:NSMakeRange([self.testView.testDesc.text length] - 1, 1)];
+ [self.testView.button1 setHidden:true];
+ [self.testView.button2 setHidden:true];
+ return;
+ }
+ self.testView.title = [NSString stringWithFormat:@"%s", ctitle];
+ self.testView.testDesc.text = [self.testView.testDesc.text stringByAppendingString: [NSString stringWithFormat:@"%s\n\n", cmsg]];
+ [self.testView.testDesc scrollRangeToVisible:NSMakeRange([self.testView.testDesc.text length] - 1, 1)];
+
+ [self.testView.button1 setHidden:false];
+ [self.testView.button2 setHidden:false];
+ if (cflag == WITH_YESNO) {
+ [self.testView.button1 setTitle:@"Yes" forState:UIControlStateNormal];
+ [self.testView.button2 setTitle:@"No" forState:UIControlStateNormal];
+ } else if (cflag == WITH_OK) {
+ [self.testView.button1 setTitle:@"OK" forState:UIControlStateNormal];
+ [self.testView.button2 setHidden:true];
+ } else if (cflag == WITH_OKCANCEL) {
+ [self.testView.button1 setTitle:@"OK" forState:UIControlStateNormal];
+ [self.testView.button2 setTitle:@"Cancel" forState:UIControlStateNormal];
+ }
+}
+
+
+// Override to support row selection in the table view.
+- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
+
+ // Navigation logic may go here -- for example, create and push another view controller.
+ // AnotherViewController *anotherViewController = [[AnotherViewController alloc] initWithNibName:@"AnotherView" bundle:nil];
+ // [self.navigationController pushViewController:anotherViewController animated:YES];
+ // [anotherViewController release];
+
+ if (self.testView == nil) {
+ self.testView = [[TestViewController alloc] initWithNibName:@"TestViewController" bundle:[NSBundle mainBundle]];
+ }
+
+ [self.navigationController pushViewController:self.testView animated:YES];
+ self.testView.title = [[menus objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
+ self.testView.testDesc.text = @"";
+ section = indexPath.section;
+ row = indexPath.row;
+}
+
+
+/*
+ // Override to support conditional editing of the table view.
+ - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
+ // Return NO if you do not want the specified item to be editable.
+ return YES;
+ }
+ */
+
+
+/*
+ // Override to support editing the table view.
+ - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
+
+ if (editingStyle == UITableViewCellEditingStyleDelete) {
+ // Delete the row from the data source.
+ [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
+ }
+ else if (editingStyle == UITableViewCellEditingStyleInsert) {
+ // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
+ }
+ }
+ */
+
+
+/*
+ // Override to support rearranging the table view.
+ - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
+ }
+ */
+
+
+/*
+ // Override to support conditional rearranging of the table view.
+ - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
+ // Return NO if you do not want the item to be re-orderable.
+ return YES;
+ }
+ */
+
+
+- (void)dealloc {
+ [super dealloc];
+}
+
+
+@end
+
diff --git a/pjsip-apps/src/ipjsystest/Classes/TestViewController.h b/pjsip-apps/src/ipjsystest/Classes/TestViewController.h
new file mode 100644
index 0000000..9cbc057
--- /dev/null
+++ b/pjsip-apps/src/ipjsystest/Classes/TestViewController.h
@@ -0,0 +1,35 @@
+/* $Id: TestViewController.h 3552 2011-05-05 05:50:48Z nanang $ */
+/*
+ * Copyright (C) 2010-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#import <UIKit/UIKit.h>
+
+
+@interface TestViewController : UIViewController {
+ IBOutlet UITextView *testDesc;
+ IBOutlet UIButton *button1;
+ IBOutlet UIButton *button2;
+
+ NSInteger key;
+}
+
+@property (nonatomic, retain) IBOutlet UITextView *testDesc;
+@property (nonatomic, retain) IBOutlet UIButton *button1;
+@property (nonatomic, retain) IBOutlet UIButton *button2;
+@property (nonatomic) NSInteger key;
+
+@end
diff --git a/pjsip-apps/src/ipjsystest/Classes/TestViewController.m b/pjsip-apps/src/ipjsystest/Classes/TestViewController.m
new file mode 100644
index 0000000..404a0e8
--- /dev/null
+++ b/pjsip-apps/src/ipjsystest/Classes/TestViewController.m
@@ -0,0 +1,91 @@
+/* $Id: TestViewController.m 3552 2011-05-05 05:50:48Z nanang $ */
+/*
+ * Copyright (C) 2010-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#import "TestViewController.h"
+
+@implementation TestViewController
+@synthesize testDesc;
+@synthesize button1;
+@synthesize button2;
+@synthesize key;
+
+- (void)button1Pressed:(id)sender {
+ self.key = 1;
+ [self.button1 setHidden:true];
+ [self.button2 setHidden:true];
+}
+
+- (void)button2Pressed:(id)sender {
+ self.key = 2;
+ [self.button1 setHidden:true];
+ [self.button2 setHidden:true];
+}
+
+/*
+ // The designated initializer. Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
+ - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
+ if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
+ // Custom initialization
+ }
+ return self;
+ }
+ */
+
+/*
+ // Implement loadView to create a view hierarchy programmatically, without using a nib.
+ - (void)loadView {
+ }
+ */
+
+
+// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ [button1 addTarget:self action:@selector(button1Pressed:) forControlEvents:(UIControlEvents)UIControlEventTouchDown];
+ [button2 addTarget:self action:@selector(button2Pressed:) forControlEvents:(UIControlEvents)UIControlEventTouchDown];
+ [testDesc setEditable:false];
+}
+
+/*
+ // Override to allow orientations other than the default portrait orientation.
+ - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
+ // Return YES for supported orientations
+ return (interfaceOrientation == UIInterfaceOrientationPortrait);
+ }
+ */
+
+- (void)didReceiveMemoryWarning {
+ // Releases the view if it doesn't have a superview.
+ [super didReceiveMemoryWarning];
+
+ // Release any cached data, images, etc that aren't in use.
+}
+
+- (void)viewDidUnload {
+ // Release any retained subviews of the main view.
+ // e.g. self.myOutlet = nil;
+}
+
+
+- (void)dealloc {
+ [super dealloc];
+}
+
+
+@end
diff --git a/pjsip-apps/src/ipjsystest/Classes/ipjsystestAppDelegate.h b/pjsip-apps/src/ipjsystest/Classes/ipjsystestAppDelegate.h
new file mode 100644
index 0000000..ddce05c
--- /dev/null
+++ b/pjsip-apps/src/ipjsystest/Classes/ipjsystestAppDelegate.h
@@ -0,0 +1,29 @@
+/* $Id: ipjsystestAppDelegate.h 3552 2011-05-05 05:50:48Z nanang $ */
+/*
+ * Copyright (C) 2010-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+@interface ipjsystestAppDelegate : NSObject <UIApplicationDelegate> {
+
+ UIWindow *window;
+ UINavigationController *navigationController;
+}
+
+@property (nonatomic, retain) IBOutlet UIWindow *window;
+@property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
+
+@end
+
diff --git a/pjsip-apps/src/ipjsystest/Classes/ipjsystestAppDelegate.m b/pjsip-apps/src/ipjsystest/Classes/ipjsystestAppDelegate.m
new file mode 100644
index 0000000..f206348
--- /dev/null
+++ b/pjsip-apps/src/ipjsystest/Classes/ipjsystestAppDelegate.m
@@ -0,0 +1,55 @@
+/* $Id: ipjsystestAppDelegate.m 3552 2011-05-05 05:50:48Z nanang $ */
+/*
+ * Copyright (C) 2010-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#import "ipjsystestAppDelegate.h"
+#import "RootViewController.h"
+
+
+@implementation ipjsystestAppDelegate
+
+@synthesize window;
+@synthesize navigationController;
+
+#pragma mark -
+#pragma mark Application lifecycle
+
+- (void)applicationDidFinishLaunching:(UIApplication *)application {
+
+ // Override point for customization after app launch
+ [window addSubview:[navigationController view]];
+ [window makeKeyAndVisible];
+}
+
+
+- (void)applicationWillTerminate:(UIApplication *)application {
+ // Save data if appropriate
+}
+
+
+#pragma mark -
+#pragma mark Memory management
+
+- (void)dealloc {
+ [navigationController release];
+ [window release];
+ [super dealloc];
+}
+
+
+@end
+
diff --git a/pjsip-apps/src/ipjsystest/MainWindow.xib b/pjsip-apps/src/ipjsystest/MainWindow.xib
new file mode 100644
index 0000000..8b08922
--- /dev/null
+++ b/pjsip-apps/src/ipjsystest/MainWindow.xib
@@ -0,0 +1,507 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="7.10">
+ <data>
+ <int key="IBDocument.SystemTarget">784</int>
+ <string key="IBDocument.SystemVersion">10C540</string>
+ <string key="IBDocument.InterfaceBuilderVersion">740</string>
+ <string key="IBDocument.AppKitVersion">1038.25</string>
+ <string key="IBDocument.HIToolboxVersion">458.00</string>
+ <object class="NSMutableDictionary" key="IBDocument.PluginVersions">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string key="NS.object.0">62</string>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <integer value="13"/>
+ </object>
+ <object class="NSArray" key="IBDocument.PluginDependencies">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.Metadata">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys" id="0">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBProxyObject" id="841351856">
+ <string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
+ </object>
+ <object class="IBProxyObject" id="302016328">
+ <string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
+ </object>
+ <object class="IBUICustomObject" id="664661524"/>
+ <object class="IBUIWindow" id="380026005">
+ <nil key="NSNextResponder"/>
+ <int key="NSvFlags">1316</int>
+ <object class="NSPSMatrix" key="NSFrameMatrix"/>
+ <string key="NSFrameSize">{320, 480}</string>
+ <object class="NSColor" key="IBUIBackgroundColor">
+ <int key="NSColorSpace">1</int>
+ <bytes key="NSRGB">MSAxIDEAA</bytes>
+ </object>
+ <bool key="IBUIOpaque">NO</bool>
+ <bool key="IBUIClearsContextBeforeDrawing">NO</bool>
+ <object class="IBUISimulatedStatusBarMetrics" key="IBUISimulatedStatusBarMetrics"/>
+ </object>
+ <object class="IBUINavigationController" id="701001926">
+ <object class="IBUISimulatedStatusBarMetrics" key="IBUISimulatedStatusBarMetrics"/>
+ <object class="IBUINavigationBar" key="IBUINavigationBar" id="207850653">
+ <nil key="NSNextResponder"/>
+ <int key="NSvFlags">256</int>
+ <string key="NSFrameSize">{0, 0}</string>
+ <bool key="IBUIOpaque">NO</bool>
+ <bool key="IBUIClipsSubviews">YES</bool>
+ <bool key="IBUIMultipleTouchEnabled">YES</bool>
+ </object>
+ <object class="NSArray" key="IBUIViewControllers">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBUIViewController" id="619226028">
+ <object class="IBUINavigationItem" key="IBUINavigationItem" id="394667715">
+ <reference key="IBUINavigationBar"/>
+ <string key="IBUITitle">ipjsystest</string>
+ </object>
+ <reference key="IBUIParentViewController" ref="701001926"/>
+ <string key="IBUINibName">RootViewController</string>
+ <object class="IBUISimulatedStatusBarMetrics" key="IBUISimulatedStatusBarMetrics"/>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="IBObjectContainer" key="IBDocument.Objects">
+ <object class="NSMutableArray" key="connectionRecords">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">delegate</string>
+ <reference key="source" ref="841351856"/>
+ <reference key="destination" ref="664661524"/>
+ </object>
+ <int key="connectionID">4</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">window</string>
+ <reference key="source" ref="664661524"/>
+ <reference key="destination" ref="380026005"/>
+ </object>
+ <int key="connectionID">5</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">navigationController</string>
+ <reference key="source" ref="664661524"/>
+ <reference key="destination" ref="701001926"/>
+ </object>
+ <int key="connectionID">15</int>
+ </object>
+ </object>
+ <object class="IBMutableOrderedSet" key="objectRecords">
+ <object class="NSArray" key="orderedObjects">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBObjectRecord">
+ <int key="objectID">0</int>
+ <reference key="object" ref="0"/>
+ <reference key="children" ref="1000"/>
+ <nil key="parent"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">2</int>
+ <reference key="object" ref="380026005"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-1</int>
+ <reference key="object" ref="841351856"/>
+ <reference key="parent" ref="0"/>
+ <string key="objectName">File's Owner</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">3</int>
+ <reference key="object" ref="664661524"/>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-2</int>
+ <reference key="object" ref="302016328"/>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">9</int>
+ <reference key="object" ref="701001926"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="207850653"/>
+ <reference ref="619226028"/>
+ </object>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">11</int>
+ <reference key="object" ref="207850653"/>
+ <reference key="parent" ref="701001926"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">13</int>
+ <reference key="object" ref="619226028"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="394667715"/>
+ </object>
+ <reference key="parent" ref="701001926"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">14</int>
+ <reference key="object" ref="394667715"/>
+ <reference key="parent" ref="619226028"/>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="flattenedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>-1.CustomClassName</string>
+ <string>-2.CustomClassName</string>
+ <string>11.IBPluginDependency</string>
+ <string>13.CustomClassName</string>
+ <string>13.IBPluginDependency</string>
+ <string>2.IBAttributePlaceholdersKey</string>
+ <string>2.IBEditorWindowLastContentRect</string>
+ <string>2.IBPluginDependency</string>
+ <string>3.CustomClassName</string>
+ <string>3.IBPluginDependency</string>
+ <string>9.IBEditorWindowLastContentRect</string>
+ <string>9.IBPluginDependency</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>UIApplication</string>
+ <string>UIResponder</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>RootViewController</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <object class="NSMutableDictionary">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <string>{{673, 376}, {320, 480}}</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>ipjsystestAppDelegate</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>{{500, 343}, {320, 480}}</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="unlocalizedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="activeLocalization"/>
+ <object class="NSMutableDictionary" key="localizations">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="sourceID"/>
+ <int key="maxID">20</int>
+ </object>
+ <object class="IBClassDescriber" key="IBDocument.Classes">
+ <object class="NSMutableArray" key="referencedPartialClassDescriptions">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBPartialClassDescription">
+ <string key="className">RootViewController</string>
+ <string key="superclassName">UITableViewController</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">Classes/RootViewController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">ipjsystestAppDelegate</string>
+ <string key="superclassName">NSObject</string>
+ <object class="NSMutableDictionary" key="outlets">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>navigationController</string>
+ <string>window</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>UINavigationController</string>
+ <string>UIWindow</string>
+ </object>
+ </object>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">Classes/ipjsystestAppDelegate.h</string>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSError.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSFileManager.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSKeyValueCoding.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSKeyValueObserving.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSKeyedArchiver.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSNetServices.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSObject.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSPort.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSRunLoop.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSStream.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSThread.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSURL.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSURLConnection.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSXMLParser.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIAccessibility.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UINibLoading.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier" id="457547627">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIResponder.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIApplication</string>
+ <string key="superclassName">UIResponder</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIApplication.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIBarButtonItem</string>
+ <string key="superclassName">UIBarItem</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIBarButtonItem.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIBarItem</string>
+ <string key="superclassName">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIBarItem.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UINavigationBar</string>
+ <string key="superclassName">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier" id="719966566">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UINavigationBar.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UINavigationController</string>
+ <string key="superclassName">UIViewController</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier" id="737619010">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UINavigationController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UINavigationItem</string>
+ <string key="superclassName">NSObject</string>
+ <reference key="sourceIdentifier" ref="719966566"/>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIResponder</string>
+ <string key="superclassName">NSObject</string>
+ <reference key="sourceIdentifier" ref="457547627"/>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UISearchBar</string>
+ <string key="superclassName">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UISearchBar.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UISearchDisplayController</string>
+ <string key="superclassName">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UISearchDisplayController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UITableViewController</string>
+ <string key="superclassName">UIViewController</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UITableViewController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UITextField.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIView</string>
+ <string key="superclassName">UIResponder</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIView.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIViewController</string>
+ <reference key="sourceIdentifier" ref="737619010"/>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIViewController</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UITabBarController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIViewController</string>
+ <string key="superclassName">UIResponder</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIViewController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIWindow</string>
+ <string key="superclassName">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIWindow.h</string>
+ </object>
+ </object>
+ </object>
+ </object>
+ <int key="IBDocument.localizationMode">0</int>
+ <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3</string>
+ <integer value="3100" key="NS.object.0"/>
+ </object>
+ <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
+ <string key="IBDocument.LastKnownRelativeProjectPath">ipjsystest.xcodeproj</string>
+ <int key="IBDocument.defaultPropertyAccessControl">3</int>
+ <string key="IBCocoaTouchPluginVersion">3.1</string>
+ </data>
+</archive>
diff --git a/pjsip-apps/src/ipjsystest/RootViewController.xib b/pjsip-apps/src/ipjsystest/RootViewController.xib
new file mode 100644
index 0000000..5c44ed2
--- /dev/null
+++ b/pjsip-apps/src/ipjsystest/RootViewController.xib
@@ -0,0 +1,380 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="7.10">
+ <data>
+ <int key="IBDocument.SystemTarget">784</int>
+ <string key="IBDocument.SystemVersion">10A405</string>
+ <string key="IBDocument.InterfaceBuilderVersion">732</string>
+ <string key="IBDocument.AppKitVersion">1031</string>
+ <string key="IBDocument.HIToolboxVersion">432.00</string>
+ <object class="NSMutableDictionary" key="IBDocument.PluginVersions">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string key="NS.object.0">62</string>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <integer value="2"/>
+ </object>
+ <object class="NSArray" key="IBDocument.PluginDependencies">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.Metadata">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys" id="0">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBProxyObject" id="841351856">
+ <string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
+ </object>
+ <object class="IBProxyObject" id="371349661">
+ <string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
+ </object>
+ <object class="IBUITableView" id="709618507">
+ <reference key="NSNextResponder"/>
+ <int key="NSvFlags">274</int>
+ <string key="NSFrameSize">{320, 247}</string>
+ <reference key="NSSuperview"/>
+ <object class="NSColor" key="IBUIBackgroundColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MQA</bytes>
+ </object>
+ <bool key="IBUIOpaque">NO</bool>
+ <bool key="IBUIClipsSubviews">YES</bool>
+ <bool key="IBUIClearsContextBeforeDrawing">NO</bool>
+ <bool key="IBUIBouncesZoom">NO</bool>
+ <int key="IBUISeparatorStyle">1</int>
+ <int key="IBUISectionIndexMinimumDisplayRowCount">0</int>
+ <bool key="IBUIShowsSelectionImmediatelyOnTouchBegin">YES</bool>
+ <float key="IBUIRowHeight">44</float>
+ <float key="IBUISectionHeaderHeight">22</float>
+ <float key="IBUISectionFooterHeight">22</float>
+ </object>
+ </object>
+ <object class="IBObjectContainer" key="IBDocument.Objects">
+ <object class="NSMutableArray" key="connectionRecords">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">view</string>
+ <reference key="source" ref="841351856"/>
+ <reference key="destination" ref="709618507"/>
+ </object>
+ <int key="connectionID">3</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">dataSource</string>
+ <reference key="source" ref="709618507"/>
+ <reference key="destination" ref="841351856"/>
+ </object>
+ <int key="connectionID">4</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">delegate</string>
+ <reference key="source" ref="709618507"/>
+ <reference key="destination" ref="841351856"/>
+ </object>
+ <int key="connectionID">5</int>
+ </object>
+ </object>
+ <object class="IBMutableOrderedSet" key="objectRecords">
+ <object class="NSArray" key="orderedObjects">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBObjectRecord">
+ <int key="objectID">0</int>
+ <reference key="object" ref="0"/>
+ <reference key="children" ref="1000"/>
+ <nil key="parent"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-1</int>
+ <reference key="object" ref="841351856"/>
+ <reference key="parent" ref="0"/>
+ <string key="objectName">File's Owner</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-2</int>
+ <reference key="object" ref="371349661"/>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">2</int>
+ <reference key="object" ref="709618507"/>
+ <reference key="parent" ref="0"/>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="flattenedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>-1.CustomClassName</string>
+ <string>-2.CustomClassName</string>
+ <string>2.IBEditorWindowLastContentRect</string>
+ <string>2.IBPluginDependency</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>RootViewController</string>
+ <string>UIResponder</string>
+ <string>{{0, 598}, {320, 247}}</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="unlocalizedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="activeLocalization"/>
+ <object class="NSMutableDictionary" key="localizations">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="sourceID"/>
+ <int key="maxID">5</int>
+ </object>
+ <object class="IBClassDescriber" key="IBDocument.Classes">
+ <object class="NSMutableArray" key="referencedPartialClassDescriptions">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBPartialClassDescription">
+ <string key="className">RootViewController</string>
+ <string key="superclassName">UITableViewController</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">Classes/RootViewController.h</string>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSError.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSFileManager.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSKeyValueCoding.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSKeyValueObserving.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSKeyedArchiver.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSNetServices.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSObject.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSPort.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSRunLoop.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSStream.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSThread.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSURL.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSURLConnection.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSXMLParser.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIAccessibility.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UINibLoading.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier" id="654420027">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIResponder.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIResponder</string>
+ <string key="superclassName">NSObject</string>
+ <reference key="sourceIdentifier" ref="654420027"/>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIScrollView</string>
+ <string key="superclassName">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIScrollView.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UISearchBar</string>
+ <string key="superclassName">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UISearchBar.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UISearchDisplayController</string>
+ <string key="superclassName">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UISearchDisplayController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UITableView</string>
+ <string key="superclassName">UIScrollView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UITableView.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UITableViewController</string>
+ <string key="superclassName">UIViewController</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UITableViewController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UITextField.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIView</string>
+ <string key="superclassName">UIResponder</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIView.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIViewController</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UINavigationController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIViewController</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UITabBarController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIViewController</string>
+ <string key="superclassName">UIResponder</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIViewController.h</string>
+ </object>
+ </object>
+ </object>
+ </object>
+ <int key="IBDocument.localizationMode">0</int>
+ <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS</string>
+ <integer value="784" key="NS.object.0"/>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3</string>
+ <integer value="3100" key="NS.object.0"/>
+ </object>
+ <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
+ <string key="IBDocument.LastKnownRelativeProjectPath">ipjsystest.xcodeproj</string>
+ <int key="IBDocument.defaultPropertyAccessControl">3</int>
+ <string key="IBCocoaTouchPluginVersion">3.1</string>
+ </data>
+</archive>
diff --git a/pjsip-apps/src/ipjsystest/TestViewController.xib b/pjsip-apps/src/ipjsystest/TestViewController.xib
new file mode 100644
index 0000000..3a66c09
--- /dev/null
+++ b/pjsip-apps/src/ipjsystest/TestViewController.xib
@@ -0,0 +1,496 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="7.10">
+ <data>
+ <int key="IBDocument.SystemTarget">784</int>
+ <string key="IBDocument.SystemVersion">10C540</string>
+ <string key="IBDocument.InterfaceBuilderVersion">740</string>
+ <string key="IBDocument.AppKitVersion">1038.25</string>
+ <string key="IBDocument.HIToolboxVersion">458.00</string>
+ <object class="NSMutableDictionary" key="IBDocument.PluginVersions">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string key="NS.object.0">62</string>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <integer value="1"/>
+ </object>
+ <object class="NSArray" key="IBDocument.PluginDependencies">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.Metadata">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys" id="0">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBProxyObject" id="372490531">
+ <string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
+ </object>
+ <object class="IBProxyObject" id="711762367">
+ <string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
+ </object>
+ <object class="IBUIView" id="191373211">
+ <reference key="NSNextResponder"/>
+ <int key="NSvFlags">292</int>
+ <object class="NSMutableArray" key="NSSubviews">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBUITextView" id="613869543">
+ <reference key="NSNextResponder" ref="191373211"/>
+ <int key="NSvFlags">274</int>
+ <string key="NSFrameSize">{320, 358}</string>
+ <reference key="NSSuperview" ref="191373211"/>
+ <bool key="IBUIOpaque">NO</bool>
+ <bool key="IBUIClipsSubviews">YES</bool>
+ <bool key="IBUIMultipleTouchEnabled">YES</bool>
+ <bool key="IBUIShowsHorizontalScrollIndicator">NO</bool>
+ <bool key="IBUIDelaysContentTouches">NO</bool>
+ <bool key="IBUICanCancelContentTouches">NO</bool>
+ <bool key="IBUIBouncesZoom">NO</bool>
+ <string key="IBUIText">Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda.</string>
+ <object class="IBUITextInputTraits" key="IBUITextInputTraits">
+ <int key="IBUIAutocapitalizationType">2</int>
+ </object>
+ </object>
+ <object class="IBUIButton" id="669764012">
+ <reference key="NSNextResponder" ref="191373211"/>
+ <int key="NSvFlags">292</int>
+ <string key="NSFrame">{{228, 366}, {72, 37}}</string>
+ <reference key="NSSuperview" ref="191373211"/>
+ <bool key="IBUIOpaque">NO</bool>
+ <bool key="IBUIClearsContextBeforeDrawing">NO</bool>
+ <int key="IBUIContentHorizontalAlignment">0</int>
+ <int key="IBUIContentVerticalAlignment">0</int>
+ <object class="NSFont" key="IBUIFont" id="892040736">
+ <string key="NSName">Helvetica-Bold</string>
+ <double key="NSSize">15</double>
+ <int key="NSfFlags">16</int>
+ </object>
+ <int key="IBUIButtonType">1</int>
+ <string key="IBUINormalTitle">OK</string>
+ <object class="NSColor" key="IBUIHighlightedTitleColor" id="501426315">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MQA</bytes>
+ </object>
+ <object class="NSColor" key="IBUINormalTitleColor">
+ <int key="NSColorSpace">1</int>
+ <bytes key="NSRGB">MC4xOTYwNzg0MyAwLjMwOTgwMzkzIDAuNTIxNTY4NjYAA</bytes>
+ </object>
+ <object class="NSColor" key="IBUINormalTitleShadowColor" id="88580318">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MC41AA</bytes>
+ </object>
+ </object>
+ <object class="IBUIButton" id="970816430">
+ <reference key="NSNextResponder" ref="191373211"/>
+ <int key="NSvFlags">292</int>
+ <string key="NSFrame">{{141, 366}, {72, 37}}</string>
+ <reference key="NSSuperview" ref="191373211"/>
+ <bool key="IBUIOpaque">NO</bool>
+ <bool key="IBUIClearsContextBeforeDrawing">NO</bool>
+ <int key="IBUIContentHorizontalAlignment">0</int>
+ <int key="IBUIContentVerticalAlignment">0</int>
+ <reference key="IBUIFont" ref="892040736"/>
+ <int key="IBUIButtonType">1</int>
+ <string key="IBUINormalTitle">Cancel</string>
+ <reference key="IBUIHighlightedTitleColor" ref="501426315"/>
+ <object class="NSColor" key="IBUINormalTitleColor">
+ <int key="NSColorSpace">1</int>
+ <bytes key="NSRGB">MC4xOTYwNzg0MyAwLjMwOTgwMzkzIDAuNTIxNTY4NjYAA</bytes>
+ </object>
+ <reference key="IBUINormalTitleShadowColor" ref="88580318"/>
+ </object>
+ </object>
+ <string key="NSFrameSize">{320, 460}</string>
+ <reference key="NSSuperview"/>
+ <object class="NSColor" key="IBUIBackgroundColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MQA</bytes>
+ <object class="NSColorSpace" key="NSCustomColorSpace">
+ <int key="NSID">2</int>
+ </object>
+ </object>
+ <object class="IBUISimulatedStatusBarMetrics" key="IBUISimulatedStatusBarMetrics"/>
+ </object>
+ </object>
+ <object class="IBObjectContainer" key="IBDocument.Objects">
+ <object class="NSMutableArray" key="connectionRecords">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">testDesc</string>
+ <reference key="source" ref="372490531"/>
+ <reference key="destination" ref="613869543"/>
+ </object>
+ <int key="connectionID">4</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">view</string>
+ <reference key="source" ref="372490531"/>
+ <reference key="destination" ref="191373211"/>
+ </object>
+ <int key="connectionID">5</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">button1</string>
+ <reference key="source" ref="372490531"/>
+ <reference key="destination" ref="669764012"/>
+ </object>
+ <int key="connectionID">8</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">button2</string>
+ <reference key="source" ref="372490531"/>
+ <reference key="destination" ref="970816430"/>
+ </object>
+ <int key="connectionID">9</int>
+ </object>
+ </object>
+ <object class="IBMutableOrderedSet" key="objectRecords">
+ <object class="NSArray" key="orderedObjects">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBObjectRecord">
+ <int key="objectID">0</int>
+ <reference key="object" ref="0"/>
+ <reference key="children" ref="1000"/>
+ <nil key="parent"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">1</int>
+ <reference key="object" ref="191373211"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="613869543"/>
+ <reference ref="669764012"/>
+ <reference ref="970816430"/>
+ </object>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-1</int>
+ <reference key="object" ref="372490531"/>
+ <reference key="parent" ref="0"/>
+ <string key="objectName">File's Owner</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-2</int>
+ <reference key="object" ref="711762367"/>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">3</int>
+ <reference key="object" ref="613869543"/>
+ <reference key="parent" ref="191373211"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">6</int>
+ <reference key="object" ref="669764012"/>
+ <reference key="parent" ref="191373211"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">7</int>
+ <reference key="object" ref="970816430"/>
+ <reference key="parent" ref="191373211"/>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="flattenedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>-1.CustomClassName</string>
+ <string>-2.CustomClassName</string>
+ <string>1.IBEditorWindowLastContentRect</string>
+ <string>1.IBPluginDependency</string>
+ <string>3.IBPluginDependency</string>
+ <string>6.IBPluginDependency</string>
+ <string>7.IBPluginDependency</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>TestViewController</string>
+ <string>UIResponder</string>
+ <string>{{461, 327}, {320, 480}}</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="unlocalizedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="activeLocalization"/>
+ <object class="NSMutableDictionary" key="localizations">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="sourceID"/>
+ <int key="maxID">9</int>
+ </object>
+ <object class="IBClassDescriber" key="IBDocument.Classes">
+ <object class="NSMutableArray" key="referencedPartialClassDescriptions">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBPartialClassDescription">
+ <string key="className">TestViewController</string>
+ <string key="superclassName">UIViewController</string>
+ <object class="NSMutableDictionary" key="outlets">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>button1</string>
+ <string>button2</string>
+ <string>testDesc</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>UIButton</string>
+ <string>UIButton</string>
+ <string>UITextView</string>
+ </object>
+ </object>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">Classes/TestViewController.h</string>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSError.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSFileManager.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSKeyValueCoding.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSKeyValueObserving.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSKeyedArchiver.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSNetServices.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSObject.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSPort.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSRunLoop.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSStream.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSThread.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSURL.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSURLConnection.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSXMLParser.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIAccessibility.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UINibLoading.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier" id="27432675">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIResponder.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIButton</string>
+ <string key="superclassName">UIControl</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIButton.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIControl</string>
+ <string key="superclassName">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIControl.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIResponder</string>
+ <string key="superclassName">NSObject</string>
+ <reference key="sourceIdentifier" ref="27432675"/>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIScrollView</string>
+ <string key="superclassName">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIScrollView.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UISearchBar</string>
+ <string key="superclassName">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UISearchBar.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UISearchDisplayController</string>
+ <string key="superclassName">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UISearchDisplayController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UITextView</string>
+ <string key="superclassName">UIScrollView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UITextView.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UITextField.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIView</string>
+ <string key="superclassName">UIResponder</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIView.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIViewController</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UINavigationController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIViewController</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UITabBarController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIViewController</string>
+ <string key="superclassName">UIResponder</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIViewController.h</string>
+ </object>
+ </object>
+ </object>
+ </object>
+ <int key="IBDocument.localizationMode">0</int>
+ <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3</string>
+ <integer value="3100" key="NS.object.0"/>
+ </object>
+ <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
+ <string key="IBDocument.LastKnownRelativeProjectPath">ipjsystest.xcodeproj</string>
+ <int key="IBDocument.defaultPropertyAccessControl">3</int>
+ <string key="IBCocoaTouchPluginVersion">3.1</string>
+ </data>
+</archive>
diff --git a/pjsip-apps/src/ipjsystest/ipjsystest-Info.plist b/pjsip-apps/src/ipjsystest/ipjsystest-Info.plist
new file mode 100644
index 0000000..e15a90b
--- /dev/null
+++ b/pjsip-apps/src/ipjsystest/ipjsystest-Info.plist
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleDisplayName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+ <key>CFBundleIconFile</key>
+ <string></string>
+ <key>CFBundleIdentifier</key>
+ <string>com.teluu.${PRODUCT_NAME:rfc1034identifier}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+ <key>LSRequiresIPhoneOS</key>
+ <true/>
+ <key>NSMainNibFile</key>
+ <string>MainWindow</string>
+ <key>UIBackgroundModes</key>
+ <array>
+ <string>audio</string>
+ </array>
+</dict>
+</plist>
diff --git a/pjsip-apps/src/ipjsystest/ipjsystest.xcodeproj/project.pbxproj b/pjsip-apps/src/ipjsystest/ipjsystest.xcodeproj/project.pbxproj
new file mode 100755
index 0000000..2709d61
--- /dev/null
+++ b/pjsip-apps/src/ipjsystest/ipjsystest.xcodeproj/project.pbxproj
@@ -0,0 +1,434 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 45;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 1D3623260D0F684500981E51 /* ipjsystestAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D3623250D0F684500981E51 /* ipjsystestAppDelegate.m */; };
+ 1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; };
+ 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; };
+ 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; };
+ 2892E4100DC94CBA00A64D0F /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2892E40F0DC94CBA00A64D0F /* CoreGraphics.framework */; };
+ 28AD73600D9D9599002E5188 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD735F0D9D9599002E5188 /* MainWindow.xib */; };
+ 28C286E10D94DF7D0034E888 /* RootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 28C286E00D94DF7D0034E888 /* RootViewController.m */; };
+ 28F335F11007B36200424DE2 /* RootViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28F335F01007B36200424DE2 /* RootViewController.xib */; };
+ 3A3478AA1154BF8E00D51880 /* TestViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3A3478A91154BF8E00D51880 /* TestViewController.xib */; };
+ 3A3478AF1154BFD700D51880 /* TestViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A3478AE1154BFD700D51880 /* TestViewController.m */; };
+ 3A3479221154DB0800D51880 /* systest.c in Sources */ = {isa = PBXBuildFile; fileRef = 3A3479211154DB0800D51880 /* systest.c */; };
+ 3A34794B1154E39900D51880 /* libpjmedia-arm-apple-darwin9.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A34794A1154E39900D51880 /* libpjmedia-arm-apple-darwin9.a */; };
+ 3A34794D1154E39900D51880 /* libpjmedia-audiodev-arm-apple-darwin9.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A34794C1154E39900D51880 /* libpjmedia-audiodev-arm-apple-darwin9.a */; };
+ 3A34794F1154E3F000D51880 /* libpjsip-arm-apple-darwin9.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A34794E1154E3F000D51880 /* libpjsip-arm-apple-darwin9.a */; };
+ 3A3479511154E42400D51880 /* libpjsip-simple-arm-apple-darwin9.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A3479501154E42400D51880 /* libpjsip-simple-arm-apple-darwin9.a */; };
+ 3A3479531154E42400D51880 /* libpjsip-ua-arm-apple-darwin9.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A3479521154E42400D51880 /* libpjsip-ua-arm-apple-darwin9.a */; };
+ 3A3479551154E42400D51880 /* libpjsua-arm-apple-darwin9.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A3479541154E42400D51880 /* libpjsua-arm-apple-darwin9.a */; };
+ 3A34795B1154E45A00D51880 /* libpj-arm-apple-darwin9.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A34795A1154E45A00D51880 /* libpj-arm-apple-darwin9.a */; };
+ 3A34795D1154E48700D51880 /* libpjlib-util-arm-apple-darwin9.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A34795C1154E48700D51880 /* libpjlib-util-arm-apple-darwin9.a */; };
+ 3A3479791154EBDE00D51880 /* libpjmedia-codec-arm-apple-darwin9.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A3479781154EBDE00D51880 /* libpjmedia-codec-arm-apple-darwin9.a */; };
+ 3A34797B1154EBDE00D51880 /* libpjnath-arm-apple-darwin9.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A34797A1154EBDE00D51880 /* libpjnath-arm-apple-darwin9.a */; };
+ 3A3479871154EC4E00D51880 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A3479861154EC4E00D51880 /* AudioToolbox.framework */; };
+ 3A34799A1154ECA300D51880 /* libgsmcodec-arm-apple-darwin9.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A3479991154ECA300D51880 /* libgsmcodec-arm-apple-darwin9.a */; };
+ 3A34799C1154ECB100D51880 /* libresample-arm-apple-darwin9.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A34799B1154ECB100D51880 /* libresample-arm-apple-darwin9.a */; };
+ 3ABE0507147CA00B00A57A62 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3ABE0506147CA00B00A57A62 /* CFNetwork.framework */; };
+ 3AC6435E1162192900B7A751 /* tock8.wav in Resources */ = {isa = PBXBuildFile; fileRef = 3AC6435D1162192900B7A751 /* tock8.wav */; };
+ 3ADA4AB911572300008D95FE /* input.8.wav in Resources */ = {isa = PBXBuildFile; fileRef = 3ADA4AB811572300008D95FE /* input.8.wav */; };
+ 3AE90E9B115F7A4F00FAEAA5 /* libg7221codec-arm-apple-darwin9.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AE90E95115F7A4E00FAEAA5 /* libg7221codec-arm-apple-darwin9.a */; };
+ 3AE90E9C115F7A4F00FAEAA5 /* libilbccodec-arm-apple-darwin9.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AE90E96115F7A4F00FAEAA5 /* libilbccodec-arm-apple-darwin9.a */; };
+ 3AE90E9D115F7A4F00FAEAA5 /* libmilenage-arm-apple-darwin9.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AE90E97115F7A4F00FAEAA5 /* libmilenage-arm-apple-darwin9.a */; };
+ 3AE90E9E115F7A4F00FAEAA5 /* libpjsdp-arm-apple-darwin9.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AE90E98115F7A4F00FAEAA5 /* libpjsdp-arm-apple-darwin9.a */; };
+ 3AE90E9F115F7A4F00FAEAA5 /* libspeex-arm-apple-darwin9.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AE90E99115F7A4F00FAEAA5 /* libspeex-arm-apple-darwin9.a */; };
+ 3AE90EA0115F7A4F00FAEAA5 /* libsrtp-arm-apple-darwin9.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AE90E9A115F7A4F00FAEAA5 /* libsrtp-arm-apple-darwin9.a */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+ 1D3623240D0F684500981E51 /* ipjsystestAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ipjsystestAppDelegate.h; sourceTree = "<group>"; };
+ 1D3623250D0F684500981E51 /* ipjsystestAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ipjsystestAppDelegate.m; sourceTree = "<group>"; };
+ 1D6058910D05DD3D006BFB54 /* ipjsystest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ipjsystest.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
+ 2892E40F0DC94CBA00A64D0F /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
+ 28A0AAE50D9B0CCF005BE974 /* ipjsystest_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ipjsystest_Prefix.pch; sourceTree = "<group>"; };
+ 28AD735F0D9D9599002E5188 /* MainWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainWindow.xib; sourceTree = "<group>"; };
+ 28C286DF0D94DF7D0034E888 /* RootViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RootViewController.h; sourceTree = "<group>"; };
+ 28C286E00D94DF7D0034E888 /* RootViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RootViewController.m; sourceTree = "<group>"; };
+ 28F335F01007B36200424DE2 /* RootViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = RootViewController.xib; sourceTree = "<group>"; };
+ 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
+ 3A3478A91154BF8E00D51880 /* TestViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = TestViewController.xib; sourceTree = "<group>"; };
+ 3A3478AD1154BFD700D51880 /* TestViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestViewController.h; sourceTree = "<group>"; };
+ 3A3478AE1154BFD700D51880 /* TestViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TestViewController.m; sourceTree = "<group>"; };
+ 3A3479211154DB0800D51880 /* systest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = systest.c; path = ../pjsystest/systest.c; sourceTree = SOURCE_ROOT; };
+ 3A34794A1154E39900D51880 /* libpjmedia-arm-apple-darwin9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libpjmedia-arm-apple-darwin9.a"; path = "../../../pjmedia/lib/libpjmedia-arm-apple-darwin9.a"; sourceTree = SOURCE_ROOT; };
+ 3A34794C1154E39900D51880 /* libpjmedia-audiodev-arm-apple-darwin9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libpjmedia-audiodev-arm-apple-darwin9.a"; path = "../../../pjmedia/lib/libpjmedia-audiodev-arm-apple-darwin9.a"; sourceTree = SOURCE_ROOT; };
+ 3A34794E1154E3F000D51880 /* libpjsip-arm-apple-darwin9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libpjsip-arm-apple-darwin9.a"; path = "../../../pjsip/lib/libpjsip-arm-apple-darwin9.a"; sourceTree = SOURCE_ROOT; };
+ 3A3479501154E42400D51880 /* libpjsip-simple-arm-apple-darwin9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libpjsip-simple-arm-apple-darwin9.a"; path = "../../../pjsip/lib/libpjsip-simple-arm-apple-darwin9.a"; sourceTree = SOURCE_ROOT; };
+ 3A3479521154E42400D51880 /* libpjsip-ua-arm-apple-darwin9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libpjsip-ua-arm-apple-darwin9.a"; path = "../../../pjsip/lib/libpjsip-ua-arm-apple-darwin9.a"; sourceTree = SOURCE_ROOT; };
+ 3A3479541154E42400D51880 /* libpjsua-arm-apple-darwin9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libpjsua-arm-apple-darwin9.a"; path = "../../../pjsip/lib/libpjsua-arm-apple-darwin9.a"; sourceTree = SOURCE_ROOT; };
+ 3A34795A1154E45A00D51880 /* libpj-arm-apple-darwin9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libpj-arm-apple-darwin9.a"; path = "../../../pjlib/lib/libpj-arm-apple-darwin9.a"; sourceTree = SOURCE_ROOT; };
+ 3A34795C1154E48700D51880 /* libpjlib-util-arm-apple-darwin9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libpjlib-util-arm-apple-darwin9.a"; path = "../../../pjlib-util/lib/libpjlib-util-arm-apple-darwin9.a"; sourceTree = SOURCE_ROOT; };
+ 3A3479721154EB5B00D51880 /* gui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = gui.h; path = ../pjsystest/gui.h; sourceTree = SOURCE_ROOT; };
+ 3A3479731154EB6B00D51880 /* systest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = systest.h; path = ../pjsystest/systest.h; sourceTree = SOURCE_ROOT; };
+ 3A3479781154EBDE00D51880 /* libpjmedia-codec-arm-apple-darwin9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libpjmedia-codec-arm-apple-darwin9.a"; path = "../../../pjmedia/lib/libpjmedia-codec-arm-apple-darwin9.a"; sourceTree = SOURCE_ROOT; };
+ 3A34797A1154EBDE00D51880 /* libpjnath-arm-apple-darwin9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libpjnath-arm-apple-darwin9.a"; path = "../../../pjnath/lib/libpjnath-arm-apple-darwin9.a"; sourceTree = SOURCE_ROOT; };
+ 3A3479861154EC4E00D51880 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
+ 3A3479991154ECA300D51880 /* libgsmcodec-arm-apple-darwin9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libgsmcodec-arm-apple-darwin9.a"; path = "../../../third_party/lib/libgsmcodec-arm-apple-darwin9.a"; sourceTree = SOURCE_ROOT; };
+ 3A34799B1154ECB100D51880 /* libresample-arm-apple-darwin9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libresample-arm-apple-darwin9.a"; path = "../../../third_party/lib/libresample-arm-apple-darwin9.a"; sourceTree = SOURCE_ROOT; };
+ 3ABE0506147CA00B00A57A62 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; };
+ 3AC6435D1162192900B7A751 /* tock8.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; name = tock8.wav; path = ../../../tests/pjsua/wavs/tock8.wav; sourceTree = SOURCE_ROOT; };
+ 3ADA4AB811572300008D95FE /* input.8.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; name = input.8.wav; path = "../../../../../../../../teluu/pjproject-new-iphone/tests/pjsua/wavs/input.8.wav"; sourceTree = BUILT_PRODUCTS_DIR; };
+ 3AE90E95115F7A4E00FAEAA5 /* libg7221codec-arm-apple-darwin9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libg7221codec-arm-apple-darwin9.a"; path = "../../../third_party/lib/libg7221codec-arm-apple-darwin9.a"; sourceTree = SOURCE_ROOT; };
+ 3AE90E96115F7A4F00FAEAA5 /* libilbccodec-arm-apple-darwin9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libilbccodec-arm-apple-darwin9.a"; path = "../../../third_party/lib/libilbccodec-arm-apple-darwin9.a"; sourceTree = SOURCE_ROOT; };
+ 3AE90E97115F7A4F00FAEAA5 /* libmilenage-arm-apple-darwin9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libmilenage-arm-apple-darwin9.a"; path = "../../../third_party/lib/libmilenage-arm-apple-darwin9.a"; sourceTree = SOURCE_ROOT; };
+ 3AE90E98115F7A4F00FAEAA5 /* libpjsdp-arm-apple-darwin9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libpjsdp-arm-apple-darwin9.a"; path = "../../../pjmedia/lib/libpjsdp-arm-apple-darwin9.a"; sourceTree = SOURCE_ROOT; };
+ 3AE90E99115F7A4F00FAEAA5 /* libspeex-arm-apple-darwin9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libspeex-arm-apple-darwin9.a"; path = "../../../third_party/lib/libspeex-arm-apple-darwin9.a"; sourceTree = SOURCE_ROOT; };
+ 3AE90E9A115F7A4F00FAEAA5 /* libsrtp-arm-apple-darwin9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libsrtp-arm-apple-darwin9.a"; path = "../../../third_party/lib/libsrtp-arm-apple-darwin9.a"; sourceTree = SOURCE_ROOT; };
+ 8D1107310486CEB800E47090 /* ipjsystest-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "ipjsystest-Info.plist"; plistStructureDefinitionIdentifier = "com.apple.xcode.plist.structure-definition.iphone.info-plist"; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 1D60588F0D05DD3D006BFB54 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */,
+ 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */,
+ 2892E4100DC94CBA00A64D0F /* CoreGraphics.framework in Frameworks */,
+ 3A34794B1154E39900D51880 /* libpjmedia-arm-apple-darwin9.a in Frameworks */,
+ 3A34794D1154E39900D51880 /* libpjmedia-audiodev-arm-apple-darwin9.a in Frameworks */,
+ 3A34794F1154E3F000D51880 /* libpjsip-arm-apple-darwin9.a in Frameworks */,
+ 3A3479511154E42400D51880 /* libpjsip-simple-arm-apple-darwin9.a in Frameworks */,
+ 3A3479531154E42400D51880 /* libpjsip-ua-arm-apple-darwin9.a in Frameworks */,
+ 3A3479551154E42400D51880 /* libpjsua-arm-apple-darwin9.a in Frameworks */,
+ 3A34795B1154E45A00D51880 /* libpj-arm-apple-darwin9.a in Frameworks */,
+ 3A34795D1154E48700D51880 /* libpjlib-util-arm-apple-darwin9.a in Frameworks */,
+ 3A3479791154EBDE00D51880 /* libpjmedia-codec-arm-apple-darwin9.a in Frameworks */,
+ 3A34797B1154EBDE00D51880 /* libpjnath-arm-apple-darwin9.a in Frameworks */,
+ 3A3479871154EC4E00D51880 /* AudioToolbox.framework in Frameworks */,
+ 3A34799A1154ECA300D51880 /* libgsmcodec-arm-apple-darwin9.a in Frameworks */,
+ 3A34799C1154ECB100D51880 /* libresample-arm-apple-darwin9.a in Frameworks */,
+ 3AE90E9B115F7A4F00FAEAA5 /* libg7221codec-arm-apple-darwin9.a in Frameworks */,
+ 3AE90E9C115F7A4F00FAEAA5 /* libilbccodec-arm-apple-darwin9.a in Frameworks */,
+ 3AE90E9D115F7A4F00FAEAA5 /* libmilenage-arm-apple-darwin9.a in Frameworks */,
+ 3AE90E9E115F7A4F00FAEAA5 /* libpjsdp-arm-apple-darwin9.a in Frameworks */,
+ 3AE90E9F115F7A4F00FAEAA5 /* libspeex-arm-apple-darwin9.a in Frameworks */,
+ 3AE90EA0115F7A4F00FAEAA5 /* libsrtp-arm-apple-darwin9.a in Frameworks */,
+ 3ABE0507147CA00B00A57A62 /* CFNetwork.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 080E96DDFE201D6D7F000001 /* Classes */ = {
+ isa = PBXGroup;
+ children = (
+ 3A3478AD1154BFD700D51880 /* TestViewController.h */,
+ 3A3478AE1154BFD700D51880 /* TestViewController.m */,
+ 28C286DF0D94DF7D0034E888 /* RootViewController.h */,
+ 28C286E00D94DF7D0034E888 /* RootViewController.m */,
+ 1D3623240D0F684500981E51 /* ipjsystestAppDelegate.h */,
+ 1D3623250D0F684500981E51 /* ipjsystestAppDelegate.m */,
+ );
+ path = Classes;
+ sourceTree = "<group>";
+ };
+ 19C28FACFE9D520D11CA2CBB /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 1D6058910D05DD3D006BFB54 /* ipjsystest.app */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = {
+ isa = PBXGroup;
+ children = (
+ 080E96DDFE201D6D7F000001 /* Classes */,
+ 29B97315FDCFA39411CA2CEA /* Other Sources */,
+ 29B97317FDCFA39411CA2CEA /* Resources */,
+ 29B97323FDCFA39411CA2CEA /* Frameworks */,
+ 3A3479941154EC6B00D51880 /* Libraries */,
+ 19C28FACFE9D520D11CA2CBB /* Products */,
+ );
+ name = CustomTemplate;
+ sourceTree = "<group>";
+ };
+ 29B97315FDCFA39411CA2CEA /* Other Sources */ = {
+ isa = PBXGroup;
+ children = (
+ 3A3479201154DAE600D51880 /* pjsystest */,
+ 28A0AAE50D9B0CCF005BE974 /* ipjsystest_Prefix.pch */,
+ 29B97316FDCFA39411CA2CEA /* main.m */,
+ );
+ name = "Other Sources";
+ sourceTree = "<group>";
+ };
+ 29B97317FDCFA39411CA2CEA /* Resources */ = {
+ isa = PBXGroup;
+ children = (
+ 3AC6435D1162192900B7A751 /* tock8.wav */,
+ 3ADA4AB811572300008D95FE /* input.8.wav */,
+ 3A3478A91154BF8E00D51880 /* TestViewController.xib */,
+ 28F335F01007B36200424DE2 /* RootViewController.xib */,
+ 28AD735F0D9D9599002E5188 /* MainWindow.xib */,
+ 8D1107310486CEB800E47090 /* ipjsystest-Info.plist */,
+ );
+ name = Resources;
+ sourceTree = "<group>";
+ };
+ 29B97323FDCFA39411CA2CEA /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 3ABE0506147CA00B00A57A62 /* CFNetwork.framework */,
+ 3A3479861154EC4E00D51880 /* AudioToolbox.framework */,
+ 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */,
+ 1D30AB110D05D00D00671497 /* Foundation.framework */,
+ 2892E40F0DC94CBA00A64D0F /* CoreGraphics.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+ 3A3479201154DAE600D51880 /* pjsystest */ = {
+ isa = PBXGroup;
+ children = (
+ 3A3479731154EB6B00D51880 /* systest.h */,
+ 3A3479721154EB5B00D51880 /* gui.h */,
+ 3A3479211154DB0800D51880 /* systest.c */,
+ );
+ name = pjsystest;
+ sourceTree = "<group>";
+ };
+ 3A3479941154EC6B00D51880 /* Libraries */ = {
+ isa = PBXGroup;
+ children = (
+ 3AE90E95115F7A4E00FAEAA5 /* libg7221codec-arm-apple-darwin9.a */,
+ 3AE90E96115F7A4F00FAEAA5 /* libilbccodec-arm-apple-darwin9.a */,
+ 3AE90E97115F7A4F00FAEAA5 /* libmilenage-arm-apple-darwin9.a */,
+ 3AE90E98115F7A4F00FAEAA5 /* libpjsdp-arm-apple-darwin9.a */,
+ 3AE90E99115F7A4F00FAEAA5 /* libspeex-arm-apple-darwin9.a */,
+ 3AE90E9A115F7A4F00FAEAA5 /* libsrtp-arm-apple-darwin9.a */,
+ 3A3479991154ECA300D51880 /* libgsmcodec-arm-apple-darwin9.a */,
+ 3A34799B1154ECB100D51880 /* libresample-arm-apple-darwin9.a */,
+ 3A34794A1154E39900D51880 /* libpjmedia-arm-apple-darwin9.a */,
+ 3A34794C1154E39900D51880 /* libpjmedia-audiodev-arm-apple-darwin9.a */,
+ 3A34794E1154E3F000D51880 /* libpjsip-arm-apple-darwin9.a */,
+ 3A3479501154E42400D51880 /* libpjsip-simple-arm-apple-darwin9.a */,
+ 3A3479521154E42400D51880 /* libpjsip-ua-arm-apple-darwin9.a */,
+ 3A3479541154E42400D51880 /* libpjsua-arm-apple-darwin9.a */,
+ 3A34795A1154E45A00D51880 /* libpj-arm-apple-darwin9.a */,
+ 3A34795C1154E48700D51880 /* libpjlib-util-arm-apple-darwin9.a */,
+ 3A3479781154EBDE00D51880 /* libpjmedia-codec-arm-apple-darwin9.a */,
+ 3A34797A1154EBDE00D51880 /* libpjnath-arm-apple-darwin9.a */,
+ );
+ name = Libraries;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 1D6058900D05DD3D006BFB54 /* ipjsystest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "ipjsystest" */;
+ buildPhases = (
+ 1D60588D0D05DD3D006BFB54 /* Resources */,
+ 1D60588E0D05DD3D006BFB54 /* Sources */,
+ 1D60588F0D05DD3D006BFB54 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = ipjsystest;
+ productName = ipjsystest;
+ productReference = 1D6058910D05DD3D006BFB54 /* ipjsystest.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 29B97313FDCFA39411CA2CEA /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ ORGANIZATIONNAME = Teluu;
+ };
+ buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ipjsystest" */;
+ compatibilityVersion = "Xcode 3.1";
+ developmentRegion = English;
+ hasScannedForEncodings = 1;
+ knownRegions = (
+ English,
+ Japanese,
+ French,
+ German,
+ en,
+ );
+ mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 1D6058900D05DD3D006BFB54 /* ipjsystest */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 1D60588D0D05DD3D006BFB54 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 28AD73600D9D9599002E5188 /* MainWindow.xib in Resources */,
+ 28F335F11007B36200424DE2 /* RootViewController.xib in Resources */,
+ 3A3478AA1154BF8E00D51880 /* TestViewController.xib in Resources */,
+ 3ADA4AB911572300008D95FE /* input.8.wav in Resources */,
+ 3AC6435E1162192900B7A751 /* tock8.wav in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 1D60588E0D05DD3D006BFB54 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 1D60589B0D05DD56006BFB54 /* main.m in Sources */,
+ 1D3623260D0F684500981E51 /* ipjsystestAppDelegate.m in Sources */,
+ 28C286E10D94DF7D0034E888 /* RootViewController.m in Sources */,
+ 3A3478AF1154BFD700D51880 /* TestViewController.m in Sources */,
+ 3A3479221154DB0800D51880 /* systest.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 1D6058940D05DD3E006BFB54 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = NO;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = ipjsystest_Prefix.pch;
+ GCC_PREPROCESSOR_DEFINITIONS = "PJ_AUTOCONF=1";
+ INFOPLIST_FILE = "ipjsystest-Info.plist";
+ LIBRARY_SEARCH_PATHS = (
+ "$(inherited)",
+ "\"$(SRCROOT)/../../../pjmedia/lib\"",
+ "\"$(SRCROOT)/../../../pjsip/lib\"",
+ "\"$(SRCROOT)/../../../pjlib/lib\"",
+ "\"$(SRCROOT)/../../../pjlib-util/lib\"",
+ "\"$(SRCROOT)/../../../pjnath/lib\"",
+ "\"$(SRCROOT)/../../../third_party/lib\"",
+ );
+ PRODUCT_NAME = ipjsystest;
+ SDKROOT = iphoneos;
+ };
+ name = Debug;
+ };
+ 1D6058950D05DD3E006BFB54 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = YES;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = ipjsystest_Prefix.pch;
+ GCC_PREPROCESSOR_DEFINITIONS = "PJ_AUTOCONF=1";
+ INFOPLIST_FILE = "ipjsystest-Info.plist";
+ LIBRARY_SEARCH_PATHS = (
+ "$(inherited)",
+ "\"$(SRCROOT)/../../../pjmedia/lib\"",
+ "\"$(SRCROOT)/../../../pjsip/lib\"",
+ "\"$(SRCROOT)/../../../pjlib/lib\"",
+ "\"$(SRCROOT)/../../../pjlib-util/lib\"",
+ "\"$(SRCROOT)/../../../pjnath/lib\"",
+ "\"$(SRCROOT)/../../../third_party/lib\"",
+ );
+ PRODUCT_NAME = ipjsystest;
+ SDKROOT = iphoneos;
+ };
+ name = Release;
+ };
+ C01FCF4F08A954540054247B /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ GCC_C_LANGUAGE_STANDARD = c99;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = (
+ ../../../pjsip/include,
+ ../../../pjlib/include,
+ "../../../pjlib-util/include",
+ ../../../pjnath/include,
+ ../../../pjmedia/include,
+ );
+ LIBRARY_SEARCH_PATHS = (
+ ../../../pjlib/lib,
+ "../../../pjlib-util/lib",
+ ../../../pjnath/lib,
+ ../../../pjmedia/lib,
+ ../../../pjsip/lib,
+ ../../../third_party/lib,
+ );
+ PREBINDING = NO;
+ SDKROOT = iphoneos4.0;
+ };
+ name = Debug;
+ };
+ C01FCF5008A954540054247B /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ GCC_C_LANGUAGE_STANDARD = c99;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = (
+ ../../../pjsip/include,
+ ../../../pjlib/include,
+ "../../../pjlib-util/include",
+ ../../../pjnath/include,
+ ../../../pjmedia/include,
+ );
+ LIBRARY_SEARCH_PATHS = (
+ ../../../pjlib/lib,
+ "../../../pjlib-util/lib",
+ ../../../pjnath/lib,
+ ../../../pjmedia/lib,
+ ../../../pjsip/lib,
+ ../../../third_party/lib,
+ );
+ PREBINDING = NO;
+ SDKROOT = iphoneos4.0;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "ipjsystest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1D6058940D05DD3E006BFB54 /* Debug */,
+ 1D6058950D05DD3E006BFB54 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ipjsystest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ C01FCF4F08A954540054247B /* Debug */,
+ C01FCF5008A954540054247B /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 29B97313FDCFA39411CA2CEA /* Project object */;
+}
diff --git a/pjsip-apps/src/ipjsystest/ipjsystest_Prefix.pch b/pjsip-apps/src/ipjsystest/ipjsystest_Prefix.pch
new file mode 100644
index 0000000..8f7b754
--- /dev/null
+++ b/pjsip-apps/src/ipjsystest/ipjsystest_Prefix.pch
@@ -0,0 +1,14 @@
+//
+// Prefix header for all source files of the 'ipjsystest' target in the 'ipjsystest' project
+//
+#import <Availability.h>
+
+#ifndef __IPHONE_3_0
+#warning "This project uses features only available in iPhone SDK 3.0 and later."
+#endif
+
+
+#ifdef __OBJC__
+ #import <Foundation/Foundation.h>
+ #import <UIKit/UIKit.h>
+#endif
diff --git a/pjsip-apps/src/ipjsystest/main.m b/pjsip-apps/src/ipjsystest/main.m
new file mode 100644
index 0000000..186fe8a
--- /dev/null
+++ b/pjsip-apps/src/ipjsystest/main.m
@@ -0,0 +1,27 @@
+/* $Id: main.m 3552 2011-05-05 05:50:48Z nanang $ */
+/*
+ * Copyright (C) 2010-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#import <UIKit/UIKit.h>
+
+int main(int argc, char *argv[]) {
+
+ NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+ int retVal = UIApplicationMain(argc, argv, nil, nil);
+ [pool release];
+ return retVal;
+}
diff --git a/pjsip-apps/src/pjsua/gui.h b/pjsip-apps/src/pjsua/gui.h
new file mode 100644
index 0000000..f7ad169
--- /dev/null
+++ b/pjsip-apps/src/pjsua/gui.h
@@ -0,0 +1,39 @@
+/* $Id: gui.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __GUI_H__
+#define __GUI_H__
+
+PJ_BEGIN_DECL
+
+#ifdef USE_GUI
+
+#define printf showMsg
+#define puts(str) showMsg("%s\n", str)
+#define fgets getInput
+
+void showMsg(const char *format, ...);
+char * getInput(char *s, int n, FILE *stream);
+pj_bool_t showNotification(pjsua_call_id call_id);
+
+#endif
+
+PJ_END_DECL
+
+
+#endif /* __GUI_H__ */
diff --git a/pjsip-apps/src/pjsua/main.c b/pjsip-apps/src/pjsua/main.c
new file mode 100644
index 0000000..8f6bd67
--- /dev/null
+++ b/pjsip-apps/src/pjsua/main.c
@@ -0,0 +1,113 @@
+/* $Id: main.c 3664 2011-07-19 03:42:28Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <pjsua-lib/pjsua.h>
+
+
+#define THIS_FILE "main.c"
+
+
+/*
+ * These are defined in pjsua_app.c.
+ */
+extern pj_bool_t app_restart;
+pj_status_t app_init(int argc, char *argv[]);
+pj_status_t app_main(void);
+pj_status_t app_destroy(void);
+
+
+#if defined(PJ_WIN32) && PJ_WIN32!=0
+#include <windows.h>
+
+static pj_thread_desc handler_desc;
+
+static BOOL WINAPI CtrlHandler(DWORD fdwCtrlType)
+{
+ pj_thread_t *thread;
+
+ switch (fdwCtrlType)
+ {
+ // Handle the CTRL+C signal.
+
+ case CTRL_C_EVENT:
+ case CTRL_CLOSE_EVENT:
+ case CTRL_BREAK_EVENT:
+ case CTRL_LOGOFF_EVENT:
+ case CTRL_SHUTDOWN_EVENT:
+ pj_thread_register("ctrlhandler", handler_desc, &thread);
+ PJ_LOG(3,(THIS_FILE, "Ctrl-C detected, quitting.."));
+ app_destroy();
+ ExitProcess(1);
+ PJ_UNREACHED(return TRUE;)
+
+ default:
+
+ return FALSE;
+ }
+}
+
+static void setup_signal_handler(void)
+{
+ SetConsoleCtrlHandler(&CtrlHandler, TRUE);
+}
+
+static void setup_socket_signal()
+{
+}
+
+#else
+#include <signal.h>
+
+static void setup_signal_handler(void)
+{
+}
+
+static void setup_socket_signal()
+{
+ signal(SIGPIPE, SIG_IGN);
+}
+
+#endif
+
+static int main_func(int argc, char *argv[])
+{
+ setup_socket_signal();
+
+ do {
+ app_restart = PJ_FALSE;
+
+ if (app_init(argc, argv) != PJ_SUCCESS)
+ return 1;
+
+ setup_signal_handler();
+
+ app_main();
+ app_destroy();
+
+ /* This is on purpose */
+ app_destroy();
+ } while (app_restart);
+
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ return pj_run_app(&main_func, argc, argv, 0);
+}
diff --git a/pjsip-apps/src/pjsua/main_rtems.c b/pjsip-apps/src/pjsua/main_rtems.c
new file mode 100644
index 0000000..d26605a
--- /dev/null
+++ b/pjsip-apps/src/pjsua/main_rtems.c
@@ -0,0 +1,12 @@
+
+/*
+ * !! OIY OIY !!
+ *
+ * The purpose of this file is only to get the executable linked. I haven't
+ * actually tried to run this on RTEMS!!
+ *
+ */
+
+#include "../../pjlib/src/pjlib-test/main_rtems.c"
+
+
diff --git a/pjsip-apps/src/pjsua/pjsua_app.c b/pjsip-apps/src/pjsua/pjsua_app.c
new file mode 100644
index 0000000..6a4f9a1
--- /dev/null
+++ b/pjsip-apps/src/pjsua/pjsua_app.c
@@ -0,0 +1,6312 @@
+/* $Id: pjsua_app.c 4129 2012-05-17 08:27:46Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <pjsua-lib/pjsua.h>
+#include "gui.h"
+
+
+#define THIS_FILE "pjsua_app.c"
+#define NO_LIMIT (int)0x7FFFFFFF
+
+//#define STEREO_DEMO
+//#define TRANSPORT_ADAPTER_SAMPLE
+//#define HAVE_MULTIPART_TEST
+
+/* Ringtones US UK */
+#define RINGBACK_FREQ1 440 /* 400 */
+#define RINGBACK_FREQ2 480 /* 450 */
+#define RINGBACK_ON 2000 /* 400 */
+#define RINGBACK_OFF 4000 /* 200 */
+#define RINGBACK_CNT 1 /* 2 */
+#define RINGBACK_INTERVAL 4000 /* 2000 */
+
+#define RING_FREQ1 800
+#define RING_FREQ2 640
+#define RING_ON 200
+#define RING_OFF 100
+#define RING_CNT 3
+#define RING_INTERVAL 3000
+
+#define MAX_AVI 4
+
+/* Call specific data */
+struct call_data
+{
+ pj_timer_entry timer;
+ pj_bool_t ringback_on;
+ pj_bool_t ring_on;
+};
+
+/* Video settings */
+struct app_vid
+{
+ unsigned vid_cnt;
+ int vcapture_dev;
+ int vrender_dev;
+ pj_bool_t in_auto_show;
+ pj_bool_t out_auto_transmit;
+};
+
+/* Pjsua application data */
+static struct app_config
+{
+ pjsua_config cfg;
+ pjsua_logging_config log_cfg;
+ pjsua_media_config media_cfg;
+ pj_bool_t no_refersub;
+ pj_bool_t ipv6;
+ pj_bool_t enable_qos;
+ pj_bool_t no_tcp;
+ pj_bool_t no_udp;
+ pj_bool_t use_tls;
+ pjsua_transport_config udp_cfg;
+ pjsua_transport_config rtp_cfg;
+ pjsip_redirect_op redir_op;
+
+ unsigned acc_cnt;
+ pjsua_acc_config acc_cfg[PJSUA_MAX_ACC];
+
+ unsigned buddy_cnt;
+ pjsua_buddy_config buddy_cfg[PJSUA_MAX_BUDDIES];
+
+ struct call_data call_data[PJSUA_MAX_CALLS];
+
+ pj_pool_t *pool;
+ /* Compatibility with older pjsua */
+
+ unsigned codec_cnt;
+ pj_str_t codec_arg[32];
+ unsigned codec_dis_cnt;
+ pj_str_t codec_dis[32];
+ pj_bool_t null_audio;
+ unsigned wav_count;
+ pj_str_t wav_files[32];
+ unsigned tone_count;
+ pjmedia_tone_desc tones[32];
+ pjsua_conf_port_id tone_slots[32];
+ pjsua_player_id wav_id;
+ pjsua_conf_port_id wav_port;
+ pj_bool_t auto_play;
+ pj_bool_t auto_play_hangup;
+ pj_timer_entry auto_hangup_timer;
+ pj_bool_t auto_loop;
+ pj_bool_t auto_conf;
+ pj_str_t rec_file;
+ pj_bool_t auto_rec;
+ pjsua_recorder_id rec_id;
+ pjsua_conf_port_id rec_port;
+ unsigned auto_answer;
+ unsigned duration;
+
+#ifdef STEREO_DEMO
+ pjmedia_snd_port *snd;
+ pjmedia_port *sc, *sc_ch1;
+ pjsua_conf_port_id sc_ch1_slot;
+#endif
+
+ float mic_level,
+ speaker_level;
+
+ int capture_dev, playback_dev;
+ unsigned capture_lat, playback_lat;
+
+ pj_bool_t no_tones;
+ int ringback_slot;
+ int ringback_cnt;
+ pjmedia_port *ringback_port;
+ int ring_slot;
+ int ring_cnt;
+ pjmedia_port *ring_port;
+
+ struct app_vid vid;
+ unsigned aud_cnt;
+
+ /* AVI to play */
+ unsigned avi_cnt;
+ struct {
+ pj_str_t path;
+ pjmedia_vid_dev_index dev_id;
+ pjsua_conf_port_id slot;
+ } avi[MAX_AVI];
+ pj_bool_t avi_auto_play;
+ int avi_def_idx;
+
+} app_config;
+
+
+//static pjsua_acc_id current_acc;
+#define current_acc pjsua_acc_get_default()
+static pjsua_call_id current_call = PJSUA_INVALID_ID;
+static pj_bool_t cmd_echo;
+static int stdout_refresh = -1;
+static const char *stdout_refresh_text = "STDOUT_REFRESH";
+static pj_bool_t stdout_refresh_quit = PJ_FALSE;
+static pj_str_t uri_arg;
+
+#if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0)
+# define SOME_BUF_SIZE (1024 * 10)
+#else
+# define SOME_BUF_SIZE (1024 * 3)
+#endif
+
+static char some_buf[SOME_BUF_SIZE];
+
+#ifdef STEREO_DEMO
+static void stereo_demo();
+#endif
+static pj_status_t create_ipv6_media_transports(void);
+pj_status_t app_destroy(void);
+
+static void ringback_start(pjsua_call_id call_id);
+static void ring_start(pjsua_call_id call_id);
+static void ring_stop(pjsua_call_id call_id);
+
+pj_bool_t app_restart;
+pj_log_func *log_cb = NULL;
+
+/*****************************************************************************
+ * Configuration manipulation
+ */
+
+#if (defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \
+ PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0) || \
+ defined(__IPHONE_4_0)
+void keepAliveFunction(int timeout)
+{
+ int i;
+ for (i=0; i<(int)pjsua_acc_get_count(); ++i) {
+ if (!pjsua_acc_is_valid(i))
+ continue;
+
+ if (app_config.acc_cfg[i].reg_timeout < timeout)
+ app_config.acc_cfg[i].reg_timeout = timeout;
+ pjsua_acc_set_registration(i, PJ_TRUE);
+ }
+}
+#endif
+
+/* Show usage */
+static void usage(void)
+{
+ puts ("Usage:");
+ puts (" pjsua [options] [SIP URL to call]");
+ puts ("");
+ puts ("General options:");
+ puts (" --config-file=file Read the config/arguments from file.");
+ puts (" --help Display this help screen");
+ puts (" --version Display version info");
+ puts ("");
+ puts ("Logging options:");
+ puts (" --log-file=fname Log to filename (default stderr)");
+ puts (" --log-level=N Set log max level to N (0(none) to 6(trace)) (default=5)");
+ puts (" --app-log-level=N Set log max level for stdout display (default=4)");
+ puts (" --log-append Append instead of overwrite existing log file.\n");
+ puts (" --color Use colorful logging (default yes on Win32)");
+ puts (" --no-color Disable colorful logging");
+ puts (" --light-bg Use dark colors for light background (default is dark bg)");
+ puts (" --no-stderr Disable stderr");
+
+ puts ("");
+ puts ("SIP Account options:");
+ puts (" --use-ims Enable 3GPP/IMS related settings on this account");
+#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
+ puts (" --use-srtp=N Use SRTP? 0:disabled, 1:optional, 2:mandatory,");
+ puts (" 3:optional by duplicating media offer (def:0)");
+ puts (" --srtp-secure=N SRTP require secure SIP? 0:no, 1:tls, 2:sips (def:1)");
+#endif
+ puts (" --registrar=url Set the URL of registrar server");
+ puts (" --id=url Set the URL of local ID (used in From header)");
+ puts (" --contact=url Optionally override the Contact information");
+ puts (" --contact-params=S Append the specified parameters S in Contact header");
+ puts (" --contact-uri-params=S Append the specified parameters S in Contact URI");
+ puts (" --proxy=url Optional URL of proxy server to visit");
+ puts (" May be specified multiple times");
+ printf(" --reg-timeout=SEC Optional registration interval (default %d)\n",
+ PJSUA_REG_INTERVAL);
+ printf(" --rereg-delay=SEC Optional auto retry registration interval (default %d)\n",
+ PJSUA_REG_RETRY_INTERVAL);
+ puts (" --reg-use-proxy=N Control the use of proxy settings in REGISTER.");
+ puts (" 0=no proxy, 1=outbound only, 2=acc only, 3=all (default)");
+ puts (" --realm=string Set realm");
+ puts (" --username=string Set authentication username");
+ puts (" --password=string Set authentication password");
+ puts (" --publish Send presence PUBLISH for this account");
+ puts (" --mwi Subscribe to message summary/waiting indication");
+ puts (" --use-100rel Require reliable provisional response (100rel)");
+ puts (" --use-timer=N Use SIP session timers? (default=1)");
+ puts (" 0:inactive, 1:optional, 2:mandatory, 3:always");
+ printf(" --timer-se=N Session timers expiration period, in secs (def:%d)\n",
+ PJSIP_SESS_TIMER_DEF_SE);
+ puts (" --timer-min-se=N Session timers minimum expiration period, in secs (def:90)");
+ puts (" --outb-rid=string Set SIP outbound reg-id (default:1)");
+ puts (" --auto-update-nat=N Where N is 0 or 1 to enable/disable SIP traversal behind");
+ puts (" symmetric NAT (default 1)");
+ puts (" --next-cred Add another credentials");
+ puts ("");
+ puts ("SIP Account Control:");
+ puts (" --next-account Add more account");
+ puts ("");
+ puts ("Transport Options:");
+#if defined(PJ_HAS_IPV6) && PJ_HAS_IPV6
+ puts (" --ipv6 Use IPv6 instead for SIP and media.");
+#endif
+ puts (" --set-qos Enable QoS tagging for SIP and media.");
+ puts (" --local-port=port Set TCP/UDP port. This implicitly enables both ");
+ puts (" TCP and UDP transports on the specified port, unless");
+ puts (" if TCP or UDP is disabled.");
+ puts (" --ip-addr=IP Use the specifed address as SIP and RTP addresses.");
+ puts (" (Hint: the IP may be the public IP of the NAT/router)");
+ puts (" --bound-addr=IP Bind transports to this IP interface");
+ puts (" --no-tcp Disable TCP transport.");
+ puts (" --no-udp Disable UDP transport.");
+ puts (" --nameserver=NS Add the specified nameserver to enable SRV resolution");
+ puts (" This option can be specified multiple times.");
+ puts (" --outbound=url Set the URL of global outbound proxy server");
+ puts (" May be specified multiple times");
+ puts (" --stun-srv=FORMAT Set STUN server host or domain. This option may be");
+ puts (" specified more than once. FORMAT is hostdom[:PORT]");
+
+#if defined(PJSIP_HAS_TLS_TRANSPORT) && (PJSIP_HAS_TLS_TRANSPORT != 0)
+ puts ("");
+ puts ("TLS Options:");
+ puts (" --use-tls Enable TLS transport (default=no)");
+ puts (" --tls-ca-file Specify TLS CA file (default=none)");
+ puts (" --tls-cert-file Specify TLS certificate file (default=none)");
+ puts (" --tls-privkey-file Specify TLS private key file (default=none)");
+ puts (" --tls-password Specify TLS password to private key file (default=none)");
+ puts (" --tls-verify-server Verify server's certificate (default=no)");
+ puts (" --tls-verify-client Verify client's certificate (default=no)");
+ puts (" --tls-neg-timeout Specify TLS negotiation timeout (default=no)");
+ puts (" --tls-srv-name Specify TLS server name for multihosting server");
+ puts (" --tls-cipher Specify prefered TLS cipher (optional).");
+ puts (" May be specified multiple times");
+#endif
+
+ puts ("");
+ puts ("Audio Options:");
+ puts (" --add-codec=name Manually add codec (default is to enable all)");
+ puts (" --dis-codec=name Disable codec (can be specified multiple times)");
+ puts (" --clock-rate=N Override conference bridge clock rate");
+ puts (" --snd-clock-rate=N Override sound device clock rate");
+ puts (" --stereo Audio device and conference bridge opened in stereo mode");
+ puts (" --null-audio Use NULL audio device");
+ puts (" --play-file=file Register WAV file in conference bridge.");
+ puts (" This can be specified multiple times.");
+ puts (" --play-tone=FORMAT Register tone to the conference bridge.");
+ puts (" FORMAT is 'F1,F2,ON,OFF', where F1,F2 are");
+ puts (" frequencies, and ON,OFF=on/off duration in msec.");
+ puts (" This can be specified multiple times.");
+ puts (" --auto-play Automatically play the file (to incoming calls only)");
+ puts (" --auto-loop Automatically loop incoming RTP to outgoing RTP");
+ puts (" --auto-conf Automatically put calls in conference with others");
+ puts (" --rec-file=file Open file recorder (extension can be .wav or .mp3");
+ puts (" --auto-rec Automatically record conversation");
+ puts (" --quality=N Specify media quality (0-10, default=6)");
+ puts (" --ptime=MSEC Override codec ptime to MSEC (default=specific)");
+ puts (" --no-vad Disable VAD/silence detector (default=vad enabled)");
+ puts (" --ec-tail=MSEC Set echo canceller tail length (default=256)");
+ puts (" --ec-opt=OPT Select echo canceller algorithm (0=default, ");
+ puts (" 1=speex, 2=suppressor)");
+ puts (" --ilbc-mode=MODE Set iLBC codec mode (20 or 30, default is 30)");
+ puts (" --capture-dev=id Audio capture device ID (default=-1)");
+ puts (" --playback-dev=id Audio playback device ID (default=-1)");
+ puts (" --capture-lat=N Audio capture latency, in ms (default=100)");
+ puts (" --playback-lat=N Audio playback latency, in ms (default=100)");
+ puts (" --snd-auto-close=N Auto close audio device when idle for N secs (default=1)");
+ puts (" Specify N=-1 to disable this feature.");
+ puts (" Specify N=0 for instant close when unused.");
+ puts (" --no-tones Disable audible tones");
+ puts (" --jb-max-size Specify jitter buffer maximum size, in frames (default=-1)");
+ puts (" --extra-audio Add one more audio stream");
+
+#if PJSUA_HAS_VIDEO
+ puts ("");
+ puts ("Video Options:");
+ puts (" --video Enable video");
+ puts (" --vcapture-dev=id Video capture device ID (default=-1)");
+ puts (" --vrender-dev=id Video render device ID (default=-1)");
+ puts (" --play-avi=FILE Load this AVI as virtual capture device");
+ puts (" --auto-play-avi Automatically play the AVI media to call");
+#endif
+
+ puts ("");
+ puts ("Media Transport Options:");
+ puts (" --use-ice Enable ICE (default:no)");
+ puts (" --ice-regular Use ICE regular nomination (default: aggressive)");
+ puts (" --ice-max-hosts=N Set maximum number of ICE host candidates");
+ puts (" --ice-no-rtcp Disable RTCP component in ICE (default: no)");
+ puts (" --rtp-port=N Base port to try for RTP (default=4000)");
+ puts (" --rx-drop-pct=PCT Drop PCT percent of RX RTP (for pkt lost sim, default: 0)");
+ puts (" --tx-drop-pct=PCT Drop PCT percent of TX RTP (for pkt lost sim, default: 0)");
+ puts (" --use-turn Enable TURN relay with ICE (default:no)");
+ puts (" --turn-srv Domain or host name of TURN server (\"NAME:PORT\" format)");
+ puts (" --turn-tcp Use TCP connection to TURN server (default no)");
+ puts (" --turn-user TURN username");
+ puts (" --turn-passwd TURN password");
+
+ puts ("");
+ puts ("Buddy List (can be more than one):");
+ puts (" --add-buddy url Add the specified URL to the buddy list.");
+ puts ("");
+ puts ("User Agent options:");
+ puts (" --auto-answer=code Automatically answer incoming calls with code (e.g. 200)");
+ puts (" --max-calls=N Maximum number of concurrent calls (default:4, max:255)");
+ puts (" --thread-cnt=N Number of worker threads (default:1)");
+ puts (" --duration=SEC Set maximum call duration (default:no limit)");
+ puts (" --norefersub Suppress event subscription when transfering calls");
+ puts (" --use-compact-form Minimize SIP message size");
+ puts (" --no-force-lr Allow strict-route to be used (i.e. do not force lr)");
+ puts (" --accept-redirect=N Specify how to handle call redirect (3xx) response.");
+ puts (" 0: reject, 1: follow automatically (default), 2: ask");
+
+ puts ("");
+ puts ("When URL is specified, pjsua will immediately initiate call to that URL");
+ puts ("");
+
+ fflush(stdout);
+}
+
+
+/* Set default config. */
+static void default_config(struct app_config *cfg)
+{
+ char tmp[80];
+ unsigned i;
+
+ pjsua_config_default(&cfg->cfg);
+ pj_ansi_sprintf(tmp, "PJSUA v%s %s", pj_get_version(),
+ pj_get_sys_info()->info.ptr);
+ pj_strdup2_with_null(app_config.pool, &cfg->cfg.user_agent, tmp);
+
+ pjsua_logging_config_default(&cfg->log_cfg);
+ pjsua_media_config_default(&cfg->media_cfg);
+ pjsua_transport_config_default(&cfg->udp_cfg);
+ cfg->udp_cfg.port = 5060;
+ pjsua_transport_config_default(&cfg->rtp_cfg);
+ cfg->rtp_cfg.port = 4000;
+ cfg->redir_op = PJSIP_REDIRECT_ACCEPT;
+ cfg->duration = NO_LIMIT;
+ cfg->wav_id = PJSUA_INVALID_ID;
+ cfg->rec_id = PJSUA_INVALID_ID;
+ cfg->wav_port = PJSUA_INVALID_ID;
+ cfg->rec_port = PJSUA_INVALID_ID;
+ cfg->mic_level = cfg->speaker_level = 1.0;
+ cfg->capture_dev = PJSUA_INVALID_ID;
+ cfg->playback_dev = PJSUA_INVALID_ID;
+ cfg->capture_lat = PJMEDIA_SND_DEFAULT_REC_LATENCY;
+ cfg->playback_lat = PJMEDIA_SND_DEFAULT_PLAY_LATENCY;
+ cfg->ringback_slot = PJSUA_INVALID_ID;
+ cfg->ring_slot = PJSUA_INVALID_ID;
+
+ for (i=0; i<PJ_ARRAY_SIZE(cfg->acc_cfg); ++i)
+ pjsua_acc_config_default(&cfg->acc_cfg[i]);
+
+ for (i=0; i<PJ_ARRAY_SIZE(cfg->buddy_cfg); ++i)
+ pjsua_buddy_config_default(&cfg->buddy_cfg[i]);
+
+ cfg->vid.vcapture_dev = PJMEDIA_VID_DEFAULT_CAPTURE_DEV;
+ cfg->vid.vrender_dev = PJMEDIA_VID_DEFAULT_RENDER_DEV;
+ cfg->aud_cnt = 1;
+
+ cfg->avi_def_idx = PJSUA_INVALID_ID;
+}
+
+
+/*
+ * Read command arguments from config file.
+ */
+static int read_config_file(pj_pool_t *pool, const char *filename,
+ int *app_argc, char ***app_argv)
+{
+ int i;
+ FILE *fhnd;
+ char line[200];
+ int argc = 0;
+ char **argv;
+ enum { MAX_ARGS = 128 };
+
+ /* Allocate MAX_ARGS+1 (argv needs to be terminated with NULL argument) */
+ argv = pj_pool_calloc(pool, MAX_ARGS+1, sizeof(char*));
+ argv[argc++] = *app_argv[0];
+
+ /* Open config file. */
+ fhnd = fopen(filename, "rt");
+ if (!fhnd) {
+ PJ_LOG(1,(THIS_FILE, "Unable to open config file %s", filename));
+ fflush(stdout);
+ return -1;
+ }
+
+ /* Scan tokens in the file. */
+ while (argc < MAX_ARGS && !feof(fhnd)) {
+ char *token;
+ char *p;
+ const char *whitespace = " \t\r\n";
+ char cDelimiter;
+ int len, token_len;
+
+ if (fgets(line, sizeof(line), fhnd) == NULL) break;
+
+ // Trim ending newlines
+ len = strlen(line);
+ if (line[len-1]=='\n')
+ line[--len] = '\0';
+ if (line[len-1]=='\r')
+ line[--len] = '\0';
+
+ if (len==0) continue;
+
+ for (p = line; *p != '\0' && argc < MAX_ARGS; p++) {
+ // first, scan whitespaces
+ while (*p != '\0' && strchr(whitespace, *p) != NULL) p++;
+
+ if (*p == '\0') // are we done yet?
+ break;
+
+ if (*p == '"' || *p == '\'') { // is token a quoted string
+ cDelimiter = *p++; // save quote delimiter
+ token = p;
+
+ while (*p != '\0' && *p != cDelimiter) p++;
+
+ if (*p == '\0') // found end of the line, but,
+ cDelimiter = '\0'; // didn't find a matching quote
+
+ } else { // token's not a quoted string
+ token = p;
+
+ while (*p != '\0' && strchr(whitespace, *p) == NULL) p++;
+
+ cDelimiter = *p;
+ }
+
+ *p = '\0';
+ token_len = p-token;
+
+ if (token_len > 0) {
+ if (*token == '#')
+ break; // ignore remainder of line
+
+ argv[argc] = pj_pool_alloc(pool, token_len + 1);
+ pj_memcpy(argv[argc], token, token_len + 1);
+ ++argc;
+ }
+
+ *p = cDelimiter;
+ }
+ }
+
+ /* Copy arguments from command line */
+ for (i=1; i<*app_argc && argc < MAX_ARGS; ++i)
+ argv[argc++] = (*app_argv)[i];
+
+ if (argc == MAX_ARGS && (i!=*app_argc || !feof(fhnd))) {
+ PJ_LOG(1,(THIS_FILE,
+ "Too many arguments specified in cmd line/config file"));
+ fflush(stdout);
+ fclose(fhnd);
+ return -1;
+ }
+
+ fclose(fhnd);
+
+ /* Assign the new command line back to the original command line. */
+ *app_argc = argc;
+ *app_argv = argv;
+ return 0;
+
+}
+
+static int my_atoi(const char *cs)
+{
+ pj_str_t s;
+
+ pj_cstr(&s, cs);
+ if (cs[0] == '-') {
+ s.ptr++, s.slen--;
+ return 0 - (int)pj_strtoul(&s);
+ } else if (cs[0] == '+') {
+ s.ptr++, s.slen--;
+ return pj_strtoul(&s);
+ } else {
+ return pj_strtoul(&s);
+ }
+}
+
+
+/* Parse arguments. */
+static pj_status_t parse_args(int argc, char *argv[],
+ struct app_config *cfg,
+ pj_str_t *uri_to_call)
+{
+ int c;
+ int option_index;
+ enum { OPT_CONFIG_FILE=127, OPT_LOG_FILE, OPT_LOG_LEVEL, OPT_APP_LOG_LEVEL,
+ OPT_LOG_APPEND, OPT_COLOR, OPT_NO_COLOR, OPT_LIGHT_BG, OPT_NO_STDERR,
+ OPT_HELP, OPT_VERSION, OPT_NULL_AUDIO, OPT_SND_AUTO_CLOSE,
+ OPT_LOCAL_PORT, OPT_IP_ADDR, OPT_PROXY, OPT_OUTBOUND_PROXY,
+ OPT_REGISTRAR, OPT_REG_TIMEOUT, OPT_PUBLISH, OPT_ID, OPT_CONTACT,
+ OPT_BOUND_ADDR, OPT_CONTACT_PARAMS, OPT_CONTACT_URI_PARAMS,
+ OPT_100REL, OPT_USE_IMS, OPT_REALM, OPT_USERNAME, OPT_PASSWORD,
+ OPT_REG_RETRY_INTERVAL, OPT_REG_USE_PROXY,
+ OPT_MWI, OPT_NAMESERVER, OPT_STUN_SRV, OPT_OUTB_RID,
+ OPT_ADD_BUDDY, OPT_OFFER_X_MS_MSG, OPT_NO_PRESENCE,
+ OPT_AUTO_ANSWER, OPT_AUTO_PLAY, OPT_AUTO_PLAY_HANGUP, OPT_AUTO_LOOP,
+ OPT_AUTO_CONF, OPT_CLOCK_RATE, OPT_SND_CLOCK_RATE, OPT_STEREO,
+ OPT_USE_ICE, OPT_ICE_REGULAR, OPT_USE_SRTP, OPT_SRTP_SECURE,
+ OPT_USE_TURN, OPT_ICE_MAX_HOSTS, OPT_ICE_NO_RTCP, OPT_TURN_SRV,
+ OPT_TURN_TCP, OPT_TURN_USER, OPT_TURN_PASSWD,
+ OPT_PLAY_FILE, OPT_PLAY_TONE, OPT_RTP_PORT, OPT_ADD_CODEC,
+ OPT_ILBC_MODE, OPT_REC_FILE, OPT_AUTO_REC,
+ OPT_COMPLEXITY, OPT_QUALITY, OPT_PTIME, OPT_NO_VAD,
+ OPT_RX_DROP_PCT, OPT_TX_DROP_PCT, OPT_EC_TAIL, OPT_EC_OPT,
+ OPT_NEXT_ACCOUNT, OPT_NEXT_CRED, OPT_MAX_CALLS,
+ OPT_DURATION, OPT_NO_TCP, OPT_NO_UDP, OPT_THREAD_CNT,
+ OPT_NOREFERSUB, OPT_ACCEPT_REDIRECT,
+ OPT_USE_TLS, OPT_TLS_CA_FILE, OPT_TLS_CERT_FILE, OPT_TLS_PRIV_FILE,
+ OPT_TLS_PASSWORD, OPT_TLS_VERIFY_SERVER, OPT_TLS_VERIFY_CLIENT,
+ OPT_TLS_NEG_TIMEOUT, OPT_TLS_CIPHER,
+ OPT_CAPTURE_DEV, OPT_PLAYBACK_DEV,
+ OPT_CAPTURE_LAT, OPT_PLAYBACK_LAT, OPT_NO_TONES, OPT_JB_MAX_SIZE,
+ OPT_STDOUT_REFRESH, OPT_STDOUT_REFRESH_TEXT, OPT_IPV6, OPT_QOS,
+#ifdef _IONBF
+ OPT_STDOUT_NO_BUF,
+#endif
+ OPT_AUTO_UPDATE_NAT,OPT_USE_COMPACT_FORM,OPT_DIS_CODEC,
+ OPT_NO_FORCE_LR,
+ OPT_TIMER, OPT_TIMER_SE, OPT_TIMER_MIN_SE,
+ OPT_VIDEO, OPT_EXTRA_AUDIO,
+ OPT_VCAPTURE_DEV, OPT_VRENDER_DEV, OPT_PLAY_AVI, OPT_AUTO_PLAY_AVI
+ };
+ struct pj_getopt_option long_options[] = {
+ { "config-file",1, 0, OPT_CONFIG_FILE},
+ { "log-file", 1, 0, OPT_LOG_FILE},
+ { "log-level", 1, 0, OPT_LOG_LEVEL},
+ { "app-log-level",1,0,OPT_APP_LOG_LEVEL},
+ { "log-append", 0, 0, OPT_LOG_APPEND},
+ { "color", 0, 0, OPT_COLOR},
+ { "no-color", 0, 0, OPT_NO_COLOR},
+ { "light-bg", 0, 0, OPT_LIGHT_BG},
+ { "no-stderr", 0, 0, OPT_NO_STDERR},
+ { "help", 0, 0, OPT_HELP},
+ { "version", 0, 0, OPT_VERSION},
+ { "clock-rate", 1, 0, OPT_CLOCK_RATE},
+ { "snd-clock-rate", 1, 0, OPT_SND_CLOCK_RATE},
+ { "stereo", 0, 0, OPT_STEREO},
+ { "null-audio", 0, 0, OPT_NULL_AUDIO},
+ { "local-port", 1, 0, OPT_LOCAL_PORT},
+ { "ip-addr", 1, 0, OPT_IP_ADDR},
+ { "bound-addr", 1, 0, OPT_BOUND_ADDR},
+ { "no-tcp", 0, 0, OPT_NO_TCP},
+ { "no-udp", 0, 0, OPT_NO_UDP},
+ { "norefersub", 0, 0, OPT_NOREFERSUB},
+ { "proxy", 1, 0, OPT_PROXY},
+ { "outbound", 1, 0, OPT_OUTBOUND_PROXY},
+ { "registrar", 1, 0, OPT_REGISTRAR},
+ { "reg-timeout",1, 0, OPT_REG_TIMEOUT},
+ { "publish", 0, 0, OPT_PUBLISH},
+ { "mwi", 0, 0, OPT_MWI},
+ { "use-100rel", 0, 0, OPT_100REL},
+ { "use-ims", 0, 0, OPT_USE_IMS},
+ { "id", 1, 0, OPT_ID},
+ { "contact", 1, 0, OPT_CONTACT},
+ { "contact-params",1,0, OPT_CONTACT_PARAMS},
+ { "contact-uri-params",1,0, OPT_CONTACT_URI_PARAMS},
+ { "auto-update-nat", 1, 0, OPT_AUTO_UPDATE_NAT},
+ { "use-compact-form", 0, 0, OPT_USE_COMPACT_FORM},
+ { "accept-redirect", 1, 0, OPT_ACCEPT_REDIRECT},
+ { "no-force-lr",0, 0, OPT_NO_FORCE_LR},
+ { "realm", 1, 0, OPT_REALM},
+ { "username", 1, 0, OPT_USERNAME},
+ { "password", 1, 0, OPT_PASSWORD},
+ { "rereg-delay",1, 0, OPT_REG_RETRY_INTERVAL},
+ { "reg-use-proxy", 1, 0, OPT_REG_USE_PROXY},
+ { "nameserver", 1, 0, OPT_NAMESERVER},
+ { "stun-srv", 1, 0, OPT_STUN_SRV},
+ { "add-buddy", 1, 0, OPT_ADD_BUDDY},
+ { "offer-x-ms-msg",0,0,OPT_OFFER_X_MS_MSG},
+ { "no-presence", 0, 0, OPT_NO_PRESENCE},
+ { "auto-answer",1, 0, OPT_AUTO_ANSWER},
+ { "auto-play", 0, 0, OPT_AUTO_PLAY},
+ { "auto-play-hangup",0, 0, OPT_AUTO_PLAY_HANGUP},
+ { "auto-rec", 0, 0, OPT_AUTO_REC},
+ { "auto-loop", 0, 0, OPT_AUTO_LOOP},
+ { "auto-conf", 0, 0, OPT_AUTO_CONF},
+ { "play-file", 1, 0, OPT_PLAY_FILE},
+ { "play-tone", 1, 0, OPT_PLAY_TONE},
+ { "rec-file", 1, 0, OPT_REC_FILE},
+ { "rtp-port", 1, 0, OPT_RTP_PORT},
+
+ { "use-ice", 0, 0, OPT_USE_ICE},
+ { "ice-regular",0, 0, OPT_ICE_REGULAR},
+ { "use-turn", 0, 0, OPT_USE_TURN},
+ { "ice-max-hosts",1, 0, OPT_ICE_MAX_HOSTS},
+ { "ice-no-rtcp",0, 0, OPT_ICE_NO_RTCP},
+ { "turn-srv", 1, 0, OPT_TURN_SRV},
+ { "turn-tcp", 0, 0, OPT_TURN_TCP},
+ { "turn-user", 1, 0, OPT_TURN_USER},
+ { "turn-passwd",1, 0, OPT_TURN_PASSWD},
+
+#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
+ { "use-srtp", 1, 0, OPT_USE_SRTP},
+ { "srtp-secure",1, 0, OPT_SRTP_SECURE},
+#endif
+ { "add-codec", 1, 0, OPT_ADD_CODEC},
+ { "dis-codec", 1, 0, OPT_DIS_CODEC},
+ { "complexity", 1, 0, OPT_COMPLEXITY},
+ { "quality", 1, 0, OPT_QUALITY},
+ { "ptime", 1, 0, OPT_PTIME},
+ { "no-vad", 0, 0, OPT_NO_VAD},
+ { "ec-tail", 1, 0, OPT_EC_TAIL},
+ { "ec-opt", 1, 0, OPT_EC_OPT},
+ { "ilbc-mode", 1, 0, OPT_ILBC_MODE},
+ { "rx-drop-pct",1, 0, OPT_RX_DROP_PCT},
+ { "tx-drop-pct",1, 0, OPT_TX_DROP_PCT},
+ { "next-account",0,0, OPT_NEXT_ACCOUNT},
+ { "next-cred", 0, 0, OPT_NEXT_CRED},
+ { "max-calls", 1, 0, OPT_MAX_CALLS},
+ { "duration", 1, 0, OPT_DURATION},
+ { "thread-cnt", 1, 0, OPT_THREAD_CNT},
+#if defined(PJSIP_HAS_TLS_TRANSPORT) && (PJSIP_HAS_TLS_TRANSPORT != 0)
+ { "use-tls", 0, 0, OPT_USE_TLS},
+ { "tls-ca-file",1, 0, OPT_TLS_CA_FILE},
+ { "tls-cert-file",1,0, OPT_TLS_CERT_FILE},
+ { "tls-privkey-file",1,0, OPT_TLS_PRIV_FILE},
+ { "tls-password",1,0, OPT_TLS_PASSWORD},
+ { "tls-verify-server", 0, 0, OPT_TLS_VERIFY_SERVER},
+ { "tls-verify-client", 0, 0, OPT_TLS_VERIFY_CLIENT},
+ { "tls-neg-timeout", 1, 0, OPT_TLS_NEG_TIMEOUT},
+ { "tls-cipher", 1, 0, OPT_TLS_CIPHER},
+#endif
+ { "capture-dev", 1, 0, OPT_CAPTURE_DEV},
+ { "playback-dev", 1, 0, OPT_PLAYBACK_DEV},
+ { "capture-lat", 1, 0, OPT_CAPTURE_LAT},
+ { "playback-lat", 1, 0, OPT_PLAYBACK_LAT},
+ { "stdout-refresh", 1, 0, OPT_STDOUT_REFRESH},
+ { "stdout-refresh-text", 1, 0, OPT_STDOUT_REFRESH_TEXT},
+#ifdef _IONBF
+ { "stdout-no-buf", 0, 0, OPT_STDOUT_NO_BUF },
+#endif
+ { "snd-auto-close", 1, 0, OPT_SND_AUTO_CLOSE},
+ { "no-tones", 0, 0, OPT_NO_TONES},
+ { "jb-max-size", 1, 0, OPT_JB_MAX_SIZE},
+#if defined(PJ_HAS_IPV6) && PJ_HAS_IPV6
+ { "ipv6", 0, 0, OPT_IPV6},
+#endif
+ { "set-qos", 0, 0, OPT_QOS},
+ { "use-timer", 1, 0, OPT_TIMER},
+ { "timer-se", 1, 0, OPT_TIMER_SE},
+ { "timer-min-se", 1, 0, OPT_TIMER_MIN_SE},
+ { "outb-rid", 1, 0, OPT_OUTB_RID},
+ { "video", 0, 0, OPT_VIDEO},
+ { "extra-audio",0, 0, OPT_EXTRA_AUDIO},
+ { "vcapture-dev", 1, 0, OPT_VCAPTURE_DEV},
+ { "vrender-dev", 1, 0, OPT_VRENDER_DEV},
+ { "play-avi", 1, 0, OPT_PLAY_AVI},
+ { "auto-play-avi", 0, 0, OPT_AUTO_PLAY_AVI},
+ { NULL, 0, 0, 0}
+ };
+ pj_status_t status;
+ pjsua_acc_config *cur_acc;
+ char *config_file = NULL;
+ unsigned i;
+
+ /* Run pj_getopt once to see if user specifies config file to read. */
+ pj_optind = 0;
+ while ((c=pj_getopt_long(argc, argv, "", long_options,
+ &option_index)) != -1)
+ {
+ switch (c) {
+ case OPT_CONFIG_FILE:
+ config_file = pj_optarg;
+ break;
+ }
+ if (config_file)
+ break;
+ }
+
+ if (config_file) {
+ status = read_config_file(app_config.pool, config_file, &argc, &argv);
+ if (status != 0)
+ return status;
+ }
+
+ cfg->acc_cnt = 0;
+ cur_acc = &cfg->acc_cfg[0];
+
+
+ /* Reinitialize and re-run pj_getopt again, possibly with new arguments
+ * read from config file.
+ */
+ pj_optind = 0;
+ while((c=pj_getopt_long(argc,argv, "", long_options,&option_index))!=-1) {
+ pj_str_t tmp;
+ long lval;
+
+ switch (c) {
+
+ case OPT_CONFIG_FILE:
+ /* Ignore as this has been processed before */
+ break;
+
+ case OPT_LOG_FILE:
+ cfg->log_cfg.log_filename = pj_str(pj_optarg);
+ break;
+
+ case OPT_LOG_LEVEL:
+ c = pj_strtoul(pj_cstr(&tmp, pj_optarg));
+ if (c < 0 || c > 6) {
+ PJ_LOG(1,(THIS_FILE,
+ "Error: expecting integer value 0-6 "
+ "for --log-level"));
+ return PJ_EINVAL;
+ }
+ cfg->log_cfg.level = c;
+ pj_log_set_level( c );
+ break;
+
+ case OPT_APP_LOG_LEVEL:
+ cfg->log_cfg.console_level = pj_strtoul(pj_cstr(&tmp, pj_optarg));
+ if (cfg->log_cfg.console_level < 0 || cfg->log_cfg.console_level > 6) {
+ PJ_LOG(1,(THIS_FILE,
+ "Error: expecting integer value 0-6 "
+ "for --app-log-level"));
+ return PJ_EINVAL;
+ }
+ break;
+
+ case OPT_LOG_APPEND:
+ cfg->log_cfg.log_file_flags |= PJ_O_APPEND;
+ break;
+
+ case OPT_COLOR:
+ cfg->log_cfg.decor |= PJ_LOG_HAS_COLOR;
+ break;
+
+ case OPT_NO_COLOR:
+ cfg->log_cfg.decor &= ~PJ_LOG_HAS_COLOR;
+ break;
+
+ case OPT_LIGHT_BG:
+ pj_log_set_color(1, PJ_TERM_COLOR_R);
+ pj_log_set_color(2, PJ_TERM_COLOR_R | PJ_TERM_COLOR_G);
+ pj_log_set_color(3, PJ_TERM_COLOR_B | PJ_TERM_COLOR_G);
+ pj_log_set_color(4, 0);
+ pj_log_set_color(5, 0);
+ pj_log_set_color(77, 0);
+ break;
+
+ case OPT_NO_STDERR:
+ freopen("/dev/null", "w", stderr);
+ break;
+
+ case OPT_HELP:
+ usage();
+ return PJ_EINVAL;
+
+ case OPT_VERSION: /* version */
+ pj_dump_config();
+ return PJ_EINVAL;
+
+ case OPT_NULL_AUDIO:
+ cfg->null_audio = PJ_TRUE;
+ break;
+
+ case OPT_CLOCK_RATE:
+ lval = pj_strtoul(pj_cstr(&tmp, pj_optarg));
+ if (lval < 8000 || lval > 192000) {
+ PJ_LOG(1,(THIS_FILE, "Error: expecting value between "
+ "8000-192000 for conference clock rate"));
+ return PJ_EINVAL;
+ }
+ cfg->media_cfg.clock_rate = lval;
+ break;
+
+ case OPT_SND_CLOCK_RATE:
+ lval = pj_strtoul(pj_cstr(&tmp, pj_optarg));
+ if (lval < 8000 || lval > 192000) {
+ PJ_LOG(1,(THIS_FILE, "Error: expecting value between "
+ "8000-192000 for sound device clock rate"));
+ return PJ_EINVAL;
+ }
+ cfg->media_cfg.snd_clock_rate = lval;
+ break;
+
+ case OPT_STEREO:
+ cfg->media_cfg.channel_count = 2;
+ break;
+
+ case OPT_LOCAL_PORT: /* local-port */
+ lval = pj_strtoul(pj_cstr(&tmp, pj_optarg));
+ if (lval < 0 || lval > 65535) {
+ PJ_LOG(1,(THIS_FILE,
+ "Error: expecting integer value for "
+ "--local-port"));
+ return PJ_EINVAL;
+ }
+ cfg->udp_cfg.port = (pj_uint16_t)lval;
+ break;
+
+ case OPT_IP_ADDR: /* ip-addr */
+ cfg->udp_cfg.public_addr = pj_str(pj_optarg);
+ cfg->rtp_cfg.public_addr = pj_str(pj_optarg);
+ break;
+
+ case OPT_BOUND_ADDR: /* bound-addr */
+ cfg->udp_cfg.bound_addr = pj_str(pj_optarg);
+ cfg->rtp_cfg.bound_addr = pj_str(pj_optarg);
+ break;
+
+ case OPT_NO_UDP: /* no-udp */
+ if (cfg->no_tcp) {
+ PJ_LOG(1,(THIS_FILE,"Error: can not disable both TCP and UDP"));
+ return PJ_EINVAL;
+ }
+
+ cfg->no_udp = PJ_TRUE;
+ break;
+
+ case OPT_NOREFERSUB: /* norefersub */
+ cfg->no_refersub = PJ_TRUE;
+ break;
+
+ case OPT_NO_TCP: /* no-tcp */
+ if (cfg->no_udp) {
+ PJ_LOG(1,(THIS_FILE,"Error: can not disable both TCP and UDP"));
+ return PJ_EINVAL;
+ }
+
+ cfg->no_tcp = PJ_TRUE;
+ break;
+
+ case OPT_PROXY: /* proxy */
+ if (pjsua_verify_sip_url(pj_optarg) != 0) {
+ PJ_LOG(1,(THIS_FILE,
+ "Error: invalid SIP URL '%s' "
+ "in proxy argument", pj_optarg));
+ return PJ_EINVAL;
+ }
+ cur_acc->proxy[cur_acc->proxy_cnt++] = pj_str(pj_optarg);
+ break;
+
+ case OPT_OUTBOUND_PROXY: /* outbound proxy */
+ if (pjsua_verify_sip_url(pj_optarg) != 0) {
+ PJ_LOG(1,(THIS_FILE,
+ "Error: invalid SIP URL '%s' "
+ "in outbound proxy argument", pj_optarg));
+ return PJ_EINVAL;
+ }
+ cfg->cfg.outbound_proxy[cfg->cfg.outbound_proxy_cnt++] = pj_str(pj_optarg);
+ break;
+
+ case OPT_REGISTRAR: /* registrar */
+ if (pjsua_verify_sip_url(pj_optarg) != 0) {
+ PJ_LOG(1,(THIS_FILE,
+ "Error: invalid SIP URL '%s' in "
+ "registrar argument", pj_optarg));
+ return PJ_EINVAL;
+ }
+ cur_acc->reg_uri = pj_str(pj_optarg);
+ break;
+
+ case OPT_REG_TIMEOUT: /* reg-timeout */
+ cur_acc->reg_timeout = pj_strtoul(pj_cstr(&tmp,pj_optarg));
+ if (cur_acc->reg_timeout < 1 || cur_acc->reg_timeout > 3600) {
+ PJ_LOG(1,(THIS_FILE,
+ "Error: invalid value for --reg-timeout "
+ "(expecting 1-3600)"));
+ return PJ_EINVAL;
+ }
+ break;
+
+ case OPT_PUBLISH: /* publish */
+ cur_acc->publish_enabled = PJ_TRUE;
+ break;
+
+ case OPT_MWI: /* mwi */
+ cur_acc->mwi_enabled = PJ_TRUE;
+ break;
+
+ case OPT_100REL: /** 100rel */
+ cur_acc->require_100rel = PJSUA_100REL_MANDATORY;
+ cfg->cfg.require_100rel = PJSUA_100REL_MANDATORY;
+ break;
+
+ case OPT_TIMER: /** session timer */
+ lval = pj_strtoul(pj_cstr(&tmp, pj_optarg));
+ if (lval < 0 || lval > 3) {
+ PJ_LOG(1,(THIS_FILE,
+ "Error: expecting integer value 0-3 for --use-timer"));
+ return PJ_EINVAL;
+ }
+ cur_acc->use_timer = lval;
+ cfg->cfg.use_timer = lval;
+ break;
+
+ case OPT_TIMER_SE: /** session timer session expiration */
+ cur_acc->timer_setting.sess_expires = pj_strtoul(pj_cstr(&tmp, pj_optarg));
+ if (cur_acc->timer_setting.sess_expires < 90) {
+ PJ_LOG(1,(THIS_FILE,
+ "Error: invalid value for --timer-se "
+ "(expecting higher than 90)"));
+ return PJ_EINVAL;
+ }
+ cfg->cfg.timer_setting.sess_expires = cur_acc->timer_setting.sess_expires;
+ break;
+
+ case OPT_TIMER_MIN_SE: /** session timer minimum session expiration */
+ cur_acc->timer_setting.min_se = pj_strtoul(pj_cstr(&tmp, pj_optarg));
+ if (cur_acc->timer_setting.min_se < 90) {
+ PJ_LOG(1,(THIS_FILE,
+ "Error: invalid value for --timer-min-se "
+ "(expecting higher than 90)"));
+ return PJ_EINVAL;
+ }
+ cfg->cfg.timer_setting.min_se = cur_acc->timer_setting.min_se;
+ break;
+
+ case OPT_OUTB_RID: /* Outbound reg-id */
+ cur_acc->rfc5626_reg_id = pj_str(pj_optarg);
+ break;
+
+ case OPT_USE_IMS: /* Activate IMS settings */
+ cur_acc->auth_pref.initial_auth = PJ_TRUE;
+ break;
+
+ case OPT_ID: /* id */
+ if (pjsua_verify_url(pj_optarg) != 0) {
+ PJ_LOG(1,(THIS_FILE,
+ "Error: invalid SIP URL '%s' "
+ "in local id argument", pj_optarg));
+ return PJ_EINVAL;
+ }
+ cur_acc->id = pj_str(pj_optarg);
+ break;
+
+ case OPT_CONTACT: /* contact */
+ if (pjsua_verify_sip_url(pj_optarg) != 0) {
+ PJ_LOG(1,(THIS_FILE,
+ "Error: invalid SIP URL '%s' "
+ "in contact argument", pj_optarg));
+ return PJ_EINVAL;
+ }
+ cur_acc->force_contact = pj_str(pj_optarg);
+ break;
+
+ case OPT_CONTACT_PARAMS:
+ cur_acc->contact_params = pj_str(pj_optarg);
+ break;
+
+ case OPT_CONTACT_URI_PARAMS:
+ cur_acc->contact_uri_params = pj_str(pj_optarg);
+ break;
+
+ case OPT_AUTO_UPDATE_NAT: /* OPT_AUTO_UPDATE_NAT */
+ cur_acc->allow_contact_rewrite = pj_strtoul(pj_cstr(&tmp, pj_optarg));
+ break;
+
+ case OPT_USE_COMPACT_FORM:
+ /* enable compact form - from Ticket #342 */
+ {
+ extern pj_bool_t pjsip_use_compact_form;
+ extern pj_bool_t pjsip_include_allow_hdr_in_dlg;
+ extern pj_bool_t pjmedia_add_rtpmap_for_static_pt;
+
+ pjsip_use_compact_form = PJ_TRUE;
+ /* do not transmit Allow header */
+ pjsip_include_allow_hdr_in_dlg = PJ_FALSE;
+ /* Do not include rtpmap for static payload types (<96) */
+ pjmedia_add_rtpmap_for_static_pt = PJ_FALSE;
+ }
+ break;
+
+ case OPT_ACCEPT_REDIRECT:
+ cfg->redir_op = my_atoi(pj_optarg);
+ if (cfg->redir_op<0 || cfg->redir_op>PJSIP_REDIRECT_STOP) {
+ PJ_LOG(1,(THIS_FILE,
+ "Error: accept-redirect value '%s' ", pj_optarg));
+ return PJ_EINVAL;
+ }
+ break;
+
+ case OPT_NO_FORCE_LR:
+ cfg->cfg.force_lr = PJ_FALSE;
+ break;
+
+ case OPT_NEXT_ACCOUNT: /* Add more account. */
+ cfg->acc_cnt++;
+ cur_acc = &cfg->acc_cfg[cfg->acc_cnt];
+ break;
+
+ case OPT_USERNAME: /* Default authentication user */
+ cur_acc->cred_info[cur_acc->cred_count].username = pj_str(pj_optarg);
+ cur_acc->cred_info[cur_acc->cred_count].scheme = pj_str("Digest");
+ break;
+
+ case OPT_REALM: /* Default authentication realm. */
+ cur_acc->cred_info[cur_acc->cred_count].realm = pj_str(pj_optarg);
+ break;
+
+ case OPT_PASSWORD: /* authentication password */
+ cur_acc->cred_info[cur_acc->cred_count].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
+ cur_acc->cred_info[cur_acc->cred_count].data = pj_str(pj_optarg);
+#if PJSIP_HAS_DIGEST_AKA_AUTH
+ cur_acc->cred_info[cur_acc->cred_count].data_type |= PJSIP_CRED_DATA_EXT_AKA;
+ cur_acc->cred_info[cur_acc->cred_count].ext.aka.k = pj_str(pj_optarg);
+ cur_acc->cred_info[cur_acc->cred_count].ext.aka.cb = &pjsip_auth_create_aka_response;
+#endif
+ break;
+
+ case OPT_REG_RETRY_INTERVAL:
+ cur_acc->reg_retry_interval = pj_strtoul(pj_cstr(&tmp, pj_optarg));
+ break;
+
+ case OPT_REG_USE_PROXY:
+ cur_acc->reg_use_proxy = (unsigned)pj_strtoul(pj_cstr(&tmp, pj_optarg));
+ if (cur_acc->reg_use_proxy > 3) {
+ PJ_LOG(1,(THIS_FILE, "Error: invalid --reg-use-proxy value '%s'",
+ pj_optarg));
+ return PJ_EINVAL;
+ }
+ break;
+
+ case OPT_NEXT_CRED: /* next credential */
+ cur_acc->cred_count++;
+ break;
+
+ case OPT_NAMESERVER: /* nameserver */
+ cfg->cfg.nameserver[cfg->cfg.nameserver_count++] = pj_str(pj_optarg);
+ if (cfg->cfg.nameserver_count > PJ_ARRAY_SIZE(cfg->cfg.nameserver)) {
+ PJ_LOG(1,(THIS_FILE, "Error: too many nameservers"));
+ return PJ_ETOOMANY;
+ }
+ break;
+
+ case OPT_STUN_SRV: /* STUN server */
+ cfg->cfg.stun_host = pj_str(pj_optarg);
+ if (cfg->cfg.stun_srv_cnt==PJ_ARRAY_SIZE(cfg->cfg.stun_srv)) {
+ PJ_LOG(1,(THIS_FILE, "Error: too many STUN servers"));
+ return PJ_ETOOMANY;
+ }
+ cfg->cfg.stun_srv[cfg->cfg.stun_srv_cnt++] = pj_str(pj_optarg);
+ break;
+
+ case OPT_ADD_BUDDY: /* Add to buddy list. */
+ if (pjsua_verify_url(pj_optarg) != 0) {
+ PJ_LOG(1,(THIS_FILE,
+ "Error: invalid URL '%s' in "
+ "--add-buddy option", pj_optarg));
+ return -1;
+ }
+ if (cfg->buddy_cnt == PJ_ARRAY_SIZE(cfg->buddy_cfg)) {
+ PJ_LOG(1,(THIS_FILE,
+ "Error: too many buddies in buddy list."));
+ return -1;
+ }
+ cfg->buddy_cfg[cfg->buddy_cnt].uri = pj_str(pj_optarg);
+ cfg->buddy_cnt++;
+ break;
+
+ case OPT_AUTO_PLAY:
+ cfg->auto_play = 1;
+ break;
+
+ case OPT_AUTO_PLAY_HANGUP:
+ cfg->auto_play_hangup = 1;
+ break;
+
+ case OPT_AUTO_REC:
+ cfg->auto_rec = 1;
+ break;
+
+ case OPT_AUTO_LOOP:
+ cfg->auto_loop = 1;
+ break;
+
+ case OPT_AUTO_CONF:
+ cfg->auto_conf = 1;
+ break;
+
+ case OPT_PLAY_FILE:
+ cfg->wav_files[cfg->wav_count++] = pj_str(pj_optarg);
+ break;
+
+ case OPT_PLAY_TONE:
+ {
+ int f1, f2, on, off;
+ int n;
+
+ n = sscanf(pj_optarg, "%d,%d,%d,%d", &f1, &f2, &on, &off);
+ if (n != 4) {
+ puts("Expecting f1,f2,on,off in --play-tone");
+ return -1;
+ }
+
+ cfg->tones[cfg->tone_count].freq1 = (short)f1;
+ cfg->tones[cfg->tone_count].freq2 = (short)f2;
+ cfg->tones[cfg->tone_count].on_msec = (short)on;
+ cfg->tones[cfg->tone_count].off_msec = (short)off;
+ ++cfg->tone_count;
+ }
+ break;
+
+ case OPT_REC_FILE:
+ cfg->rec_file = pj_str(pj_optarg);
+ break;
+
+ case OPT_USE_ICE:
+ cfg->media_cfg.enable_ice = PJ_TRUE;
+ break;
+
+ case OPT_ICE_REGULAR:
+ cfg->media_cfg.ice_opt.aggressive = PJ_FALSE;
+ break;
+
+ case OPT_USE_TURN:
+ cfg->media_cfg.enable_turn = PJ_TRUE;
+ break;
+
+ case OPT_ICE_MAX_HOSTS:
+ cfg->media_cfg.ice_max_host_cands = my_atoi(pj_optarg);
+ break;
+
+ case OPT_ICE_NO_RTCP:
+ cfg->media_cfg.ice_no_rtcp = PJ_TRUE;
+ break;
+
+ case OPT_TURN_SRV:
+ cfg->media_cfg.turn_server = pj_str(pj_optarg);
+ break;
+
+ case OPT_TURN_TCP:
+ cfg->media_cfg.turn_conn_type = PJ_TURN_TP_TCP;
+ break;
+
+ case OPT_TURN_USER:
+ cfg->media_cfg.turn_auth_cred.type = PJ_STUN_AUTH_CRED_STATIC;
+ cfg->media_cfg.turn_auth_cred.data.static_cred.realm = pj_str("*");
+ cfg->media_cfg.turn_auth_cred.data.static_cred.username = pj_str(pj_optarg);
+ break;
+
+ case OPT_TURN_PASSWD:
+ cfg->media_cfg.turn_auth_cred.data.static_cred.data_type = PJ_STUN_PASSWD_PLAIN;
+ cfg->media_cfg.turn_auth_cred.data.static_cred.data = pj_str(pj_optarg);
+ break;
+
+#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
+ case OPT_USE_SRTP:
+ app_config.cfg.use_srtp = my_atoi(pj_optarg);
+ if (!pj_isdigit(*pj_optarg) || app_config.cfg.use_srtp > 3) {
+ PJ_LOG(1,(THIS_FILE, "Invalid value for --use-srtp option"));
+ return -1;
+ }
+ if ((int)app_config.cfg.use_srtp == 3) {
+ /* SRTP optional mode with duplicated media offer */
+ app_config.cfg.use_srtp = PJMEDIA_SRTP_OPTIONAL;
+ app_config.cfg.srtp_optional_dup_offer = PJ_TRUE;
+ cur_acc->srtp_optional_dup_offer = PJ_TRUE;
+ }
+ cur_acc->use_srtp = app_config.cfg.use_srtp;
+ break;
+ case OPT_SRTP_SECURE:
+ app_config.cfg.srtp_secure_signaling = my_atoi(pj_optarg);
+ if (!pj_isdigit(*pj_optarg) ||
+ app_config.cfg.srtp_secure_signaling > 2)
+ {
+ PJ_LOG(1,(THIS_FILE, "Invalid value for --srtp-secure option"));
+ return -1;
+ }
+ cur_acc->srtp_secure_signaling = app_config.cfg.srtp_secure_signaling;
+ break;
+#endif
+
+ case OPT_RTP_PORT:
+ cfg->rtp_cfg.port = my_atoi(pj_optarg);
+ if (cfg->rtp_cfg.port == 0) {
+ enum { START_PORT=4000 };
+ unsigned range;
+
+ range = (65535-START_PORT-PJSUA_MAX_CALLS*2);
+ cfg->rtp_cfg.port = START_PORT +
+ ((pj_rand() % range) & 0xFFFE);
+ }
+
+ if (cfg->rtp_cfg.port < 1 || cfg->rtp_cfg.port > 65535) {
+ PJ_LOG(1,(THIS_FILE,
+ "Error: rtp-port argument value "
+ "(expecting 1-65535"));
+ return -1;
+ }
+ break;
+
+ case OPT_DIS_CODEC:
+ cfg->codec_dis[cfg->codec_dis_cnt++] = pj_str(pj_optarg);
+ break;
+
+ case OPT_ADD_CODEC:
+ cfg->codec_arg[cfg->codec_cnt++] = pj_str(pj_optarg);
+ break;
+
+ /* These options were no longer valid after new pjsua */
+ /*
+ case OPT_COMPLEXITY:
+ cfg->complexity = my_atoi(pj_optarg);
+ if (cfg->complexity < 0 || cfg->complexity > 10) {
+ PJ_LOG(1,(THIS_FILE,
+ "Error: invalid --complexity (expecting 0-10"));
+ return -1;
+ }
+ break;
+ */
+
+ case OPT_DURATION:
+ cfg->duration = my_atoi(pj_optarg);
+ break;
+
+ case OPT_THREAD_CNT:
+ cfg->cfg.thread_cnt = my_atoi(pj_optarg);
+ if (cfg->cfg.thread_cnt > 128) {
+ PJ_LOG(1,(THIS_FILE,
+ "Error: invalid --thread-cnt option"));
+ return -1;
+ }
+ break;
+
+ case OPT_PTIME:
+ cfg->media_cfg.ptime = my_atoi(pj_optarg);
+ if (cfg->media_cfg.ptime < 10 || cfg->media_cfg.ptime > 1000) {
+ PJ_LOG(1,(THIS_FILE,
+ "Error: invalid --ptime option"));
+ return -1;
+ }
+ break;
+
+ case OPT_NO_VAD:
+ cfg->media_cfg.no_vad = PJ_TRUE;
+ break;
+
+ case OPT_EC_TAIL:
+ cfg->media_cfg.ec_tail_len = my_atoi(pj_optarg);
+ if (cfg->media_cfg.ec_tail_len > 1000) {
+ PJ_LOG(1,(THIS_FILE, "I think the ec-tail length setting "
+ "is too big"));
+ return -1;
+ }
+ break;
+
+ case OPT_EC_OPT:
+ cfg->media_cfg.ec_options = my_atoi(pj_optarg);
+ break;
+
+ case OPT_QUALITY:
+ cfg->media_cfg.quality = my_atoi(pj_optarg);
+ if (cfg->media_cfg.quality < 0 || cfg->media_cfg.quality > 10) {
+ PJ_LOG(1,(THIS_FILE,
+ "Error: invalid --quality (expecting 0-10"));
+ return -1;
+ }
+ break;
+
+ case OPT_ILBC_MODE:
+ cfg->media_cfg.ilbc_mode = my_atoi(pj_optarg);
+ if (cfg->media_cfg.ilbc_mode!=20 && cfg->media_cfg.ilbc_mode!=30) {
+ PJ_LOG(1,(THIS_FILE,
+ "Error: invalid --ilbc-mode (expecting 20 or 30"));
+ return -1;
+ }
+ break;
+
+ case OPT_RX_DROP_PCT:
+ cfg->media_cfg.rx_drop_pct = my_atoi(pj_optarg);
+ if (cfg->media_cfg.rx_drop_pct > 100) {
+ PJ_LOG(1,(THIS_FILE,
+ "Error: invalid --rx-drop-pct (expecting <= 100"));
+ return -1;
+ }
+ break;
+
+ case OPT_TX_DROP_PCT:
+ cfg->media_cfg.tx_drop_pct = my_atoi(pj_optarg);
+ if (cfg->media_cfg.tx_drop_pct > 100) {
+ PJ_LOG(1,(THIS_FILE,
+ "Error: invalid --tx-drop-pct (expecting <= 100"));
+ return -1;
+ }
+ break;
+
+ case OPT_AUTO_ANSWER:
+ cfg->auto_answer = my_atoi(pj_optarg);
+ if (cfg->auto_answer < 100 || cfg->auto_answer > 699) {
+ PJ_LOG(1,(THIS_FILE,
+ "Error: invalid code in --auto-answer "
+ "(expecting 100-699"));
+ return -1;
+ }
+ break;
+
+ case OPT_MAX_CALLS:
+ cfg->cfg.max_calls = my_atoi(pj_optarg);
+ if (cfg->cfg.max_calls < 1 || cfg->cfg.max_calls > PJSUA_MAX_CALLS) {
+ PJ_LOG(1,(THIS_FILE,"Error: maximum call setting exceeds "
+ "compile time limit (PJSUA_MAX_CALLS=%d)",
+ PJSUA_MAX_CALLS));
+ return -1;
+ }
+ break;
+
+#if defined(PJSIP_HAS_TLS_TRANSPORT) && (PJSIP_HAS_TLS_TRANSPORT != 0)
+ case OPT_USE_TLS:
+ cfg->use_tls = PJ_TRUE;
+ break;
+
+ case OPT_TLS_CA_FILE:
+ cfg->udp_cfg.tls_setting.ca_list_file = pj_str(pj_optarg);
+ break;
+
+ case OPT_TLS_CERT_FILE:
+ cfg->udp_cfg.tls_setting.cert_file = pj_str(pj_optarg);
+ break;
+
+ case OPT_TLS_PRIV_FILE:
+ cfg->udp_cfg.tls_setting.privkey_file = pj_str(pj_optarg);
+ break;
+
+ case OPT_TLS_PASSWORD:
+ cfg->udp_cfg.tls_setting.password = pj_str(pj_optarg);
+ break;
+
+ case OPT_TLS_VERIFY_SERVER:
+ cfg->udp_cfg.tls_setting.verify_server = PJ_TRUE;
+ break;
+
+ case OPT_TLS_VERIFY_CLIENT:
+ cfg->udp_cfg.tls_setting.verify_client = PJ_TRUE;
+ cfg->udp_cfg.tls_setting.require_client_cert = PJ_TRUE;
+ break;
+
+ case OPT_TLS_NEG_TIMEOUT:
+ cfg->udp_cfg.tls_setting.timeout.sec = atoi(pj_optarg);
+ break;
+
+ case OPT_TLS_CIPHER:
+ {
+ pj_ssl_cipher cipher;
+
+ if (pj_ansi_strnicmp(pj_optarg, "0x", 2) == 0) {
+ pj_str_t cipher_st = pj_str(pj_optarg + 2);
+ cipher = pj_strtoul2(&cipher_st, NULL, 16);
+ } else {
+ cipher = atoi(pj_optarg);
+ }
+
+ if (pj_ssl_cipher_is_supported(cipher)) {
+ static pj_ssl_cipher tls_ciphers[128];
+
+ tls_ciphers[cfg->udp_cfg.tls_setting.ciphers_num++] = cipher;
+ cfg->udp_cfg.tls_setting.ciphers = tls_ciphers;
+ } else {
+ pj_ssl_cipher ciphers[128];
+ unsigned j, ciphers_cnt;
+
+ ciphers_cnt = PJ_ARRAY_SIZE(ciphers);
+ pj_ssl_cipher_get_availables(ciphers, &ciphers_cnt);
+
+ PJ_LOG(1,(THIS_FILE, "Cipher \"%s\" is not supported by "
+ "TLS/SSL backend.", pj_optarg));
+ printf("Available TLS/SSL ciphers (%d):\n", ciphers_cnt);
+ for (j=0; j<ciphers_cnt; ++j)
+ printf("- 0x%06X: %s\n", ciphers[j], pj_ssl_cipher_name(ciphers[j]));
+ return -1;
+ }
+ }
+ break;
+#endif /* PJSIP_HAS_TLS_TRANSPORT */
+
+ case OPT_CAPTURE_DEV:
+ cfg->capture_dev = atoi(pj_optarg);
+ break;
+
+ case OPT_PLAYBACK_DEV:
+ cfg->playback_dev = atoi(pj_optarg);
+ break;
+
+ case OPT_STDOUT_REFRESH:
+ stdout_refresh = atoi(pj_optarg);
+ break;
+
+ case OPT_STDOUT_REFRESH_TEXT:
+ stdout_refresh_text = pj_optarg;
+ break;
+
+#ifdef _IONBF
+ case OPT_STDOUT_NO_BUF:
+ setvbuf(stdout, NULL, _IONBF, 0);
+ break;
+#endif
+
+ case OPT_CAPTURE_LAT:
+ cfg->capture_lat = atoi(pj_optarg);
+ break;
+
+ case OPT_PLAYBACK_LAT:
+ cfg->playback_lat = atoi(pj_optarg);
+ break;
+
+ case OPT_SND_AUTO_CLOSE:
+ cfg->media_cfg.snd_auto_close_time = atoi(pj_optarg);
+ break;
+
+ case OPT_NO_TONES:
+ cfg->no_tones = PJ_TRUE;
+ break;
+
+ case OPT_JB_MAX_SIZE:
+ cfg->media_cfg.jb_max = atoi(pj_optarg);
+ break;
+
+#if defined(PJ_HAS_IPV6) && PJ_HAS_IPV6
+ case OPT_IPV6:
+ cfg->ipv6 = PJ_TRUE;
+ break;
+#endif
+ case OPT_QOS:
+ cfg->enable_qos = PJ_TRUE;
+ /* Set RTP traffic type to Voice */
+ cfg->rtp_cfg.qos_type = PJ_QOS_TYPE_VOICE;
+ /* Directly apply DSCP value to SIP traffic. Say lets
+ * set it to CS3 (DSCP 011000). Note that this will not
+ * work on all platforms.
+ */
+ cfg->udp_cfg.qos_params.flags = PJ_QOS_PARAM_HAS_DSCP;
+ cfg->udp_cfg.qos_params.dscp_val = 0x18;
+ break;
+ case OPT_VIDEO:
+ cfg->vid.vid_cnt = 1;
+ cfg->vid.in_auto_show = PJ_TRUE;
+ cfg->vid.out_auto_transmit = PJ_TRUE;
+ break;
+ case OPT_EXTRA_AUDIO:
+ cfg->aud_cnt++;
+ break;
+
+ case OPT_VCAPTURE_DEV:
+ cfg->vid.vcapture_dev = atoi(pj_optarg);
+ cur_acc->vid_cap_dev = cfg->vid.vcapture_dev;
+ break;
+
+ case OPT_VRENDER_DEV:
+ cfg->vid.vrender_dev = atoi(pj_optarg);
+ cur_acc->vid_rend_dev = cfg->vid.vrender_dev;
+ break;
+
+ case OPT_PLAY_AVI:
+ if (app_config.avi_cnt >= MAX_AVI) {
+ PJ_LOG(1,(THIS_FILE, "Too many AVIs"));
+ return -1;
+ }
+ app_config.avi[app_config.avi_cnt++].path = pj_str(pj_optarg);
+ break;
+
+ case OPT_AUTO_PLAY_AVI:
+ app_config.avi_auto_play = PJ_TRUE;
+ break;
+
+ default:
+ PJ_LOG(1,(THIS_FILE,
+ "Argument \"%s\" is not valid. Use --help to see help",
+ argv[pj_optind-1]));
+ return -1;
+ }
+ }
+
+ if (pj_optind != argc) {
+ pj_str_t uri_arg;
+
+ if (pjsua_verify_url(argv[pj_optind]) != PJ_SUCCESS) {
+ PJ_LOG(1,(THIS_FILE, "Invalid SIP URI %s", argv[pj_optind]));
+ return -1;
+ }
+ uri_arg = pj_str(argv[pj_optind]);
+ if (uri_to_call)
+ *uri_to_call = uri_arg;
+ pj_optind++;
+
+ /* Add URI to call to buddy list if it's not already there */
+ for (i=0; i<cfg->buddy_cnt; ++i) {
+ if (pj_stricmp(&cfg->buddy_cfg[i].uri, &uri_arg)==0)
+ break;
+ }
+ if (i == cfg->buddy_cnt && cfg->buddy_cnt < PJSUA_MAX_BUDDIES) {
+ cfg->buddy_cfg[cfg->buddy_cnt++].uri = uri_arg;
+ }
+
+ } else {
+ if (uri_to_call)
+ uri_to_call->slen = 0;
+ }
+
+ if (pj_optind != argc) {
+ PJ_LOG(1,(THIS_FILE, "Error: unknown options %s", argv[pj_optind]));
+ return PJ_EINVAL;
+ }
+
+ if (cfg->acc_cfg[cfg->acc_cnt].id.slen)
+ cfg->acc_cnt++;
+
+ for (i=0; i<cfg->acc_cnt; ++i) {
+ pjsua_acc_config *acfg = &cfg->acc_cfg[i];
+
+ if (acfg->cred_info[acfg->cred_count].username.slen)
+ {
+ acfg->cred_count++;
+ }
+
+ /* When IMS mode is enabled for the account, verify that settings
+ * are okay.
+ */
+ /* For now we check if IMS mode is activated by looking if
+ * initial_auth is set.
+ */
+ if (acfg->auth_pref.initial_auth && acfg->cred_count) {
+ /* Realm must point to the real domain */
+ if (*acfg->cred_info[0].realm.ptr=='*') {
+ PJ_LOG(1,(THIS_FILE,
+ "Error: cannot use '*' as realm with IMS"));
+ return PJ_EINVAL;
+ }
+
+ /* Username for authentication must be in a@b format */
+ if (strchr(acfg->cred_info[0].username.ptr, '@')==0) {
+ PJ_LOG(1,(THIS_FILE,
+ "Error: Username for authentication must "
+ "be in user@domain format with IMS"));
+ return PJ_EINVAL;
+ }
+ }
+ }
+
+
+ return PJ_SUCCESS;
+}
+
+
+/*
+ * Save account settings
+ */
+static void write_account_settings(int acc_index, pj_str_t *result)
+{
+ unsigned i;
+ char line[128];
+ pjsua_acc_config *acc_cfg = &app_config.acc_cfg[acc_index];
+
+
+ pj_ansi_sprintf(line, "\n#\n# Account %d:\n#\n", acc_index);
+ pj_strcat2(result, line);
+
+
+ /* Identity */
+ if (acc_cfg->id.slen) {
+ pj_ansi_sprintf(line, "--id %.*s\n",
+ (int)acc_cfg->id.slen,
+ acc_cfg->id.ptr);
+ pj_strcat2(result, line);
+ }
+
+ /* Registrar server */
+ if (acc_cfg->reg_uri.slen) {
+ pj_ansi_sprintf(line, "--registrar %.*s\n",
+ (int)acc_cfg->reg_uri.slen,
+ acc_cfg->reg_uri.ptr);
+ pj_strcat2(result, line);
+
+ pj_ansi_sprintf(line, "--reg-timeout %u\n",
+ acc_cfg->reg_timeout);
+ pj_strcat2(result, line);
+ }
+
+ /* Contact */
+ if (acc_cfg->force_contact.slen) {
+ pj_ansi_sprintf(line, "--contact %.*s\n",
+ (int)acc_cfg->force_contact.slen,
+ acc_cfg->force_contact.ptr);
+ pj_strcat2(result, line);
+ }
+
+ /* Contact header parameters */
+ if (acc_cfg->contact_params.slen) {
+ pj_ansi_sprintf(line, "--contact-params %.*s\n",
+ (int)acc_cfg->contact_params.slen,
+ acc_cfg->contact_params.ptr);
+ pj_strcat2(result, line);
+ }
+
+ /* Contact URI parameters */
+ if (acc_cfg->contact_uri_params.slen) {
+ pj_ansi_sprintf(line, "--contact-uri-params %.*s\n",
+ (int)acc_cfg->contact_uri_params.slen,
+ acc_cfg->contact_uri_params.ptr);
+ pj_strcat2(result, line);
+ }
+
+ /* */
+ if (acc_cfg->allow_contact_rewrite!=1)
+ {
+ pj_ansi_sprintf(line, "--auto-update-nat %i\n",
+ (int)acc_cfg->allow_contact_rewrite);
+ pj_strcat2(result, line);
+ }
+
+#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
+ /* SRTP */
+ if (acc_cfg->use_srtp) {
+ int use_srtp = (int)acc_cfg->use_srtp;
+ if (use_srtp == PJMEDIA_SRTP_OPTIONAL &&
+ acc_cfg->srtp_optional_dup_offer)
+ {
+ use_srtp = 3;
+ }
+ pj_ansi_sprintf(line, "--use-srtp %i\n", use_srtp);
+ pj_strcat2(result, line);
+ }
+ if (acc_cfg->srtp_secure_signaling !=
+ PJSUA_DEFAULT_SRTP_SECURE_SIGNALING)
+ {
+ pj_ansi_sprintf(line, "--srtp-secure %d\n",
+ acc_cfg->srtp_secure_signaling);
+ pj_strcat2(result, line);
+ }
+#endif
+
+ /* Proxy */
+ for (i=0; i<acc_cfg->proxy_cnt; ++i) {
+ pj_ansi_sprintf(line, "--proxy %.*s\n",
+ (int)acc_cfg->proxy[i].slen,
+ acc_cfg->proxy[i].ptr);
+ pj_strcat2(result, line);
+ }
+
+ /* Credentials */
+ for (i=0; i<acc_cfg->cred_count; ++i) {
+ if (acc_cfg->cred_info[i].realm.slen) {
+ pj_ansi_sprintf(line, "--realm %.*s\n",
+ (int)acc_cfg->cred_info[i].realm.slen,
+ acc_cfg->cred_info[i].realm.ptr);
+ pj_strcat2(result, line);
+ }
+
+ if (acc_cfg->cred_info[i].username.slen) {
+ pj_ansi_sprintf(line, "--username %.*s\n",
+ (int)acc_cfg->cred_info[i].username.slen,
+ acc_cfg->cred_info[i].username.ptr);
+ pj_strcat2(result, line);
+ }
+
+ if (acc_cfg->cred_info[i].data.slen) {
+ pj_ansi_sprintf(line, "--password %.*s\n",
+ (int)acc_cfg->cred_info[i].data.slen,
+ acc_cfg->cred_info[i].data.ptr);
+ pj_strcat2(result, line);
+ }
+
+ if (i != acc_cfg->cred_count - 1)
+ pj_strcat2(result, "--next-cred\n");
+ }
+
+ /* reg-use-proxy */
+ if (acc_cfg->reg_use_proxy != 3) {
+ pj_ansi_sprintf(line, "--reg-use-proxy %d\n",
+ acc_cfg->reg_use_proxy);
+ pj_strcat2(result, line);
+ }
+
+ /* rereg-delay */
+ if (acc_cfg->reg_retry_interval != PJSUA_REG_RETRY_INTERVAL) {
+ pj_ansi_sprintf(line, "--rereg-delay %d\n",
+ acc_cfg->reg_retry_interval);
+ pj_strcat2(result, line);
+ }
+
+ /* 100rel extension */
+ if (acc_cfg->require_100rel) {
+ pj_strcat2(result, "--use-100rel\n");
+ }
+
+ /* Session Timer extension */
+ if (acc_cfg->use_timer) {
+ pj_ansi_sprintf(line, "--use-timer %d\n",
+ acc_cfg->use_timer);
+ pj_strcat2(result, line);
+ }
+ if (acc_cfg->timer_setting.min_se != 90) {
+ pj_ansi_sprintf(line, "--timer-min-se %d\n",
+ acc_cfg->timer_setting.min_se);
+ pj_strcat2(result, line);
+ }
+ if (acc_cfg->timer_setting.sess_expires != PJSIP_SESS_TIMER_DEF_SE) {
+ pj_ansi_sprintf(line, "--timer-se %d\n",
+ acc_cfg->timer_setting.sess_expires);
+ pj_strcat2(result, line);
+ }
+
+ /* Publish */
+ if (acc_cfg->publish_enabled)
+ pj_strcat2(result, "--publish\n");
+
+ /* MWI */
+ if (acc_cfg->mwi_enabled)
+ pj_strcat2(result, "--mwi\n");
+}
+
+
+/*
+ * Write settings.
+ */
+static int write_settings(const struct app_config *config,
+ char *buf, pj_size_t max)
+{
+ unsigned acc_index;
+ unsigned i;
+ pj_str_t cfg;
+ char line[128];
+ extern pj_bool_t pjsip_use_compact_form;
+
+ PJ_UNUSED_ARG(max);
+
+ cfg.ptr = buf;
+ cfg.slen = 0;
+
+ /* Logging. */
+ pj_strcat2(&cfg, "#\n# Logging options:\n#\n");
+ pj_ansi_sprintf(line, "--log-level %d\n",
+ config->log_cfg.level);
+ pj_strcat2(&cfg, line);
+
+ pj_ansi_sprintf(line, "--app-log-level %d\n",
+ config->log_cfg.console_level);
+ pj_strcat2(&cfg, line);
+
+ if (config->log_cfg.log_filename.slen) {
+ pj_ansi_sprintf(line, "--log-file %.*s\n",
+ (int)config->log_cfg.log_filename.slen,
+ config->log_cfg.log_filename.ptr);
+ pj_strcat2(&cfg, line);
+ }
+
+ if (config->log_cfg.log_file_flags & PJ_O_APPEND) {
+ pj_strcat2(&cfg, "--log-append\n");
+ }
+
+ /* Save account settings. */
+ for (acc_index=0; acc_index < config->acc_cnt; ++acc_index) {
+
+ write_account_settings(acc_index, &cfg);
+
+ if (acc_index < config->acc_cnt-1)
+ pj_strcat2(&cfg, "--next-account\n");
+ }
+
+
+ pj_strcat2(&cfg, "\n#\n# Network settings:\n#\n");
+
+ /* Nameservers */
+ for (i=0; i<config->cfg.nameserver_count; ++i) {
+ pj_ansi_sprintf(line, "--nameserver %.*s\n",
+ (int)config->cfg.nameserver[i].slen,
+ config->cfg.nameserver[i].ptr);
+ pj_strcat2(&cfg, line);
+ }
+
+ /* Outbound proxy */
+ for (i=0; i<config->cfg.outbound_proxy_cnt; ++i) {
+ pj_ansi_sprintf(line, "--outbound %.*s\n",
+ (int)config->cfg.outbound_proxy[i].slen,
+ config->cfg.outbound_proxy[i].ptr);
+ pj_strcat2(&cfg, line);
+ }
+
+ /* Transport options */
+ if (config->ipv6) {
+ pj_strcat2(&cfg, "--ipv6\n");
+ }
+ if (config->enable_qos) {
+ pj_strcat2(&cfg, "--set-qos\n");
+ }
+
+ /* UDP Transport. */
+ pj_ansi_sprintf(line, "--local-port %d\n", config->udp_cfg.port);
+ pj_strcat2(&cfg, line);
+
+ /* IP address, if any. */
+ if (config->udp_cfg.public_addr.slen) {
+ pj_ansi_sprintf(line, "--ip-addr %.*s\n",
+ (int)config->udp_cfg.public_addr.slen,
+ config->udp_cfg.public_addr.ptr);
+ pj_strcat2(&cfg, line);
+ }
+
+ /* Bound IP address, if any. */
+ if (config->udp_cfg.bound_addr.slen) {
+ pj_ansi_sprintf(line, "--bound-addr %.*s\n",
+ (int)config->udp_cfg.bound_addr.slen,
+ config->udp_cfg.bound_addr.ptr);
+ pj_strcat2(&cfg, line);
+ }
+
+ /* No TCP ? */
+ if (config->no_tcp) {
+ pj_strcat2(&cfg, "--no-tcp\n");
+ }
+
+ /* No UDP ? */
+ if (config->no_udp) {
+ pj_strcat2(&cfg, "--no-udp\n");
+ }
+
+ /* STUN */
+ for (i=0; i<config->cfg.stun_srv_cnt; ++i) {
+ pj_ansi_sprintf(line, "--stun-srv %.*s\n",
+ (int)config->cfg.stun_srv[i].slen,
+ config->cfg.stun_srv[i].ptr);
+ pj_strcat2(&cfg, line);
+ }
+
+#if defined(PJSIP_HAS_TLS_TRANSPORT) && (PJSIP_HAS_TLS_TRANSPORT != 0)
+ /* TLS */
+ if (config->use_tls)
+ pj_strcat2(&cfg, "--use-tls\n");
+ if (config->udp_cfg.tls_setting.ca_list_file.slen) {
+ pj_ansi_sprintf(line, "--tls-ca-file %.*s\n",
+ (int)config->udp_cfg.tls_setting.ca_list_file.slen,
+ config->udp_cfg.tls_setting.ca_list_file.ptr);
+ pj_strcat2(&cfg, line);
+ }
+ if (config->udp_cfg.tls_setting.cert_file.slen) {
+ pj_ansi_sprintf(line, "--tls-cert-file %.*s\n",
+ (int)config->udp_cfg.tls_setting.cert_file.slen,
+ config->udp_cfg.tls_setting.cert_file.ptr);
+ pj_strcat2(&cfg, line);
+ }
+ if (config->udp_cfg.tls_setting.privkey_file.slen) {
+ pj_ansi_sprintf(line, "--tls-privkey-file %.*s\n",
+ (int)config->udp_cfg.tls_setting.privkey_file.slen,
+ config->udp_cfg.tls_setting.privkey_file.ptr);
+ pj_strcat2(&cfg, line);
+ }
+
+ if (config->udp_cfg.tls_setting.password.slen) {
+ pj_ansi_sprintf(line, "--tls-password %.*s\n",
+ (int)config->udp_cfg.tls_setting.password.slen,
+ config->udp_cfg.tls_setting.password.ptr);
+ pj_strcat2(&cfg, line);
+ }
+
+ if (config->udp_cfg.tls_setting.verify_server)
+ pj_strcat2(&cfg, "--tls-verify-server\n");
+
+ if (config->udp_cfg.tls_setting.verify_client)
+ pj_strcat2(&cfg, "--tls-verify-client\n");
+
+ if (config->udp_cfg.tls_setting.timeout.sec) {
+ pj_ansi_sprintf(line, "--tls-neg-timeout %d\n",
+ (int)config->udp_cfg.tls_setting.timeout.sec);
+ pj_strcat2(&cfg, line);
+ }
+
+ for (i=0; i<config->udp_cfg.tls_setting.ciphers_num; ++i) {
+ pj_ansi_sprintf(line, "--tls-cipher 0x%06X # %s\n",
+ config->udp_cfg.tls_setting.ciphers[i],
+ pj_ssl_cipher_name(config->udp_cfg.tls_setting.ciphers[i]));
+ pj_strcat2(&cfg, line);
+ }
+#endif
+
+ pj_strcat2(&cfg, "\n#\n# Media settings:\n#\n");
+
+ /* Video & extra audio */
+ for (i=0; i<config->vid.vid_cnt; ++i) {
+ pj_strcat2(&cfg, "--video\n");
+ }
+ for (i=1; i<config->aud_cnt; ++i) {
+ pj_strcat2(&cfg, "--extra-audio\n");
+ }
+
+ /* SRTP */
+#if PJMEDIA_HAS_SRTP
+ if (app_config.cfg.use_srtp != PJSUA_DEFAULT_USE_SRTP) {
+ int use_srtp = (int)app_config.cfg.use_srtp;
+ if (use_srtp == PJMEDIA_SRTP_OPTIONAL &&
+ app_config.cfg.srtp_optional_dup_offer)
+ {
+ use_srtp = 3;
+ }
+ pj_ansi_sprintf(line, "--use-srtp %d\n", use_srtp);
+ pj_strcat2(&cfg, line);
+ }
+ if (app_config.cfg.srtp_secure_signaling !=
+ PJSUA_DEFAULT_SRTP_SECURE_SIGNALING)
+ {
+ pj_ansi_sprintf(line, "--srtp-secure %d\n",
+ app_config.cfg.srtp_secure_signaling);
+ pj_strcat2(&cfg, line);
+ }
+#endif
+
+ /* Media Transport*/
+ if (config->media_cfg.enable_ice)
+ pj_strcat2(&cfg, "--use-ice\n");
+
+ if (config->media_cfg.ice_opt.aggressive == PJ_FALSE)
+ pj_strcat2(&cfg, "--ice-regular\n");
+
+ if (config->media_cfg.enable_turn)
+ pj_strcat2(&cfg, "--use-turn\n");
+
+ if (config->media_cfg.ice_max_host_cands >= 0) {
+ pj_ansi_sprintf(line, "--ice_max_host_cands %d\n",
+ config->media_cfg.ice_max_host_cands);
+ pj_strcat2(&cfg, line);
+ }
+
+ if (config->media_cfg.ice_no_rtcp)
+ pj_strcat2(&cfg, "--ice-no-rtcp\n");
+
+ if (config->media_cfg.turn_server.slen) {
+ pj_ansi_sprintf(line, "--turn-srv %.*s\n",
+ (int)config->media_cfg.turn_server.slen,
+ config->media_cfg.turn_server.ptr);
+ pj_strcat2(&cfg, line);
+ }
+
+ if (config->media_cfg.turn_conn_type == PJ_TURN_TP_TCP)
+ pj_strcat2(&cfg, "--turn-tcp\n");
+
+ if (config->media_cfg.turn_auth_cred.data.static_cred.username.slen) {
+ pj_ansi_sprintf(line, "--turn-user %.*s\n",
+ (int)config->media_cfg.turn_auth_cred.data.static_cred.username.slen,
+ config->media_cfg.turn_auth_cred.data.static_cred.username.ptr);
+ pj_strcat2(&cfg, line);
+ }
+
+ if (config->media_cfg.turn_auth_cred.data.static_cred.data.slen) {
+ pj_ansi_sprintf(line, "--turn-passwd %.*s\n",
+ (int)config->media_cfg.turn_auth_cred.data.static_cred.data.slen,
+ config->media_cfg.turn_auth_cred.data.static_cred.data.ptr);
+ pj_strcat2(&cfg, line);
+ }
+
+ /* Media */
+ if (config->null_audio)
+ pj_strcat2(&cfg, "--null-audio\n");
+ if (config->auto_play)
+ pj_strcat2(&cfg, "--auto-play\n");
+ if (config->auto_loop)
+ pj_strcat2(&cfg, "--auto-loop\n");
+ if (config->auto_conf)
+ pj_strcat2(&cfg, "--auto-conf\n");
+ for (i=0; i<config->wav_count; ++i) {
+ pj_ansi_sprintf(line, "--play-file %s\n",
+ config->wav_files[i].ptr);
+ pj_strcat2(&cfg, line);
+ }
+ for (i=0; i<config->tone_count; ++i) {
+ pj_ansi_sprintf(line, "--play-tone %d,%d,%d,%d\n",
+ config->tones[i].freq1, config->tones[i].freq2,
+ config->tones[i].on_msec, config->tones[i].off_msec);
+ pj_strcat2(&cfg, line);
+ }
+ if (config->rec_file.slen) {
+ pj_ansi_sprintf(line, "--rec-file %s\n",
+ config->rec_file.ptr);
+ pj_strcat2(&cfg, line);
+ }
+ if (config->auto_rec)
+ pj_strcat2(&cfg, "--auto-rec\n");
+ if (config->capture_dev != PJSUA_INVALID_ID) {
+ pj_ansi_sprintf(line, "--capture-dev %d\n", config->capture_dev);
+ pj_strcat2(&cfg, line);
+ }
+ if (config->playback_dev != PJSUA_INVALID_ID) {
+ pj_ansi_sprintf(line, "--playback-dev %d\n", config->playback_dev);
+ pj_strcat2(&cfg, line);
+ }
+ if (config->media_cfg.snd_auto_close_time != -1) {
+ pj_ansi_sprintf(line, "--snd-auto-close %d\n",
+ config->media_cfg.snd_auto_close_time);
+ pj_strcat2(&cfg, line);
+ }
+ if (config->no_tones) {
+ pj_strcat2(&cfg, "--no-tones\n");
+ }
+ if (config->media_cfg.jb_max != -1) {
+ pj_ansi_sprintf(line, "--jb-max-size %d\n",
+ config->media_cfg.jb_max);
+ pj_strcat2(&cfg, line);
+ }
+
+ /* Sound device latency */
+ if (config->capture_lat != PJMEDIA_SND_DEFAULT_REC_LATENCY) {
+ pj_ansi_sprintf(line, "--capture-lat %d\n", config->capture_lat);
+ pj_strcat2(&cfg, line);
+ }
+ if (config->playback_lat != PJMEDIA_SND_DEFAULT_PLAY_LATENCY) {
+ pj_ansi_sprintf(line, "--playback-lat %d\n", config->playback_lat);
+ pj_strcat2(&cfg, line);
+ }
+
+ /* Media clock rate. */
+ if (config->media_cfg.clock_rate != PJSUA_DEFAULT_CLOCK_RATE) {
+ pj_ansi_sprintf(line, "--clock-rate %d\n",
+ config->media_cfg.clock_rate);
+ pj_strcat2(&cfg, line);
+ } else {
+ pj_ansi_sprintf(line, "#using default --clock-rate %d\n",
+ config->media_cfg.clock_rate);
+ pj_strcat2(&cfg, line);
+ }
+
+ if (config->media_cfg.snd_clock_rate &&
+ config->media_cfg.snd_clock_rate != config->media_cfg.clock_rate)
+ {
+ pj_ansi_sprintf(line, "--snd-clock-rate %d\n",
+ config->media_cfg.snd_clock_rate);
+ pj_strcat2(&cfg, line);
+ }
+
+ /* Stereo mode. */
+ if (config->media_cfg.channel_count == 2) {
+ pj_ansi_sprintf(line, "--stereo\n");
+ pj_strcat2(&cfg, line);
+ }
+
+ /* quality */
+ if (config->media_cfg.quality != PJSUA_DEFAULT_CODEC_QUALITY) {
+ pj_ansi_sprintf(line, "--quality %d\n",
+ config->media_cfg.quality);
+ pj_strcat2(&cfg, line);
+ } else {
+ pj_ansi_sprintf(line, "#using default --quality %d\n",
+ config->media_cfg.quality);
+ pj_strcat2(&cfg, line);
+ }
+
+ if (config->vid.vcapture_dev != PJMEDIA_VID_DEFAULT_CAPTURE_DEV) {
+ pj_ansi_sprintf(line, "--vcapture-dev %d\n", config->vid.vcapture_dev);
+ pj_strcat2(&cfg, line);
+ }
+ if (config->vid.vrender_dev != PJMEDIA_VID_DEFAULT_RENDER_DEV) {
+ pj_ansi_sprintf(line, "--vrender-dev %d\n", config->vid.vrender_dev);
+ pj_strcat2(&cfg, line);
+ }
+ for (i=0; i<config->avi_cnt; ++i) {
+ pj_ansi_sprintf(line, "--play-avi %s\n", config->avi[i].path.ptr);
+ pj_strcat2(&cfg, line);
+ }
+ if (config->avi_auto_play) {
+ pj_ansi_sprintf(line, "--auto-play-avi\n");
+ pj_strcat2(&cfg, line);
+ }
+
+ /* ptime */
+ if (config->media_cfg.ptime) {
+ pj_ansi_sprintf(line, "--ptime %d\n",
+ config->media_cfg.ptime);
+ pj_strcat2(&cfg, line);
+ }
+
+ /* no-vad */
+ if (config->media_cfg.no_vad) {
+ pj_strcat2(&cfg, "--no-vad\n");
+ }
+
+ /* ec-tail */
+ if (config->media_cfg.ec_tail_len != PJSUA_DEFAULT_EC_TAIL_LEN) {
+ pj_ansi_sprintf(line, "--ec-tail %d\n",
+ config->media_cfg.ec_tail_len);
+ pj_strcat2(&cfg, line);
+ } else {
+ pj_ansi_sprintf(line, "#using default --ec-tail %d\n",
+ config->media_cfg.ec_tail_len);
+ pj_strcat2(&cfg, line);
+ }
+
+ /* ec-opt */
+ if (config->media_cfg.ec_options != 0) {
+ pj_ansi_sprintf(line, "--ec-opt %d\n",
+ config->media_cfg.ec_options);
+ pj_strcat2(&cfg, line);
+ }
+
+ /* ilbc-mode */
+ if (config->media_cfg.ilbc_mode != PJSUA_DEFAULT_ILBC_MODE) {
+ pj_ansi_sprintf(line, "--ilbc-mode %d\n",
+ config->media_cfg.ilbc_mode);
+ pj_strcat2(&cfg, line);
+ } else {
+ pj_ansi_sprintf(line, "#using default --ilbc-mode %d\n",
+ config->media_cfg.ilbc_mode);
+ pj_strcat2(&cfg, line);
+ }
+
+ /* RTP drop */
+ if (config->media_cfg.tx_drop_pct) {
+ pj_ansi_sprintf(line, "--tx-drop-pct %d\n",
+ config->media_cfg.tx_drop_pct);
+ pj_strcat2(&cfg, line);
+
+ }
+ if (config->media_cfg.rx_drop_pct) {
+ pj_ansi_sprintf(line, "--rx-drop-pct %d\n",
+ config->media_cfg.rx_drop_pct);
+ pj_strcat2(&cfg, line);
+
+ }
+
+
+ /* Start RTP port. */
+ pj_ansi_sprintf(line, "--rtp-port %d\n",
+ config->rtp_cfg.port);
+ pj_strcat2(&cfg, line);
+
+ /* Disable codec */
+ for (i=0; i<config->codec_dis_cnt; ++i) {
+ pj_ansi_sprintf(line, "--dis-codec %s\n",
+ config->codec_dis[i].ptr);
+ pj_strcat2(&cfg, line);
+ }
+ /* Add codec. */
+ for (i=0; i<config->codec_cnt; ++i) {
+ pj_ansi_sprintf(line, "--add-codec %s\n",
+ config->codec_arg[i].ptr);
+ pj_strcat2(&cfg, line);
+ }
+
+ pj_strcat2(&cfg, "\n#\n# User agent:\n#\n");
+
+ /* Auto-answer. */
+ if (config->auto_answer != 0) {
+ pj_ansi_sprintf(line, "--auto-answer %d\n",
+ config->auto_answer);
+ pj_strcat2(&cfg, line);
+ }
+
+ /* accept-redirect */
+ if (config->redir_op != PJSIP_REDIRECT_ACCEPT) {
+ pj_ansi_sprintf(line, "--accept-redirect %d\n",
+ config->redir_op);
+ pj_strcat2(&cfg, line);
+ }
+
+ /* Max calls. */
+ pj_ansi_sprintf(line, "--max-calls %d\n",
+ config->cfg.max_calls);
+ pj_strcat2(&cfg, line);
+
+ /* Uas-duration. */
+ if (config->duration != NO_LIMIT) {
+ pj_ansi_sprintf(line, "--duration %d\n",
+ config->duration);
+ pj_strcat2(&cfg, line);
+ }
+
+ /* norefersub ? */
+ if (config->no_refersub) {
+ pj_strcat2(&cfg, "--norefersub\n");
+ }
+
+ if (pjsip_use_compact_form)
+ {
+ pj_strcat2(&cfg, "--use-compact-form\n");
+ }
+
+ if (!config->cfg.force_lr) {
+ pj_strcat2(&cfg, "--no-force-lr\n");
+ }
+
+ pj_strcat2(&cfg, "\n#\n# Buddies:\n#\n");
+
+ /* Add buddies. */
+ for (i=0; i<config->buddy_cnt; ++i) {
+ pj_ansi_sprintf(line, "--add-buddy %.*s\n",
+ (int)config->buddy_cfg[i].uri.slen,
+ config->buddy_cfg[i].uri.ptr);
+ pj_strcat2(&cfg, line);
+ }
+
+ /* SIP extensions. */
+ pj_strcat2(&cfg, "\n#\n# SIP extensions:\n#\n");
+ /* 100rel extension */
+ if (config->cfg.require_100rel) {
+ pj_strcat2(&cfg, "--use-100rel\n");
+ }
+ /* Session Timer extension */
+ if (config->cfg.use_timer) {
+ pj_ansi_sprintf(line, "--use-timer %d\n",
+ config->cfg.use_timer);
+ pj_strcat2(&cfg, line);
+ }
+ if (config->cfg.timer_setting.min_se != 90) {
+ pj_ansi_sprintf(line, "--timer-min-se %d\n",
+ config->cfg.timer_setting.min_se);
+ pj_strcat2(&cfg, line);
+ }
+ if (config->cfg.timer_setting.sess_expires != PJSIP_SESS_TIMER_DEF_SE) {
+ pj_ansi_sprintf(line, "--timer-se %d\n",
+ config->cfg.timer_setting.sess_expires);
+ pj_strcat2(&cfg, line);
+ }
+
+ *(cfg.ptr + cfg.slen) = '\0';
+ return cfg.slen;
+}
+
+
+/*
+ * Dump application states.
+ */
+static void app_dump(pj_bool_t detail)
+{
+ pjsua_dump(detail);
+}
+
+/*
+ * Print log of call states. Since call states may be too long for logger,
+ * printing it is a bit tricky, it should be printed part by part as long
+ * as the logger can accept.
+ */
+static void log_call_dump(int call_id)
+{
+ unsigned call_dump_len;
+ unsigned part_len;
+ unsigned part_idx;
+ unsigned log_decor;
+
+ pjsua_call_dump(call_id, PJ_TRUE, some_buf,
+ sizeof(some_buf), " ");
+ call_dump_len = strlen(some_buf);
+
+ log_decor = pj_log_get_decor();
+ pj_log_set_decor(log_decor & ~(PJ_LOG_HAS_NEWLINE | PJ_LOG_HAS_CR));
+ PJ_LOG(3,(THIS_FILE, "\n"));
+ pj_log_set_decor(0);
+
+ part_idx = 0;
+ part_len = PJ_LOG_MAX_SIZE-80;
+ while (part_idx < call_dump_len) {
+ char p_orig, *p;
+
+ p = &some_buf[part_idx];
+ if (part_idx + part_len > call_dump_len)
+ part_len = call_dump_len - part_idx;
+ p_orig = p[part_len];
+ p[part_len] = '\0';
+ PJ_LOG(3,(THIS_FILE, "%s", p));
+ p[part_len] = p_orig;
+ part_idx += part_len;
+ }
+ pj_log_set_decor(log_decor);
+}
+
+/*****************************************************************************
+ * Console application
+ */
+
+static void ringback_start(pjsua_call_id call_id)
+{
+ if (app_config.no_tones)
+ return;
+
+ if (app_config.call_data[call_id].ringback_on)
+ return;
+
+ app_config.call_data[call_id].ringback_on = PJ_TRUE;
+
+ if (++app_config.ringback_cnt==1 &&
+ app_config.ringback_slot!=PJSUA_INVALID_ID)
+ {
+ pjsua_conf_connect(app_config.ringback_slot, 0);
+ }
+}
+
+static void ring_stop(pjsua_call_id call_id)
+{
+ if (app_config.no_tones)
+ return;
+
+ if (app_config.call_data[call_id].ringback_on) {
+ app_config.call_data[call_id].ringback_on = PJ_FALSE;
+
+ pj_assert(app_config.ringback_cnt>0);
+ if (--app_config.ringback_cnt == 0 &&
+ app_config.ringback_slot!=PJSUA_INVALID_ID)
+ {
+ pjsua_conf_disconnect(app_config.ringback_slot, 0);
+ pjmedia_tonegen_rewind(app_config.ringback_port);
+ }
+ }
+
+ if (app_config.call_data[call_id].ring_on) {
+ app_config.call_data[call_id].ring_on = PJ_FALSE;
+
+ pj_assert(app_config.ring_cnt>0);
+ if (--app_config.ring_cnt == 0 &&
+ app_config.ring_slot!=PJSUA_INVALID_ID)
+ {
+ pjsua_conf_disconnect(app_config.ring_slot, 0);
+ pjmedia_tonegen_rewind(app_config.ring_port);
+ }
+ }
+}
+
+static void ring_start(pjsua_call_id call_id)
+{
+ if (app_config.no_tones)
+ return;
+
+ if (app_config.call_data[call_id].ring_on)
+ return;
+
+ app_config.call_data[call_id].ring_on = PJ_TRUE;
+
+ if (++app_config.ring_cnt==1 &&
+ app_config.ring_slot!=PJSUA_INVALID_ID)
+ {
+ pjsua_conf_connect(app_config.ring_slot, 0);
+ }
+}
+
+#ifdef HAVE_MULTIPART_TEST
+ /*
+ * Enable multipart in msg_data and add a dummy body into the
+ * multipart bodies.
+ */
+ static void add_multipart(pjsua_msg_data *msg_data)
+ {
+ static pjsip_multipart_part *alt_part;
+
+ if (!alt_part) {
+ pj_str_t type, subtype, content;
+
+ alt_part = pjsip_multipart_create_part(app_config.pool);
+
+ type = pj_str("text");
+ subtype = pj_str("plain");
+ content = pj_str("Sample text body of a multipart bodies");
+ alt_part->body = pjsip_msg_body_create(app_config.pool, &type,
+ &subtype, &content);
+ }
+
+ msg_data->multipart_ctype.type = pj_str("multipart");
+ msg_data->multipart_ctype.subtype = pj_str("mixed");
+ pj_list_push_back(&msg_data->multipart_parts, alt_part);
+ }
+# define TEST_MULTIPART(msg_data) add_multipart(msg_data)
+#else
+# define TEST_MULTIPART(msg_data)
+#endif
+
+/*
+ * Find next call when current call is disconnected or when user
+ * press ']'
+ */
+static pj_bool_t find_next_call(void)
+{
+ int i, max;
+
+ max = pjsua_call_get_max_count();
+ for (i=current_call+1; i<max; ++i) {
+ if (pjsua_call_is_active(i)) {
+ current_call = i;
+ return PJ_TRUE;
+ }
+ }
+
+ for (i=0; i<current_call; ++i) {
+ if (pjsua_call_is_active(i)) {
+ current_call = i;
+ return PJ_TRUE;
+ }
+ }
+
+ current_call = PJSUA_INVALID_ID;
+ return PJ_FALSE;
+}
+
+
+/*
+ * Find previous call when user press '['
+ */
+static pj_bool_t find_prev_call(void)
+{
+ int i, max;
+
+ max = pjsua_call_get_max_count();
+ for (i=current_call-1; i>=0; --i) {
+ if (pjsua_call_is_active(i)) {
+ current_call = i;
+ return PJ_TRUE;
+ }
+ }
+
+ for (i=max-1; i>current_call; --i) {
+ if (pjsua_call_is_active(i)) {
+ current_call = i;
+ return PJ_TRUE;
+ }
+ }
+
+ current_call = PJSUA_INVALID_ID;
+ return PJ_FALSE;
+}
+
+
+/* Callback from timer when the maximum call duration has been
+ * exceeded.
+ */
+static void call_timeout_callback(pj_timer_heap_t *timer_heap,
+ struct pj_timer_entry *entry)
+{
+ pjsua_call_id call_id = entry->id;
+ pjsua_msg_data msg_data;
+ pjsip_generic_string_hdr warn;
+ pj_str_t hname = pj_str("Warning");
+ pj_str_t hvalue = pj_str("399 pjsua \"Call duration exceeded\"");
+
+ PJ_UNUSED_ARG(timer_heap);
+
+ if (call_id == PJSUA_INVALID_ID) {
+ PJ_LOG(1,(THIS_FILE, "Invalid call ID in timer callback"));
+ return;
+ }
+
+ /* Add warning header */
+ pjsua_msg_data_init(&msg_data);
+ pjsip_generic_string_hdr_init2(&warn, &hname, &hvalue);
+ pj_list_push_back(&msg_data.hdr_list, &warn);
+
+ /* Call duration has been exceeded; disconnect the call */
+ PJ_LOG(3,(THIS_FILE, "Duration (%d seconds) has been exceeded "
+ "for call %d, disconnecting the call",
+ app_config.duration, call_id));
+ entry->id = PJSUA_INVALID_ID;
+ pjsua_call_hangup(call_id, 200, NULL, &msg_data);
+}
+
+
+/*
+ * Handler when invite state has changed.
+ */
+static void on_call_state(pjsua_call_id call_id, pjsip_event *e)
+{
+ pjsua_call_info call_info;
+
+ PJ_UNUSED_ARG(e);
+
+ pjsua_call_get_info(call_id, &call_info);
+
+ if (call_info.state == PJSIP_INV_STATE_DISCONNECTED) {
+
+ /* Stop all ringback for this call */
+ ring_stop(call_id);
+
+ /* Cancel duration timer, if any */
+ if (app_config.call_data[call_id].timer.id != PJSUA_INVALID_ID) {
+ struct call_data *cd = &app_config.call_data[call_id];
+ pjsip_endpoint *endpt = pjsua_get_pjsip_endpt();
+
+ cd->timer.id = PJSUA_INVALID_ID;
+ pjsip_endpt_cancel_timer(endpt, &cd->timer);
+ }
+
+ /* Rewind play file when hangup automatically,
+ * since file is not looped
+ */
+ if (app_config.auto_play_hangup)
+ pjsua_player_set_pos(app_config.wav_id, 0);
+
+
+ PJ_LOG(3,(THIS_FILE, "Call %d is DISCONNECTED [reason=%d (%s)]",
+ call_id,
+ call_info.last_status,
+ call_info.last_status_text.ptr));
+
+ if (call_id == current_call) {
+ find_next_call();
+ }
+
+ /* Dump media state upon disconnected */
+ if (1) {
+ PJ_LOG(5,(THIS_FILE,
+ "Call %d disconnected, dumping media stats..",
+ call_id));
+ log_call_dump(call_id);
+ }
+
+ } else {
+
+ if (app_config.duration!=NO_LIMIT &&
+ call_info.state == PJSIP_INV_STATE_CONFIRMED)
+ {
+ /* Schedule timer to hangup call after the specified duration */
+ struct call_data *cd = &app_config.call_data[call_id];
+ pjsip_endpoint *endpt = pjsua_get_pjsip_endpt();
+ pj_time_val delay;
+
+ cd->timer.id = call_id;
+ delay.sec = app_config.duration;
+ delay.msec = 0;
+ pjsip_endpt_schedule_timer(endpt, &cd->timer, &delay);
+ }
+
+ if (call_info.state == PJSIP_INV_STATE_EARLY) {
+ int code;
+ pj_str_t reason;
+ pjsip_msg *msg;
+
+ /* This can only occur because of TX or RX message */
+ pj_assert(e->type == PJSIP_EVENT_TSX_STATE);
+
+ if (e->body.tsx_state.type == PJSIP_EVENT_RX_MSG) {
+ msg = e->body.tsx_state.src.rdata->msg_info.msg;
+ } else {
+ msg = e->body.tsx_state.src.tdata->msg;
+ }
+
+ code = msg->line.status.code;
+ reason = msg->line.status.reason;
+
+ /* Start ringback for 180 for UAC unless there's SDP in 180 */
+ if (call_info.role==PJSIP_ROLE_UAC && code==180 &&
+ msg->body == NULL &&
+ call_info.media_status==PJSUA_CALL_MEDIA_NONE)
+ {
+ ringback_start(call_id);
+ }
+
+ PJ_LOG(3,(THIS_FILE, "Call %d state changed to %s (%d %.*s)",
+ call_id, call_info.state_text.ptr,
+ code, (int)reason.slen, reason.ptr));
+ } else {
+ PJ_LOG(3,(THIS_FILE, "Call %d state changed to %s",
+ call_id,
+ call_info.state_text.ptr));
+ }
+
+ if (current_call==PJSUA_INVALID_ID)
+ current_call = call_id;
+
+ }
+}
+
+
+/**
+ * Handler when there is incoming call.
+ */
+static void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id,
+ pjsip_rx_data *rdata)
+{
+ pjsua_call_info call_info;
+
+ PJ_UNUSED_ARG(acc_id);
+ PJ_UNUSED_ARG(rdata);
+
+ pjsua_call_get_info(call_id, &call_info);
+
+ if (current_call==PJSUA_INVALID_ID)
+ current_call = call_id;
+
+#ifdef USE_GUI
+ if (!showNotification(call_id))
+ return;
+#endif
+
+ /* Start ringback */
+ ring_start(call_id);
+
+ if (app_config.auto_answer > 0) {
+ pjsua_call_setting call_opt;
+
+ pjsua_call_setting_default(&call_opt);
+ call_opt.aud_cnt = app_config.aud_cnt;
+ call_opt.vid_cnt = app_config.vid.vid_cnt;
+
+ pjsua_call_answer2(call_id, &call_opt, app_config.auto_answer, NULL, NULL);
+ }
+
+ if (app_config.auto_answer < 200) {
+ char notif_st[80] = {0};
+
+#if PJSUA_HAS_VIDEO
+ if (call_info.rem_offerer && call_info.rem_vid_cnt) {
+ snprintf(notif_st, sizeof(notif_st),
+ "To %s the video, type \"vid %s\" first, "
+ "before answering the call!\n",
+ (app_config.vid.vid_cnt? "reject":"accept"),
+ (app_config.vid.vid_cnt? "disable":"enable"));
+ }
+#endif
+
+ PJ_LOG(3,(THIS_FILE,
+ "Incoming call for account %d!\n"
+ "Media count: %d audio & %d video\n"
+ "%s"
+ "From: %s\n"
+ "To: %s\n"
+ "Press a to answer or h to reject call",
+ acc_id,
+ call_info.rem_aud_cnt,
+ call_info.rem_vid_cnt,
+ notif_st,
+ call_info.remote_info.ptr,
+ call_info.local_info.ptr));
+ }
+}
+
+
+/*
+ * Handler when a transaction within a call has changed state.
+ */
+static void on_call_tsx_state(pjsua_call_id call_id,
+ pjsip_transaction *tsx,
+ pjsip_event *e)
+{
+ const pjsip_method info_method =
+ {
+ PJSIP_OTHER_METHOD,
+ { "INFO", 4 }
+ };
+
+ if (pjsip_method_cmp(&tsx->method, &info_method)==0) {
+ /*
+ * Handle INFO method.
+ */
+ const pj_str_t STR_APPLICATION = { "application", 11};
+ const pj_str_t STR_DTMF_RELAY = { "dtmf-relay", 10 };
+ pjsip_msg_body *body = NULL;
+ pj_bool_t dtmf_info = PJ_FALSE;
+
+ if (tsx->role == PJSIP_ROLE_UAC) {
+ if (e->body.tsx_state.type == PJSIP_EVENT_TX_MSG)
+ body = e->body.tsx_state.src.tdata->msg->body;
+ else
+ body = e->body.tsx_state.tsx->last_tx->msg->body;
+ } else {
+ if (e->body.tsx_state.type == PJSIP_EVENT_RX_MSG)
+ body = e->body.tsx_state.src.rdata->msg_info.msg->body;
+ }
+
+ /* Check DTMF content in the INFO message */
+ if (body && body->len &&
+ pj_stricmp(&body->content_type.type, &STR_APPLICATION)==0 &&
+ pj_stricmp(&body->content_type.subtype, &STR_DTMF_RELAY)==0)
+ {
+ dtmf_info = PJ_TRUE;
+ }
+
+ if (dtmf_info && tsx->role == PJSIP_ROLE_UAC &&
+ (tsx->state == PJSIP_TSX_STATE_COMPLETED ||
+ (tsx->state == PJSIP_TSX_STATE_TERMINATED &&
+ e->body.tsx_state.prev_state != PJSIP_TSX_STATE_COMPLETED)))
+ {
+ /* Status of outgoing INFO request */
+ if (tsx->status_code >= 200 && tsx->status_code < 300) {
+ PJ_LOG(4,(THIS_FILE,
+ "Call %d: DTMF sent successfully with INFO",
+ call_id));
+ } else if (tsx->status_code >= 300) {
+ PJ_LOG(4,(THIS_FILE,
+ "Call %d: Failed to send DTMF with INFO: %d/%.*s",
+ call_id,
+ tsx->status_code,
+ (int)tsx->status_text.slen,
+ tsx->status_text.ptr));
+ }
+ } else if (dtmf_info && tsx->role == PJSIP_ROLE_UAS &&
+ tsx->state == PJSIP_TSX_STATE_TRYING)
+ {
+ /* Answer incoming INFO with 200/OK */
+ pjsip_rx_data *rdata;
+ pjsip_tx_data *tdata;
+ pj_status_t status;
+
+ rdata = e->body.tsx_state.src.rdata;
+
+ if (rdata->msg_info.msg->body) {
+ status = pjsip_endpt_create_response(tsx->endpt, rdata,
+ 200, NULL, &tdata);
+ if (status == PJ_SUCCESS)
+ status = pjsip_tsx_send_msg(tsx, tdata);
+
+ PJ_LOG(3,(THIS_FILE, "Call %d: incoming INFO:\n%.*s",
+ call_id,
+ (int)rdata->msg_info.msg->body->len,
+ rdata->msg_info.msg->body->data));
+ } else {
+ status = pjsip_endpt_create_response(tsx->endpt, rdata,
+ 400, NULL, &tdata);
+ if (status == PJ_SUCCESS)
+ status = pjsip_tsx_send_msg(tsx, tdata);
+ }
+ }
+ }
+}
+
+/* General processing for media state. "mi" is the media index */
+static void on_call_generic_media_state(pjsua_call_info *ci, unsigned mi,
+ pj_bool_t *has_error)
+{
+ const char *status_name[] = {
+ "None",
+ "Active",
+ "Local hold",
+ "Remote hold",
+ "Error"
+ };
+
+ PJ_UNUSED_ARG(has_error);
+
+ pj_assert(ci->media[mi].status <= PJ_ARRAY_SIZE(status_name));
+ pj_assert(PJSUA_CALL_MEDIA_ERROR == 4);
+
+ PJ_LOG(4,(THIS_FILE, "Call %d media %d [type=%s], status is %s",
+ ci->id, mi, pjmedia_type_name(ci->media[mi].type),
+ status_name[ci->media[mi].status]));
+}
+
+/* Process audio media state. "mi" is the media index. */
+static void on_call_audio_state(pjsua_call_info *ci, unsigned mi,
+ pj_bool_t *has_error)
+{
+ PJ_UNUSED_ARG(has_error);
+
+ /* Stop ringback */
+ ring_stop(ci->id);
+
+ /* Connect ports appropriately when media status is ACTIVE or REMOTE HOLD,
+ * otherwise we should NOT connect the ports.
+ */
+ if (ci->media[mi].status == PJSUA_CALL_MEDIA_ACTIVE ||
+ ci->media[mi].status == PJSUA_CALL_MEDIA_REMOTE_HOLD)
+ {
+ pj_bool_t connect_sound = PJ_TRUE;
+ pj_bool_t disconnect_mic = PJ_FALSE;
+ pjsua_conf_port_id call_conf_slot;
+
+ call_conf_slot = ci->media[mi].stream.aud.conf_slot;
+
+ /* Loopback sound, if desired */
+ if (app_config.auto_loop) {
+ pjsua_conf_connect(call_conf_slot, call_conf_slot);
+ connect_sound = PJ_FALSE;
+ }
+
+ /* Automatically record conversation, if desired */
+ if (app_config.auto_rec && app_config.rec_port != PJSUA_INVALID_ID) {
+ pjsua_conf_connect(call_conf_slot, app_config.rec_port);
+ }
+
+ /* Stream a file, if desired */
+ if ((app_config.auto_play || app_config.auto_play_hangup) &&
+ app_config.wav_port != PJSUA_INVALID_ID)
+ {
+ pjsua_conf_connect(app_config.wav_port, call_conf_slot);
+ connect_sound = PJ_FALSE;
+ }
+
+ /* Stream AVI, if desired */
+ if (app_config.avi_auto_play &&
+ app_config.avi_def_idx != PJSUA_INVALID_ID &&
+ app_config.avi[app_config.avi_def_idx].slot != PJSUA_INVALID_ID)
+ {
+ pjsua_conf_connect(app_config.avi[app_config.avi_def_idx].slot,
+ call_conf_slot);
+ disconnect_mic = PJ_TRUE;
+ }
+
+ /* Put call in conference with other calls, if desired */
+ if (app_config.auto_conf) {
+ pjsua_call_id call_ids[PJSUA_MAX_CALLS];
+ unsigned call_cnt=PJ_ARRAY_SIZE(call_ids);
+ unsigned i;
+
+ /* Get all calls, and establish media connection between
+ * this call and other calls.
+ */
+ pjsua_enum_calls(call_ids, &call_cnt);
+
+ for (i=0; i<call_cnt; ++i) {
+ if (call_ids[i] == ci->id)
+ continue;
+
+ if (!pjsua_call_has_media(call_ids[i]))
+ continue;
+
+ pjsua_conf_connect(call_conf_slot,
+ pjsua_call_get_conf_port(call_ids[i]));
+ pjsua_conf_connect(pjsua_call_get_conf_port(call_ids[i]),
+ call_conf_slot);
+
+ /* Automatically record conversation, if desired */
+ if (app_config.auto_rec && app_config.rec_port != PJSUA_INVALID_ID) {
+ pjsua_conf_connect(pjsua_call_get_conf_port(call_ids[i]),
+ app_config.rec_port);
+ }
+
+ }
+
+ /* Also connect call to local sound device */
+ connect_sound = PJ_TRUE;
+ }
+
+ /* Otherwise connect to sound device */
+ if (connect_sound) {
+ pjsua_conf_connect(call_conf_slot, 0);
+ if (!disconnect_mic)
+ pjsua_conf_connect(0, call_conf_slot);
+
+ /* Automatically record conversation, if desired */
+ if (app_config.auto_rec && app_config.rec_port != PJSUA_INVALID_ID) {
+ pjsua_conf_connect(call_conf_slot, app_config.rec_port);
+ pjsua_conf_connect(0, app_config.rec_port);
+ }
+ }
+ }
+}
+
+/* arrange windows. arg:
+ * -1: arrange all windows
+ * != -1: arrange only this window id
+ */
+static void arrange_window(pjsua_vid_win_id wid)
+{
+#if PJSUA_HAS_VIDEO
+ pjmedia_coord pos;
+ int i, last;
+
+ pos.x = 0;
+ pos.y = 10;
+ last = (wid == PJSUA_INVALID_ID) ? PJSUA_MAX_VID_WINS : wid;
+
+ for (i=0; i<last; ++i) {
+ pjsua_vid_win_info wi;
+ pj_status_t status;
+
+ status = pjsua_vid_win_get_info(i, &wi);
+ if (status != PJ_SUCCESS)
+ continue;
+
+ if (wid == PJSUA_INVALID_ID)
+ pjsua_vid_win_set_pos(i, &pos);
+
+ if (wi.show)
+ pos.y += wi.size.h;
+ }
+
+ if (wid != PJSUA_INVALID_ID)
+ pjsua_vid_win_set_pos(wid, &pos);
+#else
+ PJ_UNUSED_ARG(wid);
+#endif
+}
+
+/* Process video media state. "mi" is the media index. */
+static void on_call_video_state(pjsua_call_info *ci, unsigned mi,
+ pj_bool_t *has_error)
+{
+ if (ci->media_status != PJSUA_CALL_MEDIA_ACTIVE)
+ return;
+
+ arrange_window(ci->media[mi].stream.vid.win_in);
+
+ PJ_UNUSED_ARG(has_error);
+}
+
+/*
+ * Callback on media state changed event.
+ * The action may connect the call to sound device, to file, or
+ * to loop the call.
+ */
+static void on_call_media_state(pjsua_call_id call_id)
+{
+ pjsua_call_info call_info;
+ unsigned mi;
+ pj_bool_t has_error = PJ_FALSE;
+
+ pjsua_call_get_info(call_id, &call_info);
+
+ for (mi=0; mi<call_info.media_cnt; ++mi) {
+ on_call_generic_media_state(&call_info, mi, &has_error);
+
+ switch (call_info.media[mi].type) {
+ case PJMEDIA_TYPE_AUDIO:
+ on_call_audio_state(&call_info, mi, &has_error);
+ break;
+ case PJMEDIA_TYPE_VIDEO:
+ on_call_video_state(&call_info, mi, &has_error);
+ break;
+ default:
+ /* Make gcc happy about enum not handled by switch/case */
+ break;
+ }
+ }
+
+ if (has_error) {
+ pj_str_t reason = pj_str("Media failed");
+ pjsua_call_hangup(call_id, 500, &reason, NULL);
+ }
+
+#if PJSUA_HAS_VIDEO
+ /* Check if remote has just tried to enable video */
+ if (call_info.rem_offerer && call_info.rem_vid_cnt)
+ {
+ int vid_idx;
+
+ /* Check if there is active video */
+ vid_idx = pjsua_call_get_vid_stream_idx(call_id);
+ if (vid_idx == -1 || call_info.media[vid_idx].dir == PJMEDIA_DIR_NONE) {
+ PJ_LOG(3,(THIS_FILE,
+ "Just rejected incoming video offer on call %d, "
+ "use \"vid call enable %d\" or \"vid call add\" to enable video!",
+ call_id, vid_idx));
+ }
+ }
+#endif
+}
+
+/*
+ * DTMF callback.
+ */
+static void call_on_dtmf_callback(pjsua_call_id call_id, int dtmf)
+{
+ PJ_LOG(3,(THIS_FILE, "Incoming DTMF on call %d: %c", call_id, dtmf));
+}
+
+/*
+ * Redirection handler.
+ */
+static pjsip_redirect_op call_on_redirected(pjsua_call_id call_id,
+ const pjsip_uri *target,
+ const pjsip_event *e)
+{
+ PJ_UNUSED_ARG(e);
+
+ if (app_config.redir_op == PJSIP_REDIRECT_PENDING) {
+ char uristr[PJSIP_MAX_URL_SIZE];
+ int len;
+
+ len = pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, target, uristr,
+ sizeof(uristr));
+ if (len < 1) {
+ pj_ansi_strcpy(uristr, "--URI too long--");
+ }
+
+ PJ_LOG(3,(THIS_FILE, "Call %d is being redirected to %.*s. "
+ "Press 'Ra' to accept, 'Rr' to reject, or 'Rd' to "
+ "disconnect.",
+ call_id, len, uristr));
+ }
+
+ return app_config.redir_op;
+}
+
+/*
+ * Handler registration status has changed.
+ */
+static void on_reg_state(pjsua_acc_id acc_id)
+{
+ PJ_UNUSED_ARG(acc_id);
+
+ // Log already written.
+}
+
+
+/*
+ * Handler for incoming presence subscription request
+ */
+static void on_incoming_subscribe(pjsua_acc_id acc_id,
+ pjsua_srv_pres *srv_pres,
+ pjsua_buddy_id buddy_id,
+ const pj_str_t *from,
+ pjsip_rx_data *rdata,
+ pjsip_status_code *code,
+ pj_str_t *reason,
+ pjsua_msg_data *msg_data)
+{
+ /* Just accept the request (the default behavior) */
+ PJ_UNUSED_ARG(acc_id);
+ PJ_UNUSED_ARG(srv_pres);
+ PJ_UNUSED_ARG(buddy_id);
+ PJ_UNUSED_ARG(from);
+ PJ_UNUSED_ARG(rdata);
+ PJ_UNUSED_ARG(code);
+ PJ_UNUSED_ARG(reason);
+ PJ_UNUSED_ARG(msg_data);
+}
+
+
+/*
+ * Handler on buddy state changed.
+ */
+static void on_buddy_state(pjsua_buddy_id buddy_id)
+{
+ pjsua_buddy_info info;
+ pjsua_buddy_get_info(buddy_id, &info);
+
+ PJ_LOG(3,(THIS_FILE, "%.*s status is %.*s, subscription state is %s "
+ "(last termination reason code=%d %.*s)",
+ (int)info.uri.slen,
+ info.uri.ptr,
+ (int)info.status_text.slen,
+ info.status_text.ptr,
+ info.sub_state_name,
+ info.sub_term_code,
+ (int)info.sub_term_reason.slen,
+ info.sub_term_reason.ptr));
+}
+
+
+/*
+ * Subscription state has changed.
+ */
+static void on_buddy_evsub_state(pjsua_buddy_id buddy_id,
+ pjsip_evsub *sub,
+ pjsip_event *event)
+{
+ char event_info[80];
+
+ PJ_UNUSED_ARG(sub);
+
+ event_info[0] = '\0';
+
+ if (event->type == PJSIP_EVENT_TSX_STATE &&
+ event->body.tsx_state.type == PJSIP_EVENT_RX_MSG)
+ {
+ pjsip_rx_data *rdata = event->body.tsx_state.src.rdata;
+ snprintf(event_info, sizeof(event_info),
+ " (RX %s)",
+ pjsip_rx_data_get_info(rdata));
+ }
+
+ PJ_LOG(4,(THIS_FILE,
+ "Buddy %d: subscription state: %s (event: %s%s)",
+ buddy_id, pjsip_evsub_get_state_name(sub),
+ pjsip_event_str(event->type),
+ event_info));
+
+}
+
+
+/**
+ * Incoming IM message (i.e. MESSAGE request)!
+ */
+static void on_pager(pjsua_call_id call_id, const pj_str_t *from,
+ const pj_str_t *to, const pj_str_t *contact,
+ const pj_str_t *mime_type, const pj_str_t *text)
+{
+ /* Note: call index may be -1 */
+ PJ_UNUSED_ARG(call_id);
+ PJ_UNUSED_ARG(to);
+ PJ_UNUSED_ARG(contact);
+ PJ_UNUSED_ARG(mime_type);
+
+ PJ_LOG(3,(THIS_FILE,"MESSAGE from %.*s: %.*s (%.*s)",
+ (int)from->slen, from->ptr,
+ (int)text->slen, text->ptr,
+ (int)mime_type->slen, mime_type->ptr));
+}
+
+
+/**
+ * Received typing indication
+ */
+static void on_typing(pjsua_call_id call_id, const pj_str_t *from,
+ const pj_str_t *to, const pj_str_t *contact,
+ pj_bool_t is_typing)
+{
+ PJ_UNUSED_ARG(call_id);
+ PJ_UNUSED_ARG(to);
+ PJ_UNUSED_ARG(contact);
+
+ PJ_LOG(3,(THIS_FILE, "IM indication: %.*s %s",
+ (int)from->slen, from->ptr,
+ (is_typing?"is typing..":"has stopped typing")));
+}
+
+
+/**
+ * Call transfer request status.
+ */
+static void on_call_transfer_status(pjsua_call_id call_id,
+ int status_code,
+ const pj_str_t *status_text,
+ pj_bool_t final,
+ pj_bool_t *p_cont)
+{
+ PJ_LOG(3,(THIS_FILE, "Call %d: transfer status=%d (%.*s) %s",
+ call_id, status_code,
+ (int)status_text->slen, status_text->ptr,
+ (final ? "[final]" : "")));
+
+ if (status_code/100 == 2) {
+ PJ_LOG(3,(THIS_FILE,
+ "Call %d: call transfered successfully, disconnecting call",
+ call_id));
+ pjsua_call_hangup(call_id, PJSIP_SC_GONE, NULL, NULL);
+ *p_cont = PJ_FALSE;
+ }
+}
+
+
+/*
+ * Notification that call is being replaced.
+ */
+static void on_call_replaced(pjsua_call_id old_call_id,
+ pjsua_call_id new_call_id)
+{
+ pjsua_call_info old_ci, new_ci;
+
+ pjsua_call_get_info(old_call_id, &old_ci);
+ pjsua_call_get_info(new_call_id, &new_ci);
+
+ PJ_LOG(3,(THIS_FILE, "Call %d with %.*s is being replaced by "
+ "call %d with %.*s",
+ old_call_id,
+ (int)old_ci.remote_info.slen, old_ci.remote_info.ptr,
+ new_call_id,
+ (int)new_ci.remote_info.slen, new_ci.remote_info.ptr));
+}
+
+
+/*
+ * NAT type detection callback.
+ */
+static void on_nat_detect(const pj_stun_nat_detect_result *res)
+{
+ if (res->status != PJ_SUCCESS) {
+ pjsua_perror(THIS_FILE, "NAT detection failed", res->status);
+ } else {
+ PJ_LOG(3, (THIS_FILE, "NAT detected as %s", res->nat_type_name));
+ }
+}
+
+
+/*
+ * MWI indication
+ */
+static void on_mwi_info(pjsua_acc_id acc_id, pjsua_mwi_info *mwi_info)
+{
+ pj_str_t body;
+
+ PJ_LOG(3,(THIS_FILE, "Received MWI for acc %d:", acc_id));
+
+ if (mwi_info->rdata->msg_info.ctype) {
+ const pjsip_ctype_hdr *ctype = mwi_info->rdata->msg_info.ctype;
+
+ PJ_LOG(3,(THIS_FILE, " Content-Type: %.*s/%.*s",
+ (int)ctype->media.type.slen,
+ ctype->media.type.ptr,
+ (int)ctype->media.subtype.slen,
+ ctype->media.subtype.ptr));
+ }
+
+ if (!mwi_info->rdata->msg_info.msg->body) {
+ PJ_LOG(3,(THIS_FILE, " no message body"));
+ return;
+ }
+
+ body.ptr = mwi_info->rdata->msg_info.msg->body->data;
+ body.slen = mwi_info->rdata->msg_info.msg->body->len;
+
+ PJ_LOG(3,(THIS_FILE, " Body:\n%.*s", (int)body.slen, body.ptr));
+}
+
+
+/*
+ * Transport status notification
+ */
+static void on_transport_state(pjsip_transport *tp,
+ pjsip_transport_state state,
+ const pjsip_transport_state_info *info)
+{
+ char host_port[128];
+
+ pj_ansi_snprintf(host_port, sizeof(host_port), "[%.*s:%d]",
+ (int)tp->remote_name.host.slen,
+ tp->remote_name.host.ptr,
+ tp->remote_name.port);
+
+ switch (state) {
+ case PJSIP_TP_STATE_CONNECTED:
+ {
+ PJ_LOG(3,(THIS_FILE, "SIP %s transport is connected to %s",
+ tp->type_name, host_port));
+ }
+ break;
+
+ case PJSIP_TP_STATE_DISCONNECTED:
+ {
+ char buf[100];
+
+ snprintf(buf, sizeof(buf), "SIP %s transport is disconnected from %s",
+ tp->type_name, host_port);
+ pjsua_perror(THIS_FILE, buf, info->status);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+#if defined(PJSIP_HAS_TLS_TRANSPORT) && PJSIP_HAS_TLS_TRANSPORT!=0
+
+ if (!pj_ansi_stricmp(tp->type_name, "tls") && info->ext_info &&
+ (state == PJSIP_TP_STATE_CONNECTED ||
+ ((pjsip_tls_state_info*)info->ext_info)->
+ ssl_sock_info->verify_status != PJ_SUCCESS))
+ {
+ pjsip_tls_state_info *tls_info = (pjsip_tls_state_info*)info->ext_info;
+ pj_ssl_sock_info *ssl_sock_info = tls_info->ssl_sock_info;
+ char buf[2048];
+ const char *verif_msgs[32];
+ unsigned verif_msg_cnt;
+
+ /* Dump server TLS cipher */
+ PJ_LOG(4,(THIS_FILE, "TLS cipher used: 0x%06X/%s",
+ ssl_sock_info->cipher,
+ pj_ssl_cipher_name(ssl_sock_info->cipher) ));
+
+ /* Dump server TLS certificate */
+ pj_ssl_cert_info_dump(ssl_sock_info->remote_cert_info, " ",
+ buf, sizeof(buf));
+ PJ_LOG(4,(THIS_FILE, "TLS cert info of %s:\n%s", host_port, buf));
+
+ /* Dump server TLS certificate verification result */
+ verif_msg_cnt = PJ_ARRAY_SIZE(verif_msgs);
+ pj_ssl_cert_get_verify_status_strings(ssl_sock_info->verify_status,
+ verif_msgs, &verif_msg_cnt);
+ PJ_LOG(3,(THIS_FILE, "TLS cert verification result of %s : %s",
+ host_port,
+ (verif_msg_cnt == 1? verif_msgs[0]:"")));
+ if (verif_msg_cnt > 1) {
+ unsigned i;
+ for (i = 0; i < verif_msg_cnt; ++i)
+ PJ_LOG(3,(THIS_FILE, "- %s", verif_msgs[i]));
+ }
+
+ if (ssl_sock_info->verify_status &&
+ !app_config.udp_cfg.tls_setting.verify_server)
+ {
+ PJ_LOG(3,(THIS_FILE, "PJSUA is configured to ignore TLS cert "
+ "verification errors"));
+ }
+ }
+
+#endif
+
+}
+
+/*
+ * Notification on ICE error.
+ */
+static void on_ice_transport_error(int index, pj_ice_strans_op op,
+ pj_status_t status, void *param)
+{
+ PJ_UNUSED_ARG(op);
+ PJ_UNUSED_ARG(param);
+ PJ_PERROR(1,(THIS_FILE, status,
+ "ICE keep alive failure for transport %d", index));
+}
+
+/*
+ * Notification on sound device operation.
+ */
+static pj_status_t on_snd_dev_operation(int operation)
+{
+ PJ_LOG(3,(THIS_FILE, "Turning sound device %s", (operation? "ON":"OFF")));
+ return PJ_SUCCESS;
+}
+
+/* Callback on media events */
+static void on_call_media_event(pjsua_call_id call_id,
+ unsigned med_idx,
+ pjmedia_event *event)
+{
+ char event_name[5];
+
+ PJ_LOG(5,(THIS_FILE, "Event %s",
+ pjmedia_fourcc_name(event->type, event_name)));
+
+#if PJSUA_HAS_VIDEO
+ if (event->type == PJMEDIA_EVENT_FMT_CHANGED) {
+ /* Adjust renderer window size to original video size */
+ pjsua_call_info ci;
+ pjsua_vid_win_id wid;
+ pjmedia_rect_size size;
+
+ pjsua_call_get_info(call_id, &ci);
+
+ if ((ci.media[med_idx].type == PJMEDIA_TYPE_VIDEO) &&
+ (ci.media[med_idx].dir & PJMEDIA_DIR_DECODING))
+ {
+ wid = ci.media[med_idx].stream.vid.win_in;
+ size = event->data.fmt_changed.new_fmt.det.vid.size;
+ pjsua_vid_win_set_size(wid, &size);
+ }
+
+ /* Re-arrange video windows */
+ arrange_window(PJSUA_INVALID_ID);
+ }
+#else
+ PJ_UNUSED_ARG(call_id);
+ PJ_UNUSED_ARG(med_idx);
+ PJ_UNUSED_ARG(event);
+#endif
+}
+
+#ifdef TRANSPORT_ADAPTER_SAMPLE
+/*
+ * This callback is called when media transport needs to be created.
+ */
+static pjmedia_transport* on_create_media_transport(pjsua_call_id call_id,
+ unsigned media_idx,
+ pjmedia_transport *base_tp,
+ unsigned flags)
+{
+ pjmedia_transport *adapter;
+ pj_status_t status;
+
+ /* Create the adapter */
+ status = pjmedia_tp_adapter_create(pjsua_get_pjmedia_endpt(),
+ NULL, base_tp,
+ (flags & PJSUA_MED_TP_CLOSE_MEMBER),
+ &adapter);
+ if (status != PJ_SUCCESS) {
+ PJ_PERROR(1,(THIS_FILE, status, "Error creating adapter"));
+ return NULL;
+ }
+
+ PJ_LOG(3,(THIS_FILE, "Media transport is created for call %d media %d",
+ call_id, media_idx));
+
+ return adapter;
+}
+#endif
+
+/*
+ * Print buddy list.
+ */
+static void print_buddy_list(void)
+{
+ pjsua_buddy_id ids[64];
+ int i;
+ unsigned count = PJ_ARRAY_SIZE(ids);
+
+ puts("Buddy list:");
+
+ pjsua_enum_buddies(ids, &count);
+
+ if (count == 0)
+ puts(" -none-");
+ else {
+ for (i=0; i<(int)count; ++i) {
+ pjsua_buddy_info info;
+
+ if (pjsua_buddy_get_info(ids[i], &info) != PJ_SUCCESS)
+ continue;
+
+ printf(" [%2d] <%.*s> %.*s\n",
+ ids[i]+1,
+ (int)info.status_text.slen,
+ info.status_text.ptr,
+ (int)info.uri.slen,
+ info.uri.ptr);
+ }
+ }
+ puts("");
+}
+
+
+/*
+ * Print account status.
+ */
+static void print_acc_status(int acc_id)
+{
+ char buf[80];
+ pjsua_acc_info info;
+
+ pjsua_acc_get_info(acc_id, &info);
+
+ if (!info.has_registration) {
+ pj_ansi_snprintf(buf, sizeof(buf), "%.*s",
+ (int)info.status_text.slen,
+ info.status_text.ptr);
+
+ } else {
+ pj_ansi_snprintf(buf, sizeof(buf),
+ "%d/%.*s (expires=%d)",
+ info.status,
+ (int)info.status_text.slen,
+ info.status_text.ptr,
+ info.expires);
+
+ }
+
+ printf(" %c[%2d] %.*s: %s\n", (acc_id==current_acc?'*':' '),
+ acc_id, (int)info.acc_uri.slen, info.acc_uri.ptr, buf);
+ printf(" Online status: %.*s\n",
+ (int)info.online_status_text.slen,
+ info.online_status_text.ptr);
+}
+
+/* Playfile done notification, set timer to hangup calls */
+pj_status_t on_playfile_done(pjmedia_port *port, void *usr_data)
+{
+ pj_time_val delay;
+
+ PJ_UNUSED_ARG(port);
+ PJ_UNUSED_ARG(usr_data);
+
+ /* Just rewind WAV when it is played outside of call */
+ if (pjsua_call_get_count() == 0) {
+ pjsua_player_set_pos(app_config.wav_id, 0);
+ return PJ_SUCCESS;
+ }
+
+ /* Timer is already active */
+ if (app_config.auto_hangup_timer.id == 1)
+ return PJ_SUCCESS;
+
+ app_config.auto_hangup_timer.id = 1;
+ delay.sec = 0;
+ delay.msec = 200; /* Give 200 ms before hangup */
+ pjsip_endpt_schedule_timer(pjsua_get_pjsip_endpt(),
+ &app_config.auto_hangup_timer,
+ &delay);
+
+ return PJ_SUCCESS;
+}
+
+/* Auto hangup timer callback */
+static void hangup_timeout_callback(pj_timer_heap_t *timer_heap,
+ struct pj_timer_entry *entry)
+{
+ PJ_UNUSED_ARG(timer_heap);
+ PJ_UNUSED_ARG(entry);
+
+ app_config.auto_hangup_timer.id = 0;
+ pjsua_call_hangup_all();
+}
+
+/*
+ * Show a bit of help.
+ */
+static void keystroke_help(void)
+{
+ pjsua_acc_id acc_ids[16];
+ unsigned count = PJ_ARRAY_SIZE(acc_ids);
+ int i;
+
+ printf(">>>>\n");
+
+ pjsua_enum_accs(acc_ids, &count);
+
+ printf("Account list:\n");
+ for (i=0; i<(int)count; ++i)
+ print_acc_status(acc_ids[i]);
+
+ print_buddy_list();
+
+ //puts("Commands:");
+ puts("+=============================================================================+");
+ puts("| Call Commands: | Buddy, IM & Presence: | Account: |");
+ puts("| | | |");
+ puts("| m Make new call | +b Add new buddy .| +a Add new accnt |");
+ puts("| M Make multiple calls | -b Delete buddy | -a Delete accnt. |");
+ puts("| a Answer call | i Send IM | !a Modify accnt. |");
+ puts("| h Hangup call (ha=all) | s Subscribe presence | rr (Re-)register |");
+ puts("| H Hold call | u Unsubscribe presence | ru Unregister |");
+ puts("| v re-inVite (release hold) | t ToGgle Online status | > Cycle next ac.|");
+ puts("| U send UPDATE | T Set online status | < Cycle prev ac.|");
+ puts("| ],[ Select next/prev call +--------------------------+-------------------+");
+ puts("| x Xfer call | Media Commands: | Status & Config: |");
+ puts("| X Xfer with Replaces | | |");
+ puts("| # Send RFC 2833 DTMF | cl List ports | d Dump status |");
+ puts("| * Send DTMF with INFO | cc Connect port | dd Dump detailed |");
+ puts("| dq Dump curr. call quality | cd Disconnect port | dc Dump config |");
+ puts("| | V Adjust audio Volume | f Save config |");
+ puts("| S Send arbitrary REQUEST | Cp Codec priorities | |");
+ puts("+-----------------------------------------------------------------------------+");
+#if PJSUA_HAS_VIDEO
+ puts("| Video: \"vid help\" for more info |");
+ puts("+-----------------------------------------------------------------------------+");
+#endif
+ puts("| q QUIT L ReLoad sleep MS echo [0|1|txt] n: detect NAT type |");
+ puts("+=============================================================================+");
+
+ i = pjsua_call_get_count();
+ printf("You have %d active call%s\n", i, (i>1?"s":""));
+
+ if (current_call != PJSUA_INVALID_ID) {
+ pjsua_call_info ci;
+ if (pjsua_call_get_info(current_call, &ci)==PJ_SUCCESS)
+ printf("Current call id=%d to %.*s [%.*s]\n", current_call,
+ (int)ci.remote_info.slen, ci.remote_info.ptr,
+ (int)ci.state_text.slen, ci.state_text.ptr);
+ }
+}
+
+/* Help screen for video */
+#if PJSUA_HAS_VIDEO
+static void vid_show_help(void)
+{
+ pj_bool_t vid_enabled = (app_config.vid.vid_cnt > 0);
+
+ puts("+=============================================================================+");
+ puts("| Video commands: |");
+ puts("| |");
+ puts("| vid help Show this help screen |");
+ puts("| vid enable|disable Enable or disable video in next offer/answer |");
+ puts("| vid acc show Show current account video settings |");
+ puts("| vid acc autorx on|off Automatically show incoming video on/off |");
+ puts("| vid acc autotx on|off Automatically offer video on/off |");
+ puts("| vid acc cap ID Set default capture device for current acc |");
+ puts("| vid acc rend ID Set default renderer device for current acc |");
+ puts("| vid call rx on|off N Enable/disable video RX for stream N in curr call |");
+ puts("| vid call tx on|off N Enable/disable video TX for stream N in curr call |");
+ puts("| vid call add Add video stream for current call |");
+ puts("| vid call enable|disable N Enable/disable stream #N in current call |");
+ puts("| vid call cap N ID Set capture dev ID for stream #N in current call |");
+ puts("| vid dev list List all video devices |");
+ puts("| vid dev refresh Refresh video device list |");
+ puts("| vid dev prev on|off ID Enable/disable preview for specified device ID |");
+ puts("| vid codec list List video codecs |");
+ puts("| vid codec prio ID PRIO Set codec ID priority to PRIO |");
+ puts("| vid codec fps ID NUM DEN Set codec ID framerate to (NUM/DEN) fps |");
+ puts("| vid codec bw ID AVG MAX Set codec ID bitrate to AVG & MAX kbps |");
+ puts("| vid codec size ID W H Set codec ID size/resolution to W x H |");
+ puts("| vid win list List all active video windows |");
+ puts("| vid win arrange Auto arrange windows |");
+ puts("| vid win show|hide ID Show/hide the specified video window ID |");
+ puts("| vid win move ID X Y Move window ID to position X,Y |");
+ puts("| vid win resize ID w h Resize window ID to the specified width, height |");
+ puts("+=============================================================================+");
+ printf("| Video will be %s in the next offer/answer %s |\n",
+ (vid_enabled? "enabled" : "disabled"), (vid_enabled? " " : ""));
+ puts("+=============================================================================+");
+}
+#endif
+
+/*
+ * Input simple string
+ */
+static pj_bool_t simple_input(const char *title, char *buf, pj_size_t len)
+{
+ char *p;
+
+ printf("%s (empty to cancel): ", title); fflush(stdout);
+ if (fgets(buf, len, stdin) == NULL)
+ return PJ_FALSE;
+
+ /* Remove trailing newlines. */
+ for (p=buf; ; ++p) {
+ if (*p=='\r' || *p=='\n') *p='\0';
+ else if (!*p) break;
+ }
+
+ if (!*buf)
+ return PJ_FALSE;
+
+ return PJ_TRUE;
+}
+
+
+#define NO_NB -2
+struct input_result
+{
+ int nb_result;
+ char *uri_result;
+};
+
+
+/*
+ * Input URL.
+ */
+static void ui_input_url(const char *title, char *buf, int len,
+ struct input_result *result)
+{
+ result->nb_result = NO_NB;
+ result->uri_result = NULL;
+
+ print_buddy_list();
+
+ printf("Choices:\n"
+ " 0 For current dialog.\n"
+ " -1 All %d buddies in buddy list\n"
+ " [1 -%2d] Select from buddy list\n"
+ " URL An URL\n"
+ " <Enter> Empty input (or 'q') to cancel\n"
+ , pjsua_get_buddy_count(), pjsua_get_buddy_count());
+ printf("%s: ", title);
+
+ fflush(stdout);
+ if (fgets(buf, len, stdin) == NULL)
+ return;
+ len = strlen(buf);
+
+ /* Left trim */
+ while (pj_isspace(*buf)) {
+ ++buf;
+ --len;
+ }
+
+ /* Remove trailing newlines */
+ while (len && (buf[len-1] == '\r' || buf[len-1] == '\n'))
+ buf[--len] = '\0';
+
+ if (len == 0 || buf[0]=='q')
+ return;
+
+ if (pj_isdigit(*buf) || *buf=='-') {
+
+ int i;
+
+ if (*buf=='-')
+ i = 1;
+ else
+ i = 0;
+
+ for (; i<len; ++i) {
+ if (!pj_isdigit(buf[i])) {
+ puts("Invalid input");
+ return;
+ }
+ }
+
+ result->nb_result = my_atoi(buf);
+
+ if (result->nb_result >= 0 &&
+ result->nb_result <= (int)pjsua_get_buddy_count())
+ {
+ return;
+ }
+ if (result->nb_result == -1)
+ return;
+
+ puts("Invalid input");
+ result->nb_result = NO_NB;
+ return;
+
+ } else {
+ pj_status_t status;
+
+ if ((status=pjsua_verify_url(buf)) != PJ_SUCCESS) {
+ pjsua_perror(THIS_FILE, "Invalid URL", status);
+ return;
+ }
+
+ result->uri_result = buf;
+ }
+}
+
+/*
+ * List the ports in conference bridge
+ */
+static void conf_list(void)
+{
+ unsigned i, count;
+ pjsua_conf_port_id id[PJSUA_MAX_CALLS];
+
+ printf("Conference ports:\n");
+
+ count = PJ_ARRAY_SIZE(id);
+ pjsua_enum_conf_ports(id, &count);
+
+ for (i=0; i<count; ++i) {
+ char txlist[PJSUA_MAX_CALLS*4+10];
+ unsigned j;
+ pjsua_conf_port_info info;
+
+ pjsua_conf_get_port_info(id[i], &info);
+
+ txlist[0] = '\0';
+ for (j=0; j<info.listener_cnt; ++j) {
+ char s[10];
+ pj_ansi_sprintf(s, "#%d ", info.listeners[j]);
+ pj_ansi_strcat(txlist, s);
+ }
+ printf("Port #%02d[%2dKHz/%dms/%d] %20.*s transmitting to: %s\n",
+ info.slot_id,
+ info.clock_rate/1000,
+ info.samples_per_frame*1000/info.channel_count/info.clock_rate,
+ info.channel_count,
+ (int)info.name.slen,
+ info.name.ptr,
+ txlist);
+
+ }
+ puts("");
+}
+
+
+/*
+ * Send arbitrary request to remote host
+ */
+static void send_request(char *cstr_method, const pj_str_t *dst_uri)
+{
+ pj_str_t str_method;
+ pjsip_method method;
+ pjsip_tx_data *tdata;
+ pjsip_endpoint *endpt;
+ pj_status_t status;
+
+ endpt = pjsua_get_pjsip_endpt();
+
+ str_method = pj_str(cstr_method);
+ pjsip_method_init_np(&method, &str_method);
+
+ status = pjsua_acc_create_request(current_acc, &method, dst_uri, &tdata);
+
+ status = pjsip_endpt_send_request(endpt, tdata, -1, NULL, NULL);
+ if (status != PJ_SUCCESS) {
+ pjsua_perror(THIS_FILE, "Unable to send request", status);
+ return;
+ }
+}
+
+
+/*
+ * Change extended online status.
+ */
+static void change_online_status(void)
+{
+ char menuin[32];
+ pj_bool_t online_status;
+ pjrpid_element elem;
+ int i, choice;
+
+ enum {
+ AVAILABLE, BUSY, OTP, IDLE, AWAY, BRB, OFFLINE, OPT_MAX
+ };
+
+ struct opt {
+ int id;
+ char *name;
+ } opts[] = {
+ { AVAILABLE, "Available" },
+ { BUSY, "Busy"},
+ { OTP, "On the phone"},
+ { IDLE, "Idle"},
+ { AWAY, "Away"},
+ { BRB, "Be right back"},
+ { OFFLINE, "Offline"}
+ };
+
+ printf("\n"
+ "Choices:\n");
+ for (i=0; i<PJ_ARRAY_SIZE(opts); ++i) {
+ printf(" %d %s\n", opts[i].id+1, opts[i].name);
+ }
+
+ if (!simple_input("Select status", menuin, sizeof(menuin)))
+ return;
+
+ choice = atoi(menuin) - 1;
+ if (choice < 0 || choice >= OPT_MAX) {
+ puts("Invalid selection");
+ return;
+ }
+
+ pj_bzero(&elem, sizeof(elem));
+ elem.type = PJRPID_ELEMENT_TYPE_PERSON;
+
+ online_status = PJ_TRUE;
+
+ switch (choice) {
+ case AVAILABLE:
+ break;
+ case BUSY:
+ elem.activity = PJRPID_ACTIVITY_BUSY;
+ elem.note = pj_str("Busy");
+ break;
+ case OTP:
+ elem.activity = PJRPID_ACTIVITY_BUSY;
+ elem.note = pj_str("On the phone");
+ break;
+ case IDLE:
+ elem.activity = PJRPID_ACTIVITY_UNKNOWN;
+ elem.note = pj_str("Idle");
+ break;
+ case AWAY:
+ elem.activity = PJRPID_ACTIVITY_AWAY;
+ elem.note = pj_str("Away");
+ break;
+ case BRB:
+ elem.activity = PJRPID_ACTIVITY_UNKNOWN;
+ elem.note = pj_str("Be right back");
+ break;
+ case OFFLINE:
+ online_status = PJ_FALSE;
+ break;
+ }
+
+ pjsua_acc_set_online_status2(current_acc, online_status, &elem);
+}
+
+
+/*
+ * Change codec priorities.
+ */
+static void manage_codec_prio(void)
+{
+ pjsua_codec_info c[32];
+ unsigned i, count = PJ_ARRAY_SIZE(c);
+ char input[32];
+ char *codec, *prio;
+ pj_str_t id;
+ int new_prio;
+ pj_status_t status;
+
+ printf("List of audio codecs:\n");
+ pjsua_enum_codecs(c, &count);
+ for (i=0; i<count; ++i) {
+ printf(" %d\t%.*s\n", c[i].priority, (int)c[i].codec_id.slen,
+ c[i].codec_id.ptr);
+ }
+
+#if PJSUA_HAS_VIDEO
+ puts("");
+ printf("List of video codecs:\n");
+ pjsua_vid_enum_codecs(c, &count);
+ for (i=0; i<count; ++i) {
+ printf(" %d\t%.*s%s%.*s\n", c[i].priority,
+ (int)c[i].codec_id.slen,
+ c[i].codec_id.ptr,
+ c[i].desc.slen? " - ":"",
+ (int)c[i].desc.slen,
+ c[i].desc.ptr);
+ }
+#endif
+
+ puts("");
+ puts("Enter codec id and its new priority (e.g. \"speex/16000 200\", ""\"H263 200\"),");
+ puts("or empty to cancel.");
+
+ printf("Codec name (\"*\" for all) and priority: ");
+ if (fgets(input, sizeof(input), stdin) == NULL)
+ return;
+ if (input[0]=='\r' || input[0]=='\n') {
+ puts("Done");
+ return;
+ }
+
+ codec = strtok(input, " \t\r\n");
+ prio = strtok(NULL, " \r\n");
+
+ if (!codec || !prio) {
+ puts("Invalid input");
+ return;
+ }
+
+ new_prio = atoi(prio);
+ if (new_prio < 0)
+ new_prio = 0;
+ else if (new_prio > PJMEDIA_CODEC_PRIO_HIGHEST)
+ new_prio = PJMEDIA_CODEC_PRIO_HIGHEST;
+
+ status = pjsua_codec_set_priority(pj_cstr(&id, codec),
+ (pj_uint8_t)new_prio);
+#if PJSUA_HAS_VIDEO
+ if (status != PJ_SUCCESS) {
+ status = pjsua_vid_codec_set_priority(pj_cstr(&id, codec),
+ (pj_uint8_t)new_prio);
+ }
+#endif
+ if (status != PJ_SUCCESS)
+ pjsua_perror(THIS_FILE, "Error setting codec priority", status);
+}
+
+
+#if PJSUA_HAS_VIDEO
+static void vid_print_dev(int id, const pjmedia_vid_dev_info *vdi,
+ const char *title)
+{
+ char capnames[120];
+ char formats[120];
+ const char *dirname;
+ unsigned i;
+
+ if (vdi->dir == PJMEDIA_DIR_CAPTURE_RENDER) {
+ dirname = "capture, render";
+ } else if (vdi->dir == PJMEDIA_DIR_CAPTURE) {
+ dirname = "capture";
+ } else {
+ dirname = "render";
+ }
+
+
+ capnames[0] = '\0';
+ for (i=0; i<sizeof(int)*8 && (1 << i) < PJMEDIA_VID_DEV_CAP_MAX; ++i) {
+ if (vdi->caps & (1 << i)) {
+ const char *capname = pjmedia_vid_dev_cap_name(1 << i, NULL);
+ if (capname) {
+ if (*capnames)
+ strcat(capnames, ", ");
+ strncat(capnames, capname,
+ sizeof(capnames)-strlen(capnames)-1);
+ }
+ }
+ }
+
+ formats[0] = '\0';
+ for (i=0; i<vdi->fmt_cnt; ++i) {
+ const pjmedia_video_format_info *vfi =
+ pjmedia_get_video_format_info(NULL, vdi->fmt[i].id);
+ if (vfi) {
+ if (*formats)
+ strcat(formats, ", ");
+ strncat(formats, vfi->name, sizeof(formats)-strlen(formats)-1);
+ }
+ }
+
+ PJ_LOG(3,(THIS_FILE, "%3d %s [%s][%s] %s", id, vdi->name, vdi->driver,
+ dirname, title));
+ PJ_LOG(3,(THIS_FILE, " Supported capabilities: %s", capnames));
+ PJ_LOG(3,(THIS_FILE, " Supported formats: %s", formats));
+}
+
+static void vid_list_devs(void)
+{
+ unsigned i, count;
+ pjmedia_vid_dev_info vdi;
+ pj_status_t status;
+
+ PJ_LOG(3,(THIS_FILE, "Video device list:"));
+ count = pjsua_vid_dev_count();
+ if (count == 0) {
+ PJ_LOG(3,(THIS_FILE, " - no device detected -"));
+ return;
+ } else {
+ PJ_LOG(3,(THIS_FILE, "%d device(s) detected:", count));
+ }
+
+ status = pjsua_vid_dev_get_info(PJMEDIA_VID_DEFAULT_RENDER_DEV, &vdi);
+ if (status == PJ_SUCCESS)
+ vid_print_dev(PJMEDIA_VID_DEFAULT_RENDER_DEV, &vdi,
+ "(default renderer device)");
+
+ status = pjsua_vid_dev_get_info(PJMEDIA_VID_DEFAULT_CAPTURE_DEV, &vdi);
+ if (status == PJ_SUCCESS)
+ vid_print_dev(PJMEDIA_VID_DEFAULT_CAPTURE_DEV, &vdi,
+ "(default capture device)");
+
+ for (i=0; i<count; ++i) {
+ status = pjsua_vid_dev_get_info(i, &vdi);
+ if (status == PJ_SUCCESS)
+ vid_print_dev(i, &vdi, "");
+ }
+}
+
+static void app_config_init_video(pjsua_acc_config *acc_cfg)
+{
+ acc_cfg->vid_in_auto_show = app_config.vid.in_auto_show;
+ acc_cfg->vid_out_auto_transmit = app_config.vid.out_auto_transmit;
+ /* Note that normally GUI application will prefer a borderless
+ * window.
+ */
+ acc_cfg->vid_wnd_flags = PJMEDIA_VID_DEV_WND_BORDER |
+ PJMEDIA_VID_DEV_WND_RESIZABLE;
+ acc_cfg->vid_cap_dev = app_config.vid.vcapture_dev;
+ acc_cfg->vid_rend_dev = app_config.vid.vrender_dev;
+
+ if (app_config.avi_auto_play &&
+ app_config.avi_def_idx != PJSUA_INVALID_ID &&
+ app_config.avi[app_config.avi_def_idx].dev_id != PJMEDIA_VID_INVALID_DEV)
+ {
+ acc_cfg->vid_cap_dev = app_config.avi[app_config.avi_def_idx].dev_id;
+ }
+}
+
+static void app_config_show_video(int acc_id, const pjsua_acc_config *acc_cfg)
+{
+ PJ_LOG(3,(THIS_FILE,
+ "Account %d:\n"
+ " RX auto show: %d\n"
+ " TX auto transmit: %d\n"
+ " Capture dev: %d\n"
+ " Render dev: %d",
+ acc_id,
+ acc_cfg->vid_in_auto_show,
+ acc_cfg->vid_out_auto_transmit,
+ acc_cfg->vid_cap_dev,
+ acc_cfg->vid_rend_dev));
+}
+
+static void vid_handle_menu(char *menuin)
+{
+ char *argv[8];
+ int argc = 0;
+
+ /* Tokenize */
+ argv[argc] = strtok(menuin, " \t\r\n");
+ while (argv[argc] && *argv[argc]) {
+ argc++;
+ argv[argc] = strtok(NULL, " \t\r\n");
+ }
+
+ if (argc == 1 || strcmp(argv[1], "help")==0) {
+ vid_show_help();
+ } else if (argc == 2 && (strcmp(argv[1], "enable")==0 ||
+ strcmp(argv[1], "disable")==0))
+ {
+ pj_bool_t enabled = (strcmp(argv[1], "enable")==0);
+ app_config.vid.vid_cnt = (enabled ? 1 : 0);
+ PJ_LOG(3,(THIS_FILE, "Video will be %s in next offer/answer",
+ (enabled?"enabled":"disabled")));
+ } else if (strcmp(argv[1], "acc")==0) {
+ pjsua_acc_config acc_cfg;
+ pj_bool_t changed = PJ_FALSE;
+
+ pjsua_acc_get_config(current_acc, &acc_cfg);
+
+ if (argc == 3 && strcmp(argv[2], "show")==0) {
+ app_config_show_video(current_acc, &acc_cfg);
+ } else if (argc == 4 && strcmp(argv[2], "autorx")==0) {
+ int on = (strcmp(argv[3], "on")==0);
+ acc_cfg.vid_in_auto_show = on;
+ changed = PJ_TRUE;
+ } else if (argc == 4 && strcmp(argv[2], "autotx")==0) {
+ int on = (strcmp(argv[3], "on")==0);
+ acc_cfg.vid_out_auto_transmit = on;
+ changed = PJ_TRUE;
+ } else if (argc == 4 && strcmp(argv[2], "cap")==0) {
+ int dev = atoi(argv[3]);
+ acc_cfg.vid_cap_dev = dev;
+ changed = PJ_TRUE;
+ } else if (argc == 4 && strcmp(argv[2], "rend")==0) {
+ int dev = atoi(argv[3]);
+ acc_cfg.vid_rend_dev = dev;
+ changed = PJ_TRUE;
+ } else {
+ goto on_error;
+ }
+
+ if (changed) {
+ pj_status_t status = pjsua_acc_modify(current_acc, &acc_cfg);
+ if (status != PJ_SUCCESS)
+ PJ_PERROR(1,(THIS_FILE, status, "Error modifying account %d",
+ current_acc));
+ }
+
+ } else if (strcmp(argv[1], "call")==0) {
+ pjsua_call_vid_strm_op_param param;
+ pj_status_t status = PJ_SUCCESS;
+
+ pjsua_call_vid_strm_op_param_default(&param);
+
+ if (argc == 5 && strcmp(argv[2], "rx")==0) {
+ pjsua_stream_info si;
+ pj_bool_t on = (strcmp(argv[3], "on") == 0);
+
+ param.med_idx = atoi(argv[4]);
+ if (pjsua_call_get_stream_info(current_call, param.med_idx, &si) ||
+ si.type != PJMEDIA_TYPE_VIDEO)
+ {
+ PJ_PERROR(1,(THIS_FILE, PJ_EINVAL, "Invalid stream"));
+ return;
+ }
+
+ if (on) param.dir = (si.info.vid.dir | PJMEDIA_DIR_DECODING);
+ else param.dir = (si.info.vid.dir & PJMEDIA_DIR_ENCODING);
+
+ status = pjsua_call_set_vid_strm(current_call,
+ PJSUA_CALL_VID_STRM_CHANGE_DIR,
+ &param);
+ }
+ else if (argc == 5 && strcmp(argv[2], "tx")==0) {
+ pj_bool_t on = (strcmp(argv[3], "on") == 0);
+ pjsua_call_vid_strm_op op = on? PJSUA_CALL_VID_STRM_START_TRANSMIT :
+ PJSUA_CALL_VID_STRM_STOP_TRANSMIT;
+
+ param.med_idx = atoi(argv[4]);
+
+ status = pjsua_call_set_vid_strm(current_call, op, &param);
+ }
+ else if (argc == 3 && strcmp(argv[2], "add")==0) {
+ status = pjsua_call_set_vid_strm(current_call,
+ PJSUA_CALL_VID_STRM_ADD, NULL);
+ }
+ else if (argc >= 3 &&
+ (strcmp(argv[2], "disable")==0 || strcmp(argv[2], "enable")==0))
+ {
+ pj_bool_t enable = (strcmp(argv[2], "enable") == 0);
+ pjsua_call_vid_strm_op op = enable? PJSUA_CALL_VID_STRM_CHANGE_DIR :
+ PJSUA_CALL_VID_STRM_REMOVE;
+
+ param.med_idx = argc >= 4? atoi(argv[3]) : -1;
+ param.dir = PJMEDIA_DIR_ENCODING_DECODING;
+ status = pjsua_call_set_vid_strm(current_call, op, &param);
+ }
+ else if (argc >= 3 && strcmp(argv[2], "cap")==0) {
+ param.med_idx = argc >= 4? atoi(argv[3]) : -1;
+ param.cap_dev = argc >= 5? atoi(argv[4]) : PJMEDIA_VID_DEFAULT_CAPTURE_DEV;
+ status = pjsua_call_set_vid_strm(current_call,
+ PJSUA_CALL_VID_STRM_CHANGE_CAP_DEV,
+ &param);
+ } else
+ goto on_error;
+
+ if (status != PJ_SUCCESS) {
+ PJ_PERROR(1,(THIS_FILE, status, "Error modifying video stream"));
+ }
+
+ } else if (argc >= 3 && strcmp(argv[1], "dev")==0) {
+ if (strcmp(argv[2], "list")==0) {
+ vid_list_devs();
+ } else if (strcmp(argv[2], "refresh")==0) {
+ pjmedia_vid_dev_refresh();
+ } else if (strcmp(argv[2], "prev")==0) {
+ if (argc != 5) {
+ goto on_error;
+ } else {
+ pj_bool_t on = (strcmp(argv[3], "on") == 0);
+ int dev_id = atoi(argv[4]);
+ if (on) {
+ pjsua_vid_preview_param param;
+
+ pjsua_vid_preview_param_default(&param);
+ param.wnd_flags = PJMEDIA_VID_DEV_WND_BORDER |
+ PJMEDIA_VID_DEV_WND_RESIZABLE;
+ pjsua_vid_preview_start(dev_id, &param);
+ arrange_window(pjsua_vid_preview_get_win(dev_id));
+ } else {
+ pjsua_vid_win_id wid;
+ wid = pjsua_vid_preview_get_win(dev_id);
+ if (wid != PJSUA_INVALID_ID) {
+ /* Preview window hiding once it is stopped is
+ * responsibility of app */
+ pjsua_vid_win_set_show(wid, PJ_FALSE);
+ pjsua_vid_preview_stop(dev_id);
+ }
+ }
+ }
+ } else
+ goto on_error;
+ } else if (strcmp(argv[1], "win")==0) {
+ pj_status_t status = PJ_SUCCESS;
+
+ if (argc==3 && strcmp(argv[2], "list")==0) {
+ pjsua_vid_win_id wids[PJSUA_MAX_VID_WINS];
+ unsigned i, cnt = PJ_ARRAY_SIZE(wids);
+
+ pjsua_vid_enum_wins(wids, &cnt);
+
+ PJ_LOG(3,(THIS_FILE, "Found %d video windows:", cnt));
+ PJ_LOG(3,(THIS_FILE, "WID show pos size"));
+ PJ_LOG(3,(THIS_FILE, "------------------------------"));
+ for (i = 0; i < cnt; ++i) {
+ pjsua_vid_win_info wi;
+ pjsua_vid_win_get_info(wids[i], &wi);
+ PJ_LOG(3,(THIS_FILE, "%3d %c (%d,%d) %dx%d",
+ wids[i], (wi.show?'Y':'N'), wi.pos.x, wi.pos.y,
+ wi.size.w, wi.size.h));
+ }
+ } else if (argc==4 && (strcmp(argv[2], "show")==0 ||
+ strcmp(argv[2], "hide")==0))
+ {
+ pj_bool_t show = (strcmp(argv[2], "show")==0);
+ pjsua_vid_win_id wid = atoi(argv[3]);
+ status = pjsua_vid_win_set_show(wid, show);
+ } else if (argc==6 && strcmp(argv[2], "move")==0) {
+ pjsua_vid_win_id wid = atoi(argv[3]);
+ pjmedia_coord pos;
+
+ pos.x = atoi(argv[4]);
+ pos.y = atoi(argv[5]);
+ status = pjsua_vid_win_set_pos(wid, &pos);
+ } else if (argc==6 && strcmp(argv[2], "resize")==0) {
+ pjsua_vid_win_id wid = atoi(argv[3]);
+ pjmedia_rect_size size;
+
+ size.w = atoi(argv[4]);
+ size.h = atoi(argv[5]);
+ status = pjsua_vid_win_set_size(wid, &size);
+ } else if (argc==3 && strcmp(argv[2], "arrange")==0) {
+ arrange_window(PJSUA_INVALID_ID);
+ } else
+ goto on_error;
+
+ if (status != PJ_SUCCESS) {
+ PJ_PERROR(1,(THIS_FILE, status, "Window operation error"));
+ }
+
+ } else if (strcmp(argv[1], "codec")==0) {
+ pjsua_codec_info ci[PJMEDIA_CODEC_MGR_MAX_CODECS];
+ unsigned count = PJ_ARRAY_SIZE(ci);
+ pj_status_t status;
+
+ if (argc==3 && strcmp(argv[2], "list")==0) {
+ status = pjsua_vid_enum_codecs(ci, &count);
+ if (status != PJ_SUCCESS) {
+ PJ_PERROR(1,(THIS_FILE, status, "Error enumerating codecs"));
+ } else {
+ unsigned i;
+ PJ_LOG(3,(THIS_FILE, "Found %d video codecs:", count));
+ PJ_LOG(3,(THIS_FILE, "codec id prio fps bw(kbps) size"));
+ PJ_LOG(3,(THIS_FILE, "------------------------------------------"));
+ for (i=0; i<count; ++i) {
+ pjmedia_vid_codec_param cp;
+ pjmedia_video_format_detail *vfd;
+
+ status = pjsua_vid_codec_get_param(&ci[i].codec_id, &cp);
+ if (status != PJ_SUCCESS)
+ continue;
+
+ vfd = pjmedia_format_get_video_format_detail(&cp.enc_fmt,
+ PJ_TRUE);
+ PJ_LOG(3,(THIS_FILE, "%.*s%.*s %3d %7.2f %4d/%4d %dx%d",
+ (int)ci[i].codec_id.slen, ci[i].codec_id.ptr,
+ 13-(int)ci[i].codec_id.slen, " ",
+ ci[i].priority,
+ (vfd->fps.num*1.0/vfd->fps.denum),
+ vfd->avg_bps/1000, vfd->max_bps/1000,
+ vfd->size.w, vfd->size.h));
+ }
+ }
+ } else if (argc==5 && strcmp(argv[2], "prio")==0) {
+ pj_str_t cid;
+ int prio;
+ cid = pj_str(argv[3]);
+ prio = atoi(argv[4]);
+ status = pjsua_vid_codec_set_priority(&cid, (pj_uint8_t)prio);
+ if (status != PJ_SUCCESS)
+ PJ_PERROR(1,(THIS_FILE, status, "Set codec priority error"));
+ } else if (argc==6 && strcmp(argv[2], "fps")==0) {
+ pjmedia_vid_codec_param cp;
+ pj_str_t cid;
+ int M, N;
+ cid = pj_str(argv[3]);
+ M = atoi(argv[4]);
+ N = atoi(argv[5]);
+ status = pjsua_vid_codec_get_param(&cid, &cp);
+ if (status == PJ_SUCCESS) {
+ cp.enc_fmt.det.vid.fps.num = M;
+ cp.enc_fmt.det.vid.fps.denum = N;
+ status = pjsua_vid_codec_set_param(&cid, &cp);
+ }
+ if (status != PJ_SUCCESS)
+ PJ_PERROR(1,(THIS_FILE, status, "Set codec framerate error"));
+ } else if (argc==6 && strcmp(argv[2], "bw")==0) {
+ pjmedia_vid_codec_param cp;
+ pj_str_t cid;
+ int M, N;
+ cid = pj_str(argv[3]);
+ M = atoi(argv[4]);
+ N = atoi(argv[5]);
+ status = pjsua_vid_codec_get_param(&cid, &cp);
+ if (status == PJ_SUCCESS) {
+ cp.enc_fmt.det.vid.avg_bps = M * 1000;
+ cp.enc_fmt.det.vid.max_bps = N * 1000;
+ status = pjsua_vid_codec_set_param(&cid, &cp);
+ }
+ if (status != PJ_SUCCESS)
+ PJ_PERROR(1,(THIS_FILE, status, "Set codec bitrate error"));
+ } else if (argc==6 && strcmp(argv[2], "size")==0) {
+ pjmedia_vid_codec_param cp;
+ pj_str_t cid;
+ int M, N;
+ cid = pj_str(argv[3]);
+ M = atoi(argv[4]);
+ N = atoi(argv[5]);
+ status = pjsua_vid_codec_get_param(&cid, &cp);
+ if (status == PJ_SUCCESS) {
+ cp.enc_fmt.det.vid.size.w = M;
+ cp.enc_fmt.det.vid.size.h = N;
+ status = pjsua_vid_codec_set_param(&cid, &cp);
+ }
+ if (status != PJ_SUCCESS)
+ PJ_PERROR(1,(THIS_FILE, status, "Set codec bitrate error"));
+ } else
+ goto on_error;
+ } else
+ goto on_error;
+
+ return;
+
+on_error:
+ PJ_LOG(1,(THIS_FILE, "Invalid command, use 'vid help'"));
+}
+
+#else
+
+static void app_config_init_video(pjsua_acc_config *acc_cfg)
+{
+ PJ_UNUSED_ARG(acc_cfg);
+}
+
+#endif /* PJSUA_HAS_VIDEO */
+
+
+/*
+ * Main "user interface" loop.
+ */
+void console_app_main(const pj_str_t *uri_to_call)
+{
+ char menuin[32];
+ char buf[128];
+ char text[128];
+ int i, count;
+ char *uri;
+ pj_str_t tmp;
+ struct input_result result;
+ pjsua_msg_data msg_data;
+ pjsua_call_info call_info;
+ pjsua_acc_info acc_info;
+ pjsua_call_setting call_opt;
+
+ pjsua_call_setting_default(&call_opt);
+ call_opt.aud_cnt = app_config.aud_cnt;
+ call_opt.vid_cnt = app_config.vid.vid_cnt;
+
+ /* If user specifies URI to call, then call the URI */
+ if (uri_to_call->slen) {
+ pjsua_call_make_call( current_acc, uri_to_call, &call_opt, NULL, NULL, NULL);
+ }
+
+ keystroke_help();
+
+ for (;;) {
+
+ printf(">>> ");
+ fflush(stdout);
+
+ if (fgets(menuin, sizeof(menuin), stdin) == NULL) {
+ /*
+ * Be friendly to users who redirect commands into
+ * program, when file ends, resume with kbd.
+ * If exit is desired end script with q for quit
+ */
+ /* Reopen stdin/stdout/stderr to /dev/console */
+#if defined(PJ_WIN32) && PJ_WIN32!=0
+ if (freopen ("CONIN$", "r", stdin) == NULL) {
+#else
+ if (1) {
+#endif
+ puts("Cannot switch back to console from file redirection");
+ menuin[0] = 'q';
+ menuin[1] = '\0';
+ } else {
+ puts("Switched back to console from file redirection");
+ continue;
+ }
+ }
+
+ if (cmd_echo) {
+ printf("%s", menuin);
+ }
+
+ /* Update call setting */
+ pjsua_call_setting_default(&call_opt);
+ call_opt.aud_cnt = app_config.aud_cnt;
+ call_opt.vid_cnt = app_config.vid.vid_cnt;
+
+ switch (menuin[0]) {
+
+ case 'm':
+ /* Make call! : */
+ printf("(You currently have %d calls)\n",
+ pjsua_call_get_count());
+
+ uri = NULL;
+ ui_input_url("Make call", buf, sizeof(buf), &result);
+ if (result.nb_result != NO_NB) {
+
+ if (result.nb_result == -1 || result.nb_result == 0) {
+ puts("You can't do that with make call!");
+ continue;
+ } else {
+ pjsua_buddy_info binfo;
+ pjsua_buddy_get_info(result.nb_result-1, &binfo);
+ tmp.ptr = buf;
+ pj_strncpy(&tmp, &binfo.uri, sizeof(buf));
+ }
+
+ } else if (result.uri_result) {
+ tmp = pj_str(result.uri_result);
+ } else {
+ tmp.slen = 0;
+ }
+
+ pjsua_msg_data_init(&msg_data);
+ TEST_MULTIPART(&msg_data);
+ pjsua_call_make_call( current_acc, &tmp, &call_opt, NULL, &msg_data, NULL);
+ break;
+
+ case 'M':
+ /* Make multiple calls! : */
+ printf("(You currently have %d calls)\n",
+ pjsua_call_get_count());
+
+ if (!simple_input("Number of calls", menuin, sizeof(menuin)))
+ continue;
+
+ count = my_atoi(menuin);
+ if (count < 1)
+ continue;
+
+ ui_input_url("Make call", buf, sizeof(buf), &result);
+ if (result.nb_result != NO_NB) {
+ pjsua_buddy_info binfo;
+ if (result.nb_result == -1 || result.nb_result == 0) {
+ puts("You can't do that with make call!");
+ continue;
+ }
+ pjsua_buddy_get_info(result.nb_result-1, &binfo);
+ tmp.ptr = buf;
+ pj_strncpy(&tmp, &binfo.uri, sizeof(buf));
+ } else {
+ tmp = pj_str(result.uri_result);
+ }
+
+ for (i=0; i<my_atoi(menuin); ++i) {
+ pj_status_t status;
+
+ status = pjsua_call_make_call(current_acc, &tmp, &call_opt, NULL,
+ NULL, NULL);
+ if (status != PJ_SUCCESS)
+ break;
+ }
+ break;
+
+ case 'n':
+ i = pjsua_detect_nat_type();
+ if (i != PJ_SUCCESS)
+ pjsua_perror(THIS_FILE, "Error", i);
+ break;
+
+ case 'i':
+ /* Send instant messaeg */
+
+ /* i is for call index to send message, if any */
+ i = -1;
+
+ /* Make compiler happy. */
+ uri = NULL;
+
+ /* Input destination. */
+ ui_input_url("Send IM to", buf, sizeof(buf), &result);
+ if (result.nb_result != NO_NB) {
+
+ if (result.nb_result == -1) {
+ puts("You can't send broadcast IM like that!");
+ continue;
+
+ } else if (result.nb_result == 0) {
+
+ i = current_call;
+
+ } else {
+ pjsua_buddy_info binfo;
+ pjsua_buddy_get_info(result.nb_result-1, &binfo);
+ tmp.ptr = buf;
+ pj_strncpy_with_null(&tmp, &binfo.uri, sizeof(buf));
+ uri = buf;
+ }
+
+ } else if (result.uri_result) {
+ uri = result.uri_result;
+ }
+
+
+ /* Send typing indication. */
+ if (i != -1)
+ pjsua_call_send_typing_ind(i, PJ_TRUE, NULL);
+ else {
+ pj_str_t tmp_uri = pj_str(uri);
+ pjsua_im_typing(current_acc, &tmp_uri, PJ_TRUE, NULL);
+ }
+
+ /* Input the IM . */
+ if (!simple_input("Message", text, sizeof(text))) {
+ /*
+ * Cancelled.
+ * Send typing notification too, saying we're not typing.
+ */
+ if (i != -1)
+ pjsua_call_send_typing_ind(i, PJ_FALSE, NULL);
+ else {
+ pj_str_t tmp_uri = pj_str(uri);
+ pjsua_im_typing(current_acc, &tmp_uri, PJ_FALSE, NULL);
+ }
+ continue;
+ }
+
+ tmp = pj_str(text);
+
+ /* Send the IM */
+ if (i != -1)
+ pjsua_call_send_im(i, NULL, &tmp, NULL, NULL);
+ else {
+ pj_str_t tmp_uri = pj_str(uri);
+ pjsua_im_send(current_acc, &tmp_uri, NULL, &tmp, NULL, NULL);
+ }
+
+ break;
+
+ case 'a':
+
+ if (current_call != -1) {
+ pjsua_call_get_info(current_call, &call_info);
+ } else {
+ /* Make compiler happy */
+ call_info.role = PJSIP_ROLE_UAC;
+ call_info.state = PJSIP_INV_STATE_DISCONNECTED;
+ }
+
+ if (current_call == -1 ||
+ call_info.role != PJSIP_ROLE_UAS ||
+ call_info.state >= PJSIP_INV_STATE_CONNECTING)
+ {
+ puts("No pending incoming call");
+ fflush(stdout);
+ continue;
+
+ } else {
+ int st_code;
+ char contact[120];
+ pj_str_t hname = { "Contact", 7 };
+ pj_str_t hvalue;
+ pjsip_generic_string_hdr hcontact;
+
+ if (!simple_input("Answer with code (100-699)", buf, sizeof(buf)))
+ continue;
+
+ st_code = my_atoi(buf);
+ if (st_code < 100)
+ continue;
+
+ pjsua_msg_data_init(&msg_data);
+
+ if (st_code/100 == 3) {
+ if (!simple_input("Enter URL to be put in Contact",
+ contact, sizeof(contact)))
+ continue;
+ hvalue = pj_str(contact);
+ pjsip_generic_string_hdr_init2(&hcontact, &hname, &hvalue);
+
+ pj_list_push_back(&msg_data.hdr_list, &hcontact);
+ }
+
+ /*
+ * Must check again!
+ * Call may have been disconnected while we're waiting for
+ * keyboard input.
+ */
+ if (current_call == -1) {
+ puts("Call has been disconnected");
+ fflush(stdout);
+ continue;
+ }
+
+ pjsua_call_answer2(current_call, &call_opt, st_code, NULL, &msg_data);
+ }
+
+ break;
+
+
+ case 'h':
+
+ if (current_call == -1) {
+ puts("No current call");
+ fflush(stdout);
+ continue;
+
+ } else if (menuin[1] == 'a') {
+
+ /* Hangup all calls */
+ pjsua_call_hangup_all();
+
+ } else {
+
+ /* Hangup current calls */
+ pjsua_call_hangup(current_call, 0, NULL, NULL);
+ }
+ break;
+
+ case ']':
+ case '[':
+ /*
+ * Cycle next/prev dialog.
+ */
+ if (menuin[0] == ']') {
+ find_next_call();
+
+ } else {
+ find_prev_call();
+ }
+
+ if (current_call != -1) {
+
+ pjsua_call_get_info(current_call, &call_info);
+ PJ_LOG(3,(THIS_FILE,"Current dialog: %.*s",
+ (int)call_info.remote_info.slen,
+ call_info.remote_info.ptr));
+
+ } else {
+ PJ_LOG(3,(THIS_FILE,"No current dialog"));
+ }
+ break;
+
+
+ case '>':
+ case '<':
+ if (!simple_input("Enter account ID to select", buf, sizeof(buf)))
+ break;
+
+ i = my_atoi(buf);
+ if (pjsua_acc_is_valid(i)) {
+ pjsua_acc_set_default(i);
+ PJ_LOG(3,(THIS_FILE, "Current account changed to %d", i));
+ } else {
+ PJ_LOG(3,(THIS_FILE, "Invalid account id %d", i));
+ }
+ break;
+
+
+ case '+':
+ if (menuin[1] == 'b') {
+
+ pjsua_buddy_config buddy_cfg;
+ pjsua_buddy_id buddy_id;
+ pj_status_t status;
+
+ if (!simple_input("Enter buddy's URI:", buf, sizeof(buf)))
+ break;
+
+ if (pjsua_verify_url(buf) != PJ_SUCCESS) {
+ printf("Invalid URI '%s'\n", buf);
+ break;
+ }
+
+ pj_bzero(&buddy_cfg, sizeof(pjsua_buddy_config));
+
+ buddy_cfg.uri = pj_str(buf);
+ buddy_cfg.subscribe = PJ_TRUE;
+
+ status = pjsua_buddy_add(&buddy_cfg, &buddy_id);
+ if (status == PJ_SUCCESS) {
+ printf("New buddy '%s' added at index %d\n",
+ buf, buddy_id+1);
+ }
+
+ } else if (menuin[1] == 'a') {
+
+ char id[80], registrar[80], realm[80], uname[80], passwd[30];
+ pjsua_acc_config acc_cfg;
+ pj_status_t status;
+
+ if (!simple_input("Your SIP URL:", id, sizeof(id)))
+ break;
+ if (!simple_input("URL of the registrar:", registrar, sizeof(registrar)))
+ break;
+ if (!simple_input("Auth Realm:", realm, sizeof(realm)))
+ break;
+ if (!simple_input("Auth Username:", uname, sizeof(uname)))
+ break;
+ if (!simple_input("Auth Password:", passwd, sizeof(passwd)))
+ break;
+
+ pjsua_acc_config_default(&acc_cfg);
+ acc_cfg.id = pj_str(id);
+ acc_cfg.reg_uri = pj_str(registrar);
+ acc_cfg.cred_count = 1;
+ acc_cfg.cred_info[0].scheme = pj_str("Digest");
+ acc_cfg.cred_info[0].realm = pj_str(realm);
+ acc_cfg.cred_info[0].username = pj_str(uname);
+ acc_cfg.cred_info[0].data_type = 0;
+ acc_cfg.cred_info[0].data = pj_str(passwd);
+
+ acc_cfg.rtp_cfg = app_config.rtp_cfg;
+ app_config_init_video(&acc_cfg);
+
+ status = pjsua_acc_add(&acc_cfg, PJ_TRUE, NULL);
+ if (status != PJ_SUCCESS) {
+ pjsua_perror(THIS_FILE, "Error adding new account", status);
+ }
+
+ } else {
+ printf("Invalid input %s\n", menuin);
+ }
+ break;
+
+ case '-':
+ if (menuin[1] == 'b') {
+ if (!simple_input("Enter buddy ID to delete",buf,sizeof(buf)))
+ break;
+
+ i = my_atoi(buf) - 1;
+
+ if (!pjsua_buddy_is_valid(i)) {
+ printf("Invalid buddy id %d\n", i);
+ } else {
+ pjsua_buddy_del(i);
+ printf("Buddy %d deleted\n", i);
+ }
+
+ } else if (menuin[1] == 'a') {
+
+ if (!simple_input("Enter account ID to delete",buf,sizeof(buf)))
+ break;
+
+ i = my_atoi(buf);
+
+ if (!pjsua_acc_is_valid(i)) {
+ printf("Invalid account id %d\n", i);
+ } else {
+ pjsua_acc_del(i);
+ printf("Account %d deleted\n", i);
+ }
+
+ } else {
+ printf("Invalid input %s\n", menuin);
+ }
+ break;
+
+ case 'H':
+ /*
+ * Hold call.
+ */
+ if (current_call != -1) {
+
+ pjsua_call_set_hold(current_call, NULL);
+
+ } else {
+ PJ_LOG(3,(THIS_FILE, "No current call"));
+ }
+ break;
+
+ case 'v':
+#if PJSUA_HAS_VIDEO
+ if (menuin[1]=='i' && menuin[2]=='d' && menuin[3]==' ') {
+
+ vid_handle_menu(menuin);
+
+ } else
+#endif
+ if (current_call != -1) {
+ /*
+ * re-INVITE
+ */
+ call_opt.flag |= PJSUA_CALL_UNHOLD;
+ pjsua_call_reinvite2(current_call, &call_opt, NULL);
+
+ } else {
+ PJ_LOG(3,(THIS_FILE, "No current call"));
+ }
+ break;
+
+ case 'U':
+ /*
+ * Send UPDATE
+ */
+ if (current_call != -1) {
+
+ pjsua_call_update2(current_call, &call_opt, NULL);
+
+ } else {
+ PJ_LOG(3,(THIS_FILE, "No current call"));
+ }
+ break;
+
+ case 'C':
+ if (menuin[1] == 'p') {
+ manage_codec_prio();
+ }
+ break;
+
+ case 'x':
+ /*
+ * Transfer call.
+ */
+ if (current_call == -1) {
+
+ PJ_LOG(3,(THIS_FILE, "No current call"));
+
+ } else {
+ int call = current_call;
+ pjsip_generic_string_hdr refer_sub;
+ pj_str_t STR_REFER_SUB = { "Refer-Sub", 9 };
+ pj_str_t STR_FALSE = { "false", 5 };
+ pjsua_call_info ci;
+
+ pjsua_call_get_info(current_call, &ci);
+ printf("Transfering current call [%d] %.*s\n",
+ current_call,
+ (int)ci.remote_info.slen, ci.remote_info.ptr);
+
+ ui_input_url("Transfer to URL", buf, sizeof(buf), &result);
+
+ /* Check if call is still there. */
+
+ if (call != current_call) {
+ puts("Call has been disconnected");
+ continue;
+ }
+
+ pjsua_msg_data_init(&msg_data);
+ if (app_config.no_refersub) {
+ /* Add Refer-Sub: false in outgoing REFER request */
+ pjsip_generic_string_hdr_init2(&refer_sub, &STR_REFER_SUB,
+ &STR_FALSE);
+ pj_list_push_back(&msg_data.hdr_list, &refer_sub);
+ }
+ if (result.nb_result != NO_NB) {
+ if (result.nb_result == -1 || result.nb_result == 0)
+ puts("You can't do that with transfer call!");
+ else {
+ pjsua_buddy_info binfo;
+ pjsua_buddy_get_info(result.nb_result-1, &binfo);
+ pjsua_call_xfer( current_call, &binfo.uri, &msg_data);
+ }
+
+ } else if (result.uri_result) {
+ pj_str_t tmp;
+ tmp = pj_str(result.uri_result);
+ pjsua_call_xfer( current_call, &tmp, &msg_data);
+ }
+ }
+ break;
+
+ case 'X':
+ /*
+ * Transfer call with replaces.
+ */
+ if (current_call == -1) {
+
+ PJ_LOG(3,(THIS_FILE, "No current call"));
+
+ } else {
+ int call = current_call;
+ int dst_call;
+ pjsip_generic_string_hdr refer_sub;
+ pj_str_t STR_REFER_SUB = { "Refer-Sub", 9 };
+ pj_str_t STR_FALSE = { "false", 5 };
+ pjsua_call_id ids[PJSUA_MAX_CALLS];
+ pjsua_call_info ci;
+ unsigned i, count;
+
+ count = PJ_ARRAY_SIZE(ids);
+ pjsua_enum_calls(ids, &count);
+
+ if (count <= 1) {
+ puts("There are no other calls");
+ continue;
+ }
+
+ pjsua_call_get_info(current_call, &ci);
+ printf("Transfer call [%d] %.*s to one of the following:\n",
+ current_call,
+ (int)ci.remote_info.slen, ci.remote_info.ptr);
+
+ for (i=0; i<count; ++i) {
+ pjsua_call_info call_info;
+
+ if (ids[i] == call)
+ continue;
+
+ pjsua_call_get_info(ids[i], &call_info);
+ printf("%d %.*s [%.*s]\n",
+ ids[i],
+ (int)call_info.remote_info.slen,
+ call_info.remote_info.ptr,
+ (int)call_info.state_text.slen,
+ call_info.state_text.ptr);
+ }
+
+ if (!simple_input("Enter call number to be replaced",
+ buf, sizeof(buf)))
+ continue;
+
+ dst_call = my_atoi(buf);
+
+ /* Check if call is still there. */
+
+ if (call != current_call) {
+ puts("Call has been disconnected");
+ continue;
+ }
+
+ /* Check that destination call is valid. */
+ if (dst_call == call) {
+ puts("Destination call number must not be the same "
+ "as the call being transfered");
+ continue;
+ }
+ if (dst_call >= PJSUA_MAX_CALLS) {
+ puts("Invalid destination call number");
+ continue;
+ }
+ if (!pjsua_call_is_active(dst_call)) {
+ puts("Invalid destination call number");
+ continue;
+ }
+
+ pjsua_msg_data_init(&msg_data);
+ if (app_config.no_refersub) {
+ /* Add Refer-Sub: false in outgoing REFER request */
+ pjsip_generic_string_hdr_init2(&refer_sub, &STR_REFER_SUB,
+ &STR_FALSE);
+ pj_list_push_back(&msg_data.hdr_list, &refer_sub);
+ }
+
+ pjsua_call_xfer_replaces(call, dst_call,
+ PJSUA_XFER_NO_REQUIRE_REPLACES,
+ &msg_data);
+ }
+ break;
+
+ case '#':
+ /*
+ * Send DTMF strings.
+ */
+ if (current_call == -1) {
+
+ PJ_LOG(3,(THIS_FILE, "No current call"));
+
+ } else if (!pjsua_call_has_media(current_call)) {
+
+ PJ_LOG(3,(THIS_FILE, "Media is not established yet!"));
+
+ } else {
+ pj_str_t digits;
+ int call = current_call;
+ pj_status_t status;
+
+ if (!simple_input("DTMF strings to send (0-9*#A-B)", buf,
+ sizeof(buf)))
+ {
+ break;
+ }
+
+ if (call != current_call) {
+ puts("Call has been disconnected");
+ continue;
+ }
+
+ digits = pj_str(buf);
+ status = pjsua_call_dial_dtmf(current_call, &digits);
+ if (status != PJ_SUCCESS) {
+ pjsua_perror(THIS_FILE, "Unable to send DTMF", status);
+ } else {
+ puts("DTMF digits enqueued for transmission");
+ }
+ }
+ break;
+
+ case '*':
+ /* Send DTMF with INFO */
+ if (current_call == -1) {
+
+ PJ_LOG(3,(THIS_FILE, "No current call"));
+
+ } else {
+ const pj_str_t SIP_INFO = pj_str("INFO");
+ pj_str_t digits;
+ int call = current_call;
+ int i;
+ pj_status_t status;
+
+ if (!simple_input("DTMF strings to send (0-9*#A-B)", buf,
+ sizeof(buf)))
+ {
+ break;
+ }
+
+ if (call != current_call) {
+ puts("Call has been disconnected");
+ continue;
+ }
+
+ digits = pj_str(buf);
+ for (i=0; i<digits.slen; ++i) {
+ char body[80];
+
+ pjsua_msg_data_init(&msg_data);
+ msg_data.content_type = pj_str("application/dtmf-relay");
+
+ pj_ansi_snprintf(body, sizeof(body),
+ "Signal=%c\r\n"
+ "Duration=160",
+ buf[i]);
+ msg_data.msg_body = pj_str(body);
+
+ status = pjsua_call_send_request(current_call, &SIP_INFO,
+ &msg_data);
+ if (status != PJ_SUCCESS) {
+ break;
+ }
+ }
+ }
+ break;
+
+ case 'S':
+ /*
+ * Send arbitrary request
+ */
+ if (pjsua_acc_get_count() == 0) {
+ puts("Sorry, need at least one account configured");
+ break;
+ }
+
+ puts("Send arbitrary request to remote host");
+
+ /* Input METHOD */
+ if (!simple_input("Request method:",text,sizeof(text)))
+ break;
+
+ /* Input destination URI */
+ uri = NULL;
+ ui_input_url("Destination URI", buf, sizeof(buf), &result);
+ if (result.nb_result != NO_NB) {
+
+ if (result.nb_result == -1) {
+ puts("Sorry you can't do that!");
+ continue;
+ } else if (result.nb_result == 0) {
+ uri = NULL;
+ if (current_call == PJSUA_INVALID_ID) {
+ puts("No current call");
+ continue;
+ }
+ } else {
+ pjsua_buddy_info binfo;
+ pjsua_buddy_get_info(result.nb_result-1, &binfo);
+ tmp.ptr = buf;
+ pj_strncpy_with_null(&tmp, &binfo.uri, sizeof(buf));
+ uri = buf;
+ }
+
+ } else if (result.uri_result) {
+ uri = result.uri_result;
+ } else {
+ continue;
+ }
+
+ if (uri) {
+ tmp = pj_str(uri);
+ send_request(text, &tmp);
+ } else {
+ /* If you send call control request using this method
+ * (such requests includes BYE, CANCEL, etc.), it will
+ * not go well with the call state, so don't do it
+ * unless it's for testing.
+ */
+ pj_str_t method = pj_str(text);
+ pjsua_call_send_request(current_call, &method, NULL);
+ }
+ break;
+
+ case 'e':
+ if (pj_ansi_strnicmp(menuin, "echo", 4)==0) {
+ pj_str_t tmp;
+
+ tmp.ptr = menuin+5;
+ tmp.slen = pj_ansi_strlen(menuin)-6;
+
+ if (tmp.slen < 1) {
+ puts("Usage: echo [0|1]");
+ break;
+ }
+
+ cmd_echo = *tmp.ptr != '0' || tmp.slen!=1;
+ }
+ break;
+
+ case 's':
+ if (pj_ansi_strnicmp(menuin, "sleep", 5)==0) {
+ pj_str_t tmp;
+ int delay;
+
+ tmp.ptr = menuin+6;
+ tmp.slen = pj_ansi_strlen(menuin)-7;
+
+ if (tmp.slen < 1) {
+ puts("Usage: sleep MSEC");
+ break;
+ }
+
+ delay = pj_strtoul(&tmp);
+ if (delay < 0) delay = 0;
+ pj_thread_sleep(delay);
+ break;
+ }
+ /* Continue below */
+
+ case 'u':
+ /*
+ * Subscribe/unsubscribe presence.
+ */
+ ui_input_url("(un)Subscribe presence of", buf, sizeof(buf), &result);
+ if (result.nb_result != NO_NB) {
+ if (result.nb_result == -1) {
+ int i, count;
+ count = pjsua_get_buddy_count();
+ for (i=0; i<count; ++i)
+ pjsua_buddy_subscribe_pres(i, menuin[0]=='s');
+ } else if (result.nb_result == 0) {
+ puts("Sorry, can only subscribe to buddy's presence, "
+ "not from existing call");
+ } else {
+ pjsua_buddy_subscribe_pres(result.nb_result-1, (menuin[0]=='s'));
+ }
+
+ } else if (result.uri_result) {
+ puts("Sorry, can only subscribe to buddy's presence, "
+ "not arbitrary URL (for now)");
+ }
+
+ break;
+
+ case 'r':
+ switch (menuin[1]) {
+ case 'r':
+ /*
+ * Re-Register.
+ */
+ pjsua_acc_set_registration(current_acc, PJ_TRUE);
+ break;
+ case 'u':
+ /*
+ * Unregister
+ */
+ pjsua_acc_set_registration(current_acc, PJ_FALSE);
+ break;
+ }
+ break;
+
+ case 't':
+ pjsua_acc_get_info(current_acc, &acc_info);
+ acc_info.online_status = !acc_info.online_status;
+ pjsua_acc_set_online_status(current_acc, acc_info.online_status);
+ printf("Setting %s online status to %s\n",
+ acc_info.acc_uri.ptr,
+ (acc_info.online_status?"online":"offline"));
+ break;
+
+ case 'T':
+ change_online_status();
+ break;
+
+ case 'c':
+ switch (menuin[1]) {
+ case 'l':
+ conf_list();
+ break;
+ case 'c':
+ case 'd':
+ {
+ char tmp[10], src_port[10], dst_port[10];
+ pj_status_t status;
+ int cnt;
+ const char *src_title, *dst_title;
+
+ cnt = sscanf(menuin, "%s %s %s", tmp, src_port, dst_port);
+
+ if (cnt != 3) {
+ conf_list();
+
+ src_title = (menuin[1]=='c'?
+ "Connect src port #":
+ "Disconnect src port #");
+ dst_title = (menuin[1]=='c'?
+ "To dst port #":
+ "From dst port #");
+
+ if (!simple_input(src_title, src_port, sizeof(src_port)))
+ break;
+
+ if (!simple_input(dst_title, dst_port, sizeof(dst_port)))
+ break;
+ }
+
+ if (menuin[1]=='c') {
+ status = pjsua_conf_connect(my_atoi(src_port),
+ my_atoi(dst_port));
+ } else {
+ status = pjsua_conf_disconnect(my_atoi(src_port),
+ my_atoi(dst_port));
+ }
+ if (status == PJ_SUCCESS) {
+ puts("Success");
+ } else {
+ puts("ERROR!!");
+ }
+ }
+ break;
+ }
+ break;
+
+ case 'V':
+ /* Adjust audio volume */
+ sprintf(buf, "Adjust mic level: [%4.1fx] ", app_config.mic_level);
+ if (simple_input(buf,text,sizeof(text))) {
+ char *err;
+ app_config.mic_level = (float)strtod(text, &err);
+ pjsua_conf_adjust_rx_level(0, app_config.mic_level);
+ }
+ sprintf(buf, "Adjust speaker level: [%4.1fx] ",
+ app_config.speaker_level);
+ if (simple_input(buf,text,sizeof(text))) {
+ char *err;
+ app_config.speaker_level = (float)strtod(text, &err);
+ pjsua_conf_adjust_tx_level(0, app_config.speaker_level);
+ }
+
+ break;
+
+ case 'd':
+ if (menuin[1] == 'c') {
+ char settings[2000];
+ int len;
+
+ len = write_settings(&app_config, settings, sizeof(settings));
+ if (len < 1)
+ PJ_LOG(1,(THIS_FILE, "Error: not enough buffer"));
+ else
+ PJ_LOG(3,(THIS_FILE,
+ "Dumping configuration (%d bytes):\n%s\n",
+ len, settings));
+
+ } else if (menuin[1] == 'q') {
+
+ if (current_call != PJSUA_INVALID_ID) {
+ log_call_dump(current_call);
+ } else {
+ PJ_LOG(3,(THIS_FILE, "No current call"));
+ }
+
+ } else {
+ app_dump(menuin[1]=='d');
+ }
+ break;
+
+
+ case 'f':
+ if (simple_input("Enter output filename", buf, sizeof(buf))) {
+ char settings[2000];
+ int len;
+
+ len = write_settings(&app_config, settings, sizeof(settings));
+ if (len < 1)
+ PJ_LOG(1,(THIS_FILE, "Error: not enough buffer"));
+ else {
+ pj_oshandle_t fd;
+ pj_status_t status;
+
+ status = pj_file_open(app_config.pool, buf,
+ PJ_O_WRONLY, &fd);
+ if (status != PJ_SUCCESS) {
+ pjsua_perror(THIS_FILE, "Unable to open file", status);
+ } else {
+ pj_ssize_t size = len;
+ pj_file_write(fd, settings, &size);
+ pj_file_close(fd);
+
+ printf("Settings successfully written to '%s'\n", buf);
+ }
+ }
+
+ }
+ break;
+
+
+ case 'L': /* Restart */
+ app_restart = PJ_TRUE;
+ /* Continues below */
+
+ case 'q':
+ goto on_exit;
+
+ case 'R':
+ if (!pjsua_call_is_active(current_call)) {
+ PJ_LOG(1,(THIS_FILE, "Call %d has gone", current_call));
+ } else if (menuin[1] == 'a') {
+ pjsua_call_process_redirect(current_call,
+ PJSIP_REDIRECT_ACCEPT);
+ } else if (menuin[1] == 'r') {
+ pjsua_call_process_redirect(current_call,
+ PJSIP_REDIRECT_REJECT);
+ } else {
+ pjsua_call_process_redirect(current_call,
+ PJSIP_REDIRECT_STOP);
+ }
+ break;
+
+ default:
+ if (menuin[0] != '\n' && menuin[0] != '\r') {
+ printf("Invalid input %s", menuin);
+ }
+ keystroke_help();
+ break;
+ }
+ }
+
+on_exit:
+ ;
+}
+
+/*
+ * A simple registrar, invoked by default_mod_on_rx_request()
+ */
+static void simple_registrar(pjsip_rx_data *rdata)
+{
+ pjsip_tx_data *tdata;
+ const pjsip_expires_hdr *exp;
+ const pjsip_hdr *h;
+ unsigned cnt = 0;
+ pjsip_generic_string_hdr *srv;
+ pj_status_t status;
+
+ status = pjsip_endpt_create_response(pjsua_get_pjsip_endpt(),
+ rdata, 200, NULL, &tdata);
+ if (status != PJ_SUCCESS)
+ return;
+
+ exp = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_EXPIRES, NULL);
+
+ h = rdata->msg_info.msg->hdr.next;
+ while (h != &rdata->msg_info.msg->hdr) {
+ if (h->type == PJSIP_H_CONTACT) {
+ const pjsip_contact_hdr *c = (const pjsip_contact_hdr*)h;
+ int e = c->expires;
+
+ if (e < 0) {
+ if (exp)
+ e = exp->ivalue;
+ else
+ e = 3600;
+ }
+
+ if (e > 0) {
+ pjsip_contact_hdr *nc = pjsip_hdr_clone(tdata->pool, h);
+ nc->expires = e;
+ pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)nc);
+ ++cnt;
+ }
+ }
+ h = h->next;
+ }
+
+ srv = pjsip_generic_string_hdr_create(tdata->pool, NULL, NULL);
+ srv->name = pj_str("Server");
+ srv->hvalue = pj_str("pjsua simple registrar");
+ pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)srv);
+
+ pjsip_endpt_send_response2(pjsua_get_pjsip_endpt(),
+ rdata, tdata, NULL, NULL);
+}
+
+
+
+/*****************************************************************************
+ * A simple module to handle otherwise unhandled request. We will register
+ * this with the lowest priority.
+ */
+
+/* Notification on incoming request */
+static pj_bool_t default_mod_on_rx_request(pjsip_rx_data *rdata)
+{
+ pjsip_tx_data *tdata;
+ pjsip_status_code status_code;
+ pj_status_t status;
+
+ /* Don't respond to ACK! */
+ if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method,
+ &pjsip_ack_method) == 0)
+ return PJ_TRUE;
+
+ /* Simple registrar */
+ if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method,
+ &pjsip_register_method) == 0)
+ {
+ simple_registrar(rdata);
+ return PJ_TRUE;
+ }
+
+ /* Create basic response. */
+ if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method,
+ &pjsip_notify_method) == 0)
+ {
+ /* Unsolicited NOTIFY's, send with Bad Request */
+ status_code = PJSIP_SC_BAD_REQUEST;
+ } else {
+ /* Probably unknown method */
+ status_code = PJSIP_SC_METHOD_NOT_ALLOWED;
+ }
+ status = pjsip_endpt_create_response(pjsua_get_pjsip_endpt(),
+ rdata, status_code,
+ NULL, &tdata);
+ if (status != PJ_SUCCESS) {
+ pjsua_perror(THIS_FILE, "Unable to create response", status);
+ return PJ_TRUE;
+ }
+
+ /* Add Allow if we're responding with 405 */
+ if (status_code == PJSIP_SC_METHOD_NOT_ALLOWED) {
+ const pjsip_hdr *cap_hdr;
+ cap_hdr = pjsip_endpt_get_capability(pjsua_get_pjsip_endpt(),
+ PJSIP_H_ALLOW, NULL);
+ if (cap_hdr) {
+ pjsip_msg_add_hdr(tdata->msg, pjsip_hdr_clone(tdata->pool,
+ cap_hdr));
+ }
+ }
+
+ /* Add User-Agent header */
+ {
+ pj_str_t user_agent;
+ char tmp[80];
+ const pj_str_t USER_AGENT = { "User-Agent", 10};
+ pjsip_hdr *h;
+
+ pj_ansi_snprintf(tmp, sizeof(tmp), "PJSUA v%s/%s",
+ pj_get_version(), PJ_OS_NAME);
+ pj_strdup2_with_null(tdata->pool, &user_agent, tmp);
+
+ h = (pjsip_hdr*) pjsip_generic_string_hdr_create(tdata->pool,
+ &USER_AGENT,
+ &user_agent);
+ pjsip_msg_add_hdr(tdata->msg, h);
+ }
+
+ pjsip_endpt_send_response2(pjsua_get_pjsip_endpt(), rdata, tdata,
+ NULL, NULL);
+
+ return PJ_TRUE;
+}
+
+
+/* The module instance. */
+static pjsip_module mod_default_handler =
+{
+ NULL, NULL, /* prev, next. */
+ { "mod-default-handler", 19 }, /* Name. */
+ -1, /* Id */
+ PJSIP_MOD_PRIORITY_APPLICATION+99, /* Priority */
+ NULL, /* load() */
+ NULL, /* start() */
+ NULL, /* stop() */
+ NULL, /* unload() */
+ &default_mod_on_rx_request, /* on_rx_request() */
+ NULL, /* on_rx_response() */
+ NULL, /* on_tx_request. */
+ NULL, /* on_tx_response() */
+ NULL, /* on_tsx_state() */
+
+};
+
+
+
+
+/*****************************************************************************
+ * Public API
+ */
+
+pj_status_t app_init(int argc, char *argv[])
+{
+ pjsua_transport_id transport_id = -1;
+ pjsua_transport_config tcp_cfg;
+ unsigned i;
+ pj_status_t status;
+
+ app_restart = PJ_FALSE;
+
+ /* Create pjsua */
+ status = pjsua_create();
+ if (status != PJ_SUCCESS)
+ return status;
+
+ /* Create pool for application */
+ app_config.pool = pjsua_pool_create("pjsua-app", 1000, 1000);
+
+ /* Initialize default config */
+ default_config(&app_config);
+
+ /* Parse the arguments */
+ status = parse_args(argc, argv, &app_config, &uri_arg);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ /* Initialize application callbacks */
+ app_config.cfg.cb.on_call_state = &on_call_state;
+ app_config.cfg.cb.on_call_media_state = &on_call_media_state;
+ app_config.cfg.cb.on_incoming_call = &on_incoming_call;
+ app_config.cfg.cb.on_call_tsx_state = &on_call_tsx_state;
+ app_config.cfg.cb.on_dtmf_digit = &call_on_dtmf_callback;
+ app_config.cfg.cb.on_call_redirected = &call_on_redirected;
+ app_config.cfg.cb.on_reg_state = &on_reg_state;
+ app_config.cfg.cb.on_incoming_subscribe = &on_incoming_subscribe;
+ app_config.cfg.cb.on_buddy_state = &on_buddy_state;
+ app_config.cfg.cb.on_buddy_evsub_state = &on_buddy_evsub_state;
+ app_config.cfg.cb.on_pager = &on_pager;
+ app_config.cfg.cb.on_typing = &on_typing;
+ app_config.cfg.cb.on_call_transfer_status = &on_call_transfer_status;
+ app_config.cfg.cb.on_call_replaced = &on_call_replaced;
+ app_config.cfg.cb.on_nat_detect = &on_nat_detect;
+ app_config.cfg.cb.on_mwi_info = &on_mwi_info;
+ app_config.cfg.cb.on_transport_state = &on_transport_state;
+ app_config.cfg.cb.on_ice_transport_error = &on_ice_transport_error;
+ app_config.cfg.cb.on_snd_dev_operation = &on_snd_dev_operation;
+ app_config.cfg.cb.on_call_media_event = &on_call_media_event;
+#ifdef TRANSPORT_ADAPTER_SAMPLE
+ app_config.cfg.cb.on_create_media_transport = &on_create_media_transport;
+#endif
+ app_config.log_cfg.cb = log_cb;
+
+ /* Set sound device latency */
+ if (app_config.capture_lat > 0)
+ app_config.media_cfg.snd_rec_latency = app_config.capture_lat;
+ if (app_config.playback_lat)
+ app_config.media_cfg.snd_play_latency = app_config.playback_lat;
+
+ /* Initialize pjsua */
+ status = pjsua_init(&app_config.cfg, &app_config.log_cfg,
+ &app_config.media_cfg);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ /* Initialize our module to handle otherwise unhandled request */
+ status = pjsip_endpt_register_module(pjsua_get_pjsip_endpt(),
+ &mod_default_handler);
+ if (status != PJ_SUCCESS)
+ return status;
+
+#ifdef STEREO_DEMO
+ stereo_demo();
+#endif
+
+ /* Initialize calls data */
+ for (i=0; i<PJ_ARRAY_SIZE(app_config.call_data); ++i) {
+ app_config.call_data[i].timer.id = PJSUA_INVALID_ID;
+ app_config.call_data[i].timer.cb = &call_timeout_callback;
+ }
+
+ /* Optionally registers WAV file */
+ for (i=0; i<app_config.wav_count; ++i) {
+ pjsua_player_id wav_id;
+ unsigned play_options = 0;
+
+ if (app_config.auto_play_hangup)
+ play_options |= PJMEDIA_FILE_NO_LOOP;
+
+ status = pjsua_player_create(&app_config.wav_files[i], play_options,
+ &wav_id);
+ if (status != PJ_SUCCESS)
+ goto on_error;
+
+ if (app_config.wav_id == PJSUA_INVALID_ID) {
+ app_config.wav_id = wav_id;
+ app_config.wav_port = pjsua_player_get_conf_port(app_config.wav_id);
+ if (app_config.auto_play_hangup) {
+ pjmedia_port *port;
+
+ pjsua_player_get_port(app_config.wav_id, &port);
+ status = pjmedia_wav_player_set_eof_cb(port, NULL,
+ &on_playfile_done);
+ if (status != PJ_SUCCESS)
+ goto on_error;
+
+ pj_timer_entry_init(&app_config.auto_hangup_timer, 0, NULL,
+ &hangup_timeout_callback);
+ }
+ }
+ }
+
+ /* Optionally registers tone players */
+ for (i=0; i<app_config.tone_count; ++i) {
+ pjmedia_port *tport;
+ char name[80];
+ pj_str_t label;
+ pj_status_t status;
+
+ pj_ansi_snprintf(name, sizeof(name), "tone-%d,%d",
+ app_config.tones[i].freq1,
+ app_config.tones[i].freq2);
+ label = pj_str(name);
+ status = pjmedia_tonegen_create2(app_config.pool, &label,
+ 8000, 1, 160, 16,
+ PJMEDIA_TONEGEN_LOOP, &tport);
+ if (status != PJ_SUCCESS) {
+ pjsua_perror(THIS_FILE, "Unable to create tone generator", status);
+ goto on_error;
+ }
+
+ status = pjsua_conf_add_port(app_config.pool, tport,
+ &app_config.tone_slots[i]);
+ pj_assert(status == PJ_SUCCESS);
+
+ status = pjmedia_tonegen_play(tport, 1, &app_config.tones[i], 0);
+ pj_assert(status == PJ_SUCCESS);
+ }
+
+ /* Optionally create recorder file, if any. */
+ if (app_config.rec_file.slen) {
+ status = pjsua_recorder_create(&app_config.rec_file, 0, NULL, 0, 0,
+ &app_config.rec_id);
+ if (status != PJ_SUCCESS)
+ goto on_error;
+
+ app_config.rec_port = pjsua_recorder_get_conf_port(app_config.rec_id);
+ }
+
+ pj_memcpy(&tcp_cfg, &app_config.udp_cfg, sizeof(tcp_cfg));
+
+ /* Create ringback tones */
+ if (app_config.no_tones == PJ_FALSE) {
+ unsigned i, samples_per_frame;
+ pjmedia_tone_desc tone[RING_CNT+RINGBACK_CNT];
+ pj_str_t name;
+
+ samples_per_frame = app_config.media_cfg.audio_frame_ptime *
+ app_config.media_cfg.clock_rate *
+ app_config.media_cfg.channel_count / 1000;
+
+ /* Ringback tone (call is ringing) */
+ name = pj_str("ringback");
+ status = pjmedia_tonegen_create2(app_config.pool, &name,
+ app_config.media_cfg.clock_rate,
+ app_config.media_cfg.channel_count,
+ samples_per_frame,
+ 16, PJMEDIA_TONEGEN_LOOP,
+ &app_config.ringback_port);
+ if (status != PJ_SUCCESS)
+ goto on_error;
+
+ pj_bzero(&tone, sizeof(tone));
+ for (i=0; i<RINGBACK_CNT; ++i) {
+ tone[i].freq1 = RINGBACK_FREQ1;
+ tone[i].freq2 = RINGBACK_FREQ2;
+ tone[i].on_msec = RINGBACK_ON;
+ tone[i].off_msec = RINGBACK_OFF;
+ }
+ tone[RINGBACK_CNT-1].off_msec = RINGBACK_INTERVAL;
+
+ pjmedia_tonegen_play(app_config.ringback_port, RINGBACK_CNT, tone,
+ PJMEDIA_TONEGEN_LOOP);
+
+
+ status = pjsua_conf_add_port(app_config.pool, app_config.ringback_port,
+ &app_config.ringback_slot);
+ if (status != PJ_SUCCESS)
+ goto on_error;
+
+ /* Ring (to alert incoming call) */
+ name = pj_str("ring");
+ status = pjmedia_tonegen_create2(app_config.pool, &name,
+ app_config.media_cfg.clock_rate,
+ app_config.media_cfg.channel_count,
+ samples_per_frame,
+ 16, PJMEDIA_TONEGEN_LOOP,
+ &app_config.ring_port);
+ if (status != PJ_SUCCESS)
+ goto on_error;
+
+ for (i=0; i<RING_CNT; ++i) {
+ tone[i].freq1 = RING_FREQ1;
+ tone[i].freq2 = RING_FREQ2;
+ tone[i].on_msec = RING_ON;
+ tone[i].off_msec = RING_OFF;
+ }
+ tone[RING_CNT-1].off_msec = RING_INTERVAL;
+
+ pjmedia_tonegen_play(app_config.ring_port, RING_CNT,
+ tone, PJMEDIA_TONEGEN_LOOP);
+
+ status = pjsua_conf_add_port(app_config.pool, app_config.ring_port,
+ &app_config.ring_slot);
+ if (status != PJ_SUCCESS)
+ goto on_error;
+
+ }
+
+ /* Create AVI player virtual devices */
+ if (app_config.avi_cnt) {
+#if PJMEDIA_HAS_VIDEO && PJMEDIA_VIDEO_DEV_HAS_AVI
+ pjmedia_vid_dev_factory *avi_factory;
+
+ status = pjmedia_avi_dev_create_factory(pjsua_get_pool_factory(),
+ app_config.avi_cnt,
+ &avi_factory);
+ if (status != PJ_SUCCESS) {
+ PJ_PERROR(1,(THIS_FILE, status, "Error creating AVI factory"));
+ goto on_error;
+ }
+
+ for (i=0; i<app_config.avi_cnt; ++i) {
+ pjmedia_avi_dev_param avdp;
+ pjmedia_vid_dev_index avid;
+ unsigned strm_idx, strm_cnt;
+
+ app_config.avi[i].dev_id = PJMEDIA_VID_INVALID_DEV;
+ app_config.avi[i].slot = PJSUA_INVALID_ID;
+
+ pjmedia_avi_dev_param_default(&avdp);
+ avdp.path = app_config.avi[i].path;
+
+ status = pjmedia_avi_dev_alloc(avi_factory, &avdp, &avid);
+ if (status != PJ_SUCCESS) {
+ PJ_PERROR(1,(THIS_FILE, status,
+ "Error creating AVI player for %.*s",
+ (int)avdp.path.slen, avdp.path.ptr));
+ goto on_error;
+ }
+
+ PJ_LOG(4,(THIS_FILE, "AVI player %.*s created, dev_id=%d",
+ (int)avdp.title.slen, avdp.title.ptr, avid));
+
+ app_config.avi[i].dev_id = avid;
+ if (app_config.avi_def_idx == PJSUA_INVALID_ID)
+ app_config.avi_def_idx = i;
+
+ strm_cnt = pjmedia_avi_streams_get_num_streams(avdp.avi_streams);
+ for (strm_idx=0; strm_idx<strm_cnt; ++strm_idx) {
+ pjmedia_port *aud;
+ pjmedia_format *fmt;
+ pjsua_conf_port_id slot;
+ char fmt_name[5];
+
+ aud = pjmedia_avi_streams_get_stream(avdp.avi_streams,
+ strm_idx);
+ fmt = &aud->info.fmt;
+
+ pjmedia_fourcc_name(fmt->id, fmt_name);
+
+ if (fmt->id == PJMEDIA_FORMAT_PCM) {
+ status = pjsua_conf_add_port(app_config.pool, aud,
+ &slot);
+ if (status == PJ_SUCCESS) {
+ PJ_LOG(4,(THIS_FILE,
+ "AVI %.*s: audio added to slot %d",
+ (int)avdp.title.slen, avdp.title.ptr,
+ slot));
+ app_config.avi[i].slot = slot;
+ }
+ } else {
+ PJ_LOG(4,(THIS_FILE,
+ "AVI %.*s: audio ignored, format=%s",
+ (int)avdp.title.slen, avdp.title.ptr,
+ fmt_name));
+ }
+ }
+ }
+#else
+ PJ_LOG(2,(THIS_FILE,
+ "Warning: --play-avi is ignored because AVI is disabled"));
+#endif /* PJMEDIA_VIDEO_DEV_HAS_AVI */
+ }
+
+ /* Add UDP transport unless it's disabled. */
+ if (!app_config.no_udp) {
+ pjsua_acc_id aid;
+ pjsip_transport_type_e type = PJSIP_TRANSPORT_UDP;
+
+ status = pjsua_transport_create(type,
+ &app_config.udp_cfg,
+ &transport_id);
+ if (status != PJ_SUCCESS)
+ goto on_error;
+
+ /* Add local account */
+ pjsua_acc_add_local(transport_id, PJ_TRUE, &aid);
+ if (PJMEDIA_HAS_VIDEO) {
+ pjsua_acc_config acc_cfg;
+ pjsua_acc_get_config(aid, &acc_cfg);
+ app_config_init_video(&acc_cfg);
+ pjsua_acc_modify(aid, &acc_cfg);
+ }
+ //pjsua_acc_set_transport(aid, transport_id);
+ pjsua_acc_set_online_status(current_acc, PJ_TRUE);
+
+ if (app_config.udp_cfg.port == 0) {
+ pjsua_transport_info ti;
+ pj_sockaddr_in *a;
+
+ pjsua_transport_get_info(transport_id, &ti);
+ a = (pj_sockaddr_in*)&ti.local_addr;
+
+ tcp_cfg.port = pj_ntohs(a->sin_port);
+ }
+ }
+
+ /* Add UDP IPv6 transport unless it's disabled. */
+ if (!app_config.no_udp && app_config.ipv6) {
+ pjsua_acc_id aid;
+ pjsip_transport_type_e type = PJSIP_TRANSPORT_UDP6;
+ pjsua_transport_config udp_cfg;
+
+ udp_cfg = app_config.udp_cfg;
+ if (udp_cfg.port == 0)
+ udp_cfg.port = 5060;
+ else
+ udp_cfg.port += 10;
+ status = pjsua_transport_create(type,
+ &udp_cfg,
+ &transport_id);
+ if (status != PJ_SUCCESS)
+ goto on_error;
+
+ /* Add local account */
+ pjsua_acc_add_local(transport_id, PJ_TRUE, &aid);
+ if (PJMEDIA_HAS_VIDEO) {
+ pjsua_acc_config acc_cfg;
+ pjsua_acc_get_config(aid, &acc_cfg);
+ app_config_init_video(&acc_cfg);
+ pjsua_acc_modify(aid, &acc_cfg);
+ }
+ //pjsua_acc_set_transport(aid, transport_id);
+ pjsua_acc_set_online_status(current_acc, PJ_TRUE);
+
+ if (app_config.udp_cfg.port == 0) {
+ pjsua_transport_info ti;
+ pj_sockaddr_in *a;
+
+ pjsua_transport_get_info(transport_id, &ti);
+ a = (pj_sockaddr_in*)&ti.local_addr;
+
+ tcp_cfg.port = pj_ntohs(a->sin_port);
+ }
+ }
+
+ /* Add TCP transport unless it's disabled */
+ if (!app_config.no_tcp) {
+ pjsua_acc_id aid;
+
+ status = pjsua_transport_create(PJSIP_TRANSPORT_TCP,
+ &tcp_cfg,
+ &transport_id);
+ if (status != PJ_SUCCESS)
+ goto on_error;
+
+ /* Add local account */
+ pjsua_acc_add_local(transport_id, PJ_TRUE, &aid);
+ if (PJMEDIA_HAS_VIDEO) {
+ pjsua_acc_config acc_cfg;
+ pjsua_acc_get_config(aid, &acc_cfg);
+ app_config_init_video(&acc_cfg);
+ pjsua_acc_modify(aid, &acc_cfg);
+ }
+ pjsua_acc_set_online_status(current_acc, PJ_TRUE);
+
+ }
+
+
+#if defined(PJSIP_HAS_TLS_TRANSPORT) && PJSIP_HAS_TLS_TRANSPORT!=0
+ /* Add TLS transport when application wants one */
+ if (app_config.use_tls) {
+
+ pjsua_acc_id acc_id;
+
+ /* Copy the QoS settings */
+ tcp_cfg.tls_setting.qos_type = tcp_cfg.qos_type;
+ pj_memcpy(&tcp_cfg.tls_setting.qos_params, &tcp_cfg.qos_params,
+ sizeof(tcp_cfg.qos_params));
+
+ /* Set TLS port as TCP port+1 */
+ tcp_cfg.port++;
+ status = pjsua_transport_create(PJSIP_TRANSPORT_TLS,
+ &tcp_cfg,
+ &transport_id);
+ tcp_cfg.port--;
+ if (status != PJ_SUCCESS)
+ goto on_error;
+
+ /* Add local account */
+ pjsua_acc_add_local(transport_id, PJ_FALSE, &acc_id);
+ if (PJMEDIA_HAS_VIDEO) {
+ pjsua_acc_config acc_cfg;
+ pjsua_acc_get_config(acc_id, &acc_cfg);
+ app_config_init_video(&acc_cfg);
+ pjsua_acc_modify(acc_id, &acc_cfg);
+ }
+ pjsua_acc_set_online_status(acc_id, PJ_TRUE);
+ }
+#endif
+
+ if (transport_id == -1) {
+ PJ_LOG(1,(THIS_FILE, "Error: no transport is configured"));
+ status = -1;
+ goto on_error;
+ }
+
+
+ /* Add accounts */
+ for (i=0; i<app_config.acc_cnt; ++i) {
+ app_config.acc_cfg[i].rtp_cfg = app_config.rtp_cfg;
+ app_config.acc_cfg[i].reg_retry_interval = 300;
+ app_config.acc_cfg[i].reg_first_retry_interval = 60;
+
+ app_config_init_video(&app_config.acc_cfg[i]);
+
+ status = pjsua_acc_add(&app_config.acc_cfg[i], PJ_TRUE, NULL);
+ if (status != PJ_SUCCESS)
+ goto on_error;
+ pjsua_acc_set_online_status(current_acc, PJ_TRUE);
+ }
+
+ /* Add buddies */
+ for (i=0; i<app_config.buddy_cnt; ++i) {
+ status = pjsua_buddy_add(&app_config.buddy_cfg[i], NULL);
+ if (status != PJ_SUCCESS) {
+ PJ_PERROR(1,(THIS_FILE, status, "Error adding buddy"));
+ goto on_error;
+ }
+ }
+
+ /* Optionally disable some codec */
+ for (i=0; i<app_config.codec_dis_cnt; ++i) {
+ pjsua_codec_set_priority(&app_config.codec_dis[i],PJMEDIA_CODEC_PRIO_DISABLED);
+#if PJSUA_HAS_VIDEO
+ pjsua_vid_codec_set_priority(&app_config.codec_dis[i],PJMEDIA_CODEC_PRIO_DISABLED);
+#endif
+ }
+
+ /* Optionally set codec orders */
+ for (i=0; i<app_config.codec_cnt; ++i) {
+ pjsua_codec_set_priority(&app_config.codec_arg[i],
+ (pj_uint8_t)(PJMEDIA_CODEC_PRIO_NORMAL+i+9));
+#if PJSUA_HAS_VIDEO
+ pjsua_vid_codec_set_priority(&app_config.codec_arg[i],
+ (pj_uint8_t)(PJMEDIA_CODEC_PRIO_NORMAL+i+9));
+#endif
+ }
+
+ /* Add RTP transports */
+ if (app_config.ipv6)
+ status = create_ipv6_media_transports();
+ #if DISABLED_FOR_TICKET_1185
+ else
+ status = pjsua_media_transports_create(&app_config.rtp_cfg);
+ #endif
+ if (status != PJ_SUCCESS)
+ goto on_error;
+
+ /* Use null sound device? */
+#ifndef STEREO_DEMO
+ if (app_config.null_audio) {
+ status = pjsua_set_null_snd_dev();
+ if (status != PJ_SUCCESS)
+ return status;
+ }
+#endif
+
+ if (app_config.capture_dev != PJSUA_INVALID_ID ||
+ app_config.playback_dev != PJSUA_INVALID_ID)
+ {
+ status = pjsua_set_snd_dev(app_config.capture_dev,
+ app_config.playback_dev);
+ if (status != PJ_SUCCESS)
+ goto on_error;
+ }
+
+ return PJ_SUCCESS;
+
+on_error:
+ app_destroy();
+ return status;
+}
+
+
+static int stdout_refresh_proc(void *arg)
+{
+ PJ_UNUSED_ARG(arg);
+
+ /* Set thread to lowest priority so that it doesn't clobber
+ * stdout output
+ */
+ pj_thread_set_prio(pj_thread_this(),
+ pj_thread_get_prio_min(pj_thread_this()));
+
+ while (!stdout_refresh_quit) {
+ pj_thread_sleep(stdout_refresh * 1000);
+ puts(stdout_refresh_text);
+ fflush(stdout);
+ }
+
+ return 0;
+}
+
+pj_status_t app_main(void)
+{
+ pj_thread_t *stdout_refresh_thread = NULL;
+ pj_status_t status;
+
+ /* Start pjsua */
+ status = pjsua_start();
+ if (status != PJ_SUCCESS) {
+ app_destroy();
+ return status;
+ }
+
+ /* Start console refresh thread */
+ if (stdout_refresh > 0) {
+ pj_thread_create(app_config.pool, "stdout", &stdout_refresh_proc,
+ NULL, 0, 0, &stdout_refresh_thread);
+ }
+
+ console_app_main(&uri_arg);
+
+ if (stdout_refresh_thread) {
+ stdout_refresh_quit = PJ_TRUE;
+ pj_thread_join(stdout_refresh_thread);
+ pj_thread_destroy(stdout_refresh_thread);
+ }
+
+ return PJ_SUCCESS;
+}
+
+pj_status_t app_destroy(void)
+{
+ pj_status_t status;
+ unsigned i;
+
+#ifdef STEREO_DEMO
+ if (app_config.snd) {
+ pjmedia_snd_port_destroy(app_config.snd);
+ app_config.snd = NULL;
+ }
+ if (app_config.sc_ch1) {
+ pjsua_conf_remove_port(app_config.sc_ch1_slot);
+ app_config.sc_ch1_slot = PJSUA_INVALID_ID;
+ pjmedia_port_destroy(app_config.sc_ch1);
+ app_config.sc_ch1 = NULL;
+ }
+ if (app_config.sc) {
+ pjmedia_port_destroy(app_config.sc);
+ app_config.sc = NULL;
+ }
+#endif
+
+ /* Close avi devs and ports */
+ for (i=0; i<app_config.avi_cnt; ++i) {
+ if (app_config.avi[i].slot != PJSUA_INVALID_ID)
+ pjsua_conf_remove_port(app_config.avi[i].slot);
+#if PJMEDIA_HAS_VIDEO && PJMEDIA_VIDEO_DEV_HAS_AVI
+ if (app_config.avi[i].dev_id != PJMEDIA_VID_INVALID_DEV)
+ pjmedia_avi_dev_free(app_config.avi[i].dev_id);
+#endif
+ }
+
+ /* Close ringback port */
+ if (app_config.ringback_port &&
+ app_config.ringback_slot != PJSUA_INVALID_ID)
+ {
+ pjsua_conf_remove_port(app_config.ringback_slot);
+ app_config.ringback_slot = PJSUA_INVALID_ID;
+ pjmedia_port_destroy(app_config.ringback_port);
+ app_config.ringback_port = NULL;
+ }
+
+ /* Close ring port */
+ if (app_config.ring_port && app_config.ring_slot != PJSUA_INVALID_ID) {
+ pjsua_conf_remove_port(app_config.ring_slot);
+ app_config.ring_slot = PJSUA_INVALID_ID;
+ pjmedia_port_destroy(app_config.ring_port);
+ app_config.ring_port = NULL;
+ }
+
+ /* Close tone generators */
+ for (i=0; i<app_config.tone_count; ++i) {
+ pjsua_conf_remove_port(app_config.tone_slots[i]);
+ }
+
+ if (app_config.pool) {
+ pj_pool_release(app_config.pool);
+ app_config.pool = NULL;
+ }
+
+ status = pjsua_destroy();
+
+ pj_bzero(&app_config, sizeof(app_config));
+
+ return status;
+}
+
+
+#ifdef STEREO_DEMO
+/*
+ * In this stereo demo, we open the sound device in stereo mode and
+ * arrange the attachment to the PJSUA-LIB conference bridge as such
+ * so that channel0/left channel of the sound device corresponds to
+ * slot 0 in the bridge, and channel1/right channel of the sound
+ * device corresponds to slot 1 in the bridge. Then user can independently
+ * feed different media to/from the speakers/microphones channels, by
+ * connecting them to slot 0 or 1 respectively.
+ *
+ * Here's how the connection looks like:
+ *
+ +-----------+ stereo +-----------------+ 2x mono +-----------+
+ | AUDIO DEV |<------>| SPLITCOMB left|<------->|#0 BRIDGE |
+ +-----------+ | right|<------->|#1 |
+ +-----------------+ +-----------+
+ */
+static void stereo_demo()
+{
+ pjmedia_port *conf;
+ pj_status_t status;
+
+ /* Disable existing sound device */
+ conf = pjsua_set_no_snd_dev();
+
+ /* Create stereo-mono splitter/combiner */
+ status = pjmedia_splitcomb_create(app_config.pool,
+ conf->info.clock_rate /* clock rate */,
+ 2 /* stereo */,
+ 2 * conf->info.samples_per_frame,
+ conf->info.bits_per_sample,
+ 0 /* options */,
+ &app_config.sc);
+ pj_assert(status == PJ_SUCCESS);
+
+ /* Connect channel0 (left channel?) to conference port slot0 */
+ status = pjmedia_splitcomb_set_channel(app_config.sc, 0 /* ch0 */,
+ 0 /*options*/,
+ conf);
+ pj_assert(status == PJ_SUCCESS);
+
+ /* Create reverse channel for channel1 (right channel?)... */
+ status = pjmedia_splitcomb_create_rev_channel(app_config.pool,
+ app_config.sc,
+ 1 /* ch1 */,
+ 0 /* options */,
+ &app_config.sc_ch1);
+ pj_assert(status == PJ_SUCCESS);
+
+ /* .. and register it to conference bridge (it would be slot1
+ * if there's no other devices connected to the bridge)
+ */
+ status = pjsua_conf_add_port(app_config.pool, app_config.sc_ch1,
+ &app_config.sc_ch1_slot);
+ pj_assert(status == PJ_SUCCESS);
+
+ /* Create sound device */
+ status = pjmedia_snd_port_create(app_config.pool, -1, -1,
+ conf->info.clock_rate,
+ 2 /* stereo */,
+ 2 * conf->info.samples_per_frame,
+ conf->info.bits_per_sample,
+ 0, &app_config.snd);
+ pj_assert(status == PJ_SUCCESS);
+
+
+ /* Connect the splitter to the sound device */
+ status = pjmedia_snd_port_connect(app_config.snd, app_config.sc);
+ pj_assert(status == PJ_SUCCESS);
+
+}
+#endif
+
+static pj_status_t create_ipv6_media_transports(void)
+{
+ pjsua_media_transport tp[PJSUA_MAX_CALLS];
+ pj_status_t status;
+ int port = app_config.rtp_cfg.port;
+ unsigned i;
+
+ for (i=0; i<app_config.cfg.max_calls; ++i) {
+ enum { MAX_RETRY = 10 };
+ pj_sock_t sock[2];
+ pjmedia_sock_info si;
+ unsigned j;
+
+ /* Get rid of uninitialized var compiler warning with MSVC */
+ status = PJ_SUCCESS;
+
+ for (j=0; j<MAX_RETRY; ++j) {
+ unsigned k;
+
+ for (k=0; k<2; ++k) {
+ pj_sockaddr bound_addr;
+
+ status = pj_sock_socket(pj_AF_INET6(), pj_SOCK_DGRAM(), 0, &sock[k]);
+ if (status != PJ_SUCCESS)
+ break;
+
+ status = pj_sockaddr_init(pj_AF_INET6(), &bound_addr,
+ &app_config.rtp_cfg.bound_addr,
+ (unsigned short)(port+k));
+ if (status != PJ_SUCCESS)
+ break;
+
+ status = pj_sock_bind(sock[k], &bound_addr,
+ pj_sockaddr_get_len(&bound_addr));
+ if (status != PJ_SUCCESS)
+ break;
+ }
+ if (status != PJ_SUCCESS) {
+ if (k==1)
+ pj_sock_close(sock[0]);
+
+ if (port != 0)
+ port += 10;
+ else
+ break;
+
+ continue;
+ }
+
+ pj_bzero(&si, sizeof(si));
+ si.rtp_sock = sock[0];
+ si.rtcp_sock = sock[1];
+
+ pj_sockaddr_init(pj_AF_INET6(), &si.rtp_addr_name,
+ &app_config.rtp_cfg.public_addr,
+ (unsigned short)(port));
+ pj_sockaddr_init(pj_AF_INET6(), &si.rtcp_addr_name,
+ &app_config.rtp_cfg.public_addr,
+ (unsigned short)(port+1));
+
+ status = pjmedia_transport_udp_attach(pjsua_get_pjmedia_endpt(),
+ NULL,
+ &si,
+ 0,
+ &tp[i].transport);
+ if (port != 0)
+ port += 10;
+ else
+ break;
+
+ if (status == PJ_SUCCESS)
+ break;
+ }
+
+ if (status != PJ_SUCCESS) {
+ pjsua_perror(THIS_FILE, "Error creating IPv6 UDP media transport",
+ status);
+ for (j=0; j<i; ++j) {
+ pjmedia_transport_close(tp[j].transport);
+ }
+ return status;
+ }
+ }
+
+#if DISABLED_FOR_TICKET_1185
+ return pjsua_media_transports_attach(tp, i, PJ_TRUE);
+#else
+ return PJ_ENOTSUP;
+#endif
+}
+
diff --git a/pjsip-apps/src/pjsua_wince/README.TXT b/pjsip-apps/src/pjsua_wince/README.TXT
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/pjsip-apps/src/pjsua_wince/README.TXT
diff --git a/pjsip-apps/src/pjsua_wince/StdAfx.cpp b/pjsip-apps/src/pjsua_wince/StdAfx.cpp
new file mode 100644
index 0000000..dca188d
--- /dev/null
+++ b/pjsip-apps/src/pjsua_wince/StdAfx.cpp
@@ -0,0 +1,8 @@
+// stdafx.cpp : source file that includes just the standard includes
+// pjsua_wince.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
diff --git a/pjsip-apps/src/pjsua_wince/StdAfx.h b/pjsip-apps/src/pjsua_wince/StdAfx.h
new file mode 100644
index 0000000..3bc1e17
--- /dev/null
+++ b/pjsip-apps/src/pjsua_wince/StdAfx.h
@@ -0,0 +1,25 @@
+// 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__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_)
+#define AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+
+// Windows Header Files:
+#include <windows.h>
+
+// Local Header Files
+
+// TODO: reference additional headers your program requires here
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft eMbedded Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_)
diff --git a/pjsip-apps/src/pjsua_wince/newres.h b/pjsip-apps/src/pjsua_wince/newres.h
new file mode 100644
index 0000000..ac5edb7
--- /dev/null
+++ b/pjsip-apps/src/pjsua_wince/newres.h
@@ -0,0 +1,39 @@
+#ifndef __NEWRES_H__
+#define __NEWRES_H__
+
+#if !defined(UNDER_CE)
+ #define UNDER_CE _WIN32_WCE
+#endif
+
+#if defined(_WIN32_WCE)
+ #if !defined(WCEOLE_ENABLE_DIALOGEX)
+ #define DIALOGEX DIALOG DISCARDABLE
+ #endif
+ #include <commctrl.h>
+ #define SHMENUBAR RCDATA
+ #if defined(WIN32_PLATFORM_PSPC) && (_WIN32_WCE >= 300)
+ #include <aygshell.h>
+ #else
+ #define I_IMAGENONE (-2)
+ #define NOMENU 0xFFFF
+ #define IDS_SHNEW 1
+
+ #define IDM_SHAREDNEW 10
+ #define IDM_SHAREDNEWDEFAULT 11
+ #endif
+#endif // _WIN32_WCE
+
+
+#ifdef RC_INVOKED
+#ifndef _INC_WINDOWS
+#define _INC_WINDOWS
+ #include "winuser.h" // extract from windows header
+#endif
+#endif
+
+#ifdef IDC_STATIC
+#undef IDC_STATIC
+#endif
+#define IDC_STATIC (-1)
+
+#endif //__NEWRES_H__
diff --git a/pjsip-apps/src/pjsua_wince/output/.keep b/pjsip-apps/src/pjsua_wince/output/.keep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/pjsip-apps/src/pjsua_wince/output/.keep
diff --git a/pjsip-apps/src/pjsua_wince/pjsua_wince.cpp b/pjsip-apps/src/pjsua_wince/pjsua_wince.cpp
new file mode 100644
index 0000000..a10c67f
--- /dev/null
+++ b/pjsip-apps/src/pjsua_wince/pjsua_wince.cpp
@@ -0,0 +1,780 @@
+// pjsua_wince.cpp : Defines the entry point for the application.
+//
+
+#include "stdafx.h"
+#include "pjsua_wince.h"
+#include <commctrl.h>
+#include <pjsua-lib/pjsua.h>
+
+#define MAX_LOADSTRING 100
+
+// Global Variables:
+static HINSTANCE hInst;
+static HWND hMainWnd;
+static HWND hwndCB;
+static HWND hwndGlobalStatus, hwndURI, hwndCallStatus;
+static HWND hwndActionButton, hwndExitButton;
+
+
+
+//
+// Basic config.
+//
+#define SIP_PORT 5060
+
+
+//
+// Destination URI (to make call, or to subscribe presence)
+//
+#define SIP_DST_URI "sip:192.168.0.7:5061"
+
+//
+// Account
+//
+#define HAS_SIP_ACCOUNT 0 // 0 to disable registration
+#define SIP_DOMAIN "server"
+#define SIP_REALM "server"
+#define SIP_USER "user"
+#define SIP_PASSWD "secret"
+
+//
+// Outbound proxy for all accounts
+//
+#define SIP_PROXY NULL
+//#define SIP_PROXY "sip:192.168.0.2;lr"
+
+
+//
+// Configure nameserver if DNS SRV is to be used with both SIP
+// or STUN (for STUN see other settings below)
+//
+#define NAMESERVER NULL
+//#define NAMESERVER "62.241.163.201"
+
+//
+// STUN server
+#if 0
+ // Use this to have the STUN server resolved normally
+# define STUN_DOMAIN NULL
+# define STUN_SERVER "stun.fwdnet.net"
+#elif 0
+ // Use this to have the STUN server resolved with DNS SRV
+# define STUN_DOMAIN "iptel.org"
+# define STUN_SERVER NULL
+#else
+ // Use this to disable STUN
+# define STUN_DOMAIN NULL
+# define STUN_SERVER NULL
+#endif
+
+//
+// Use ICE?
+//
+#define USE_ICE 0
+
+
+//
+// Globals
+//
+static pj_pool_t *g_pool;
+static pj_str_t g_local_uri;
+static int g_current_acc;
+static int g_current_call = PJSUA_INVALID_ID;
+static int g_current_action;
+
+enum
+{
+ ID_GLOBAL_STATUS = 21,
+ ID_URI,
+ ID_CALL_STATUS,
+ ID_POLL_TIMER,
+};
+
+enum
+{
+ ID_MENU_NONE = 64,
+ ID_MENU_CALL,
+ ID_MENU_ANSWER,
+ ID_MENU_DISCONNECT,
+ ID_BTN_ACTION,
+};
+
+
+// Forward declarations of functions included in this code module:
+static ATOM MyRegisterClass (HINSTANCE, LPTSTR);
+BOOL InitInstance (HINSTANCE, int);
+static void OnCreate (HWND hWnd);
+static LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+static void OnError(const wchar_t *title, pj_status_t status)
+{
+ char errmsg[PJ_ERR_MSG_SIZE];
+ PJ_DECL_UNICODE_TEMP_BUF(werrmsg, PJ_ERR_MSG_SIZE);
+
+ pj_strerror(status, errmsg, sizeof(errmsg));
+
+ MessageBox(NULL, PJ_STRING_TO_NATIVE(errmsg, werrmsg, PJ_ERR_MSG_SIZE),
+ title, MB_OK);
+}
+
+
+static void SetLocalURI(const char *uri, int len, bool enabled=true)
+{
+ wchar_t tmp[128];
+ if (len==-1) len=pj_ansi_strlen(uri);
+ pj_ansi_to_unicode(uri, len, tmp, PJ_ARRAY_SIZE(tmp));
+ SetDlgItemText(hMainWnd, ID_GLOBAL_STATUS, tmp);
+ EnableWindow(hwndGlobalStatus, enabled?TRUE:FALSE);
+}
+
+
+
+static void SetURI(const char *uri, int len, bool enabled=true)
+{
+ wchar_t tmp[128];
+ if (len==-1) len=pj_ansi_strlen(uri);
+ pj_ansi_to_unicode(uri, len, tmp, PJ_ARRAY_SIZE(tmp));
+ SetDlgItemText(hMainWnd, ID_URI, tmp);
+ EnableWindow(hwndURI, enabled?TRUE:FALSE);
+}
+
+
+static void SetCallStatus(const char *state, int len)
+{
+ wchar_t tmp[128];
+ if (len==-1) len=pj_ansi_strlen(state);
+ pj_ansi_to_unicode(state, len, tmp, PJ_ARRAY_SIZE(tmp));
+ SetDlgItemText(hMainWnd, ID_CALL_STATUS, tmp);
+}
+
+static void SetAction(int action, bool enable=true)
+{
+ HMENU hMenu;
+
+ hMenu = CommandBar_GetMenu(hwndCB, 0);
+
+ RemoveMenu(hMenu, ID_MENU_NONE, MF_BYCOMMAND);
+ RemoveMenu(hMenu, ID_MENU_CALL, MF_BYCOMMAND);
+ RemoveMenu(hMenu, ID_MENU_ANSWER, MF_BYCOMMAND);
+ RemoveMenu(hMenu, ID_MENU_DISCONNECT, MF_BYCOMMAND);
+
+ switch (action) {
+ case ID_MENU_NONE:
+ InsertMenu(hMenu, ID_EXIT, MF_BYCOMMAND, action, TEXT("None"));
+ SetWindowText(hwndActionButton, TEXT("-"));
+ break;
+ case ID_MENU_CALL:
+ InsertMenu(hMenu, ID_EXIT, MF_BYCOMMAND, action, TEXT("Call"));
+ SetWindowText(hwndActionButton, TEXT("&Call"));
+ break;
+ case ID_MENU_ANSWER:
+ InsertMenu(hMenu, ID_EXIT, MF_BYCOMMAND, action, TEXT("Answer"));
+ SetWindowText(hwndActionButton, TEXT("&Answer"));
+ break;
+ case ID_MENU_DISCONNECT:
+ InsertMenu(hMenu, ID_EXIT, MF_BYCOMMAND, action, TEXT("Hangup"));
+ SetWindowText(hwndActionButton, TEXT("&Hangup"));
+ break;
+ }
+
+ EnableMenuItem(hMenu, action, MF_BYCOMMAND | (enable?MF_ENABLED:MF_GRAYED));
+ DrawMenuBar(hMainWnd);
+
+ g_current_action = action;
+}
+
+
+/*
+ * Handler when invite state has changed.
+ */
+static void on_call_state(pjsua_call_id call_id, pjsip_event *e)
+{
+ pjsua_call_info call_info;
+
+ PJ_UNUSED_ARG(e);
+
+ pjsua_call_get_info(call_id, &call_info);
+
+ if (call_info.state == PJSIP_INV_STATE_DISCONNECTED) {
+
+ g_current_call = PJSUA_INVALID_ID;
+ SetURI(SIP_DST_URI, -1);
+ SetAction(ID_MENU_CALL);
+ //SetCallStatus(call_info.state_text.ptr, call_info.state_text.slen);
+ SetCallStatus(call_info.last_status_text.ptr, call_info.last_status_text.slen);
+
+ } else {
+ //if (g_current_call == PJSUA_INVALID_ID)
+ // g_current_call = call_id;
+
+ if (call_info.remote_contact.slen)
+ SetURI(call_info.remote_contact.ptr, call_info.remote_contact.slen, false);
+ else
+ SetURI(call_info.remote_info.ptr, call_info.remote_info.slen, false);
+
+ if (call_info.state == PJSIP_INV_STATE_CONFIRMED)
+ SetAction(ID_MENU_DISCONNECT);
+
+ SetCallStatus(call_info.state_text.ptr, call_info.state_text.slen);
+ }
+}
+
+
+/*
+ * Callback on media state changed event.
+ * The action may connect the call to sound device, to file, or
+ * to loop the call.
+ */
+static void on_call_media_state(pjsua_call_id call_id)
+{
+ pjsua_call_info call_info;
+
+ pjsua_call_get_info(call_id, &call_info);
+
+ if (call_info.media_status == PJSUA_CALL_MEDIA_ACTIVE) {
+ pjsua_conf_connect(call_info.conf_slot, 0);
+ pjsua_conf_connect(0, call_info.conf_slot);
+ }
+}
+
+
+/**
+ * Handler when there is incoming call.
+ */
+static void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id,
+ pjsip_rx_data *rdata)
+{
+ pjsua_call_info call_info;
+
+ PJ_UNUSED_ARG(acc_id);
+ PJ_UNUSED_ARG(rdata);
+
+ if (g_current_call != PJSUA_INVALID_ID) {
+ pj_str_t reason;
+ reason = pj_str("Another call is in progress");
+ pjsua_call_answer(call_id, PJSIP_SC_BUSY_HERE, &reason, NULL);
+ return;
+ }
+
+ g_current_call = call_id;
+
+ pjsua_call_get_info(call_id, &call_info);
+
+ SetAction(ID_MENU_ANSWER);
+ SetURI(call_info.remote_info.ptr, call_info.remote_info.slen, false);
+ pjsua_call_answer(call_id, 200, NULL, NULL);
+}
+
+
+/*
+ * Handler registration status has changed.
+ */
+static void on_reg_state(pjsua_acc_id acc_id)
+{
+ PJ_UNUSED_ARG(acc_id);
+
+ // Log already written.
+}
+
+
+/*
+ * Handler on buddy state changed.
+ */
+static void on_buddy_state(pjsua_buddy_id buddy_id)
+{
+ /* Currently this is not processed */
+ PJ_UNUSED_ARG(buddy_id);
+}
+
+
+/**
+ * Incoming IM message (i.e. MESSAGE request)!
+ */
+static void on_pager(pjsua_call_id call_id, const pj_str_t *from,
+ const pj_str_t *to, const pj_str_t *contact,
+ const pj_str_t *mime_type, const pj_str_t *text)
+{
+ /* Currently this is not processed */
+ PJ_UNUSED_ARG(call_id);
+ PJ_UNUSED_ARG(from);
+ PJ_UNUSED_ARG(to);
+ PJ_UNUSED_ARG(contact);
+ PJ_UNUSED_ARG(mime_type);
+ PJ_UNUSED_ARG(text);
+}
+
+
+/**
+ * Received typing indication
+ */
+static void on_typing(pjsua_call_id call_id, const pj_str_t *from,
+ const pj_str_t *to, const pj_str_t *contact,
+ pj_bool_t is_typing)
+{
+ /* Currently this is not processed */
+ PJ_UNUSED_ARG(call_id);
+ PJ_UNUSED_ARG(from);
+ PJ_UNUSED_ARG(to);
+ PJ_UNUSED_ARG(contact);
+ PJ_UNUSED_ARG(is_typing);
+}
+
+/**
+ * Callback upon NAT detection completion
+ */
+static void nat_detect_cb(const pj_stun_nat_detect_result *res)
+{
+ if (res->status != PJ_SUCCESS) {
+ char msg[250];
+ pj_ansi_snprintf(msg, sizeof(msg), "NAT detection failed: %s",
+ res->status_text);
+ SetCallStatus(msg, pj_ansi_strlen(msg));
+ } else {
+ char msg[250];
+ pj_ansi_snprintf(msg, sizeof(msg), "NAT type is %s",
+ res->nat_type_name);
+ SetCallStatus(msg, pj_ansi_strlen(msg));
+ }
+}
+
+
+static BOOL OnInitStack(void)
+{
+ pjsua_config cfg;
+ pjsua_logging_config log_cfg;
+ pjsua_media_config media_cfg;
+ pjsua_transport_config udp_cfg;
+ pjsua_transport_config rtp_cfg;
+ pjsua_transport_id transport_id;
+ pjsua_transport_info transport_info;
+ pj_str_t tmp;
+ pj_status_t status;
+
+ /* Create pjsua */
+ status = pjsua_create();
+ if (status != PJ_SUCCESS) {
+ OnError(TEXT("Error creating pjsua"), status);
+ return FALSE;
+ }
+
+ /* Create global pool for application */
+ g_pool = pjsua_pool_create("pjsua", 4000, 4000);
+
+ /* Init configs */
+ pjsua_config_default(&cfg);
+ pjsua_media_config_default(&media_cfg);
+ pjsua_transport_config_default(&udp_cfg);
+ udp_cfg.port = SIP_PORT;
+
+ pjsua_transport_config_default(&rtp_cfg);
+ rtp_cfg.port = 40000;
+
+ pjsua_logging_config_default(&log_cfg);
+ log_cfg.level = 5;
+ log_cfg.log_filename = pj_str("\\pjsua.txt");
+ log_cfg.msg_logging = 1;
+ log_cfg.decor = pj_log_get_decor() | PJ_LOG_HAS_CR;
+
+ /* Setup media */
+ media_cfg.clock_rate = 8000;
+ media_cfg.ec_options = PJMEDIA_ECHO_SIMPLE;
+ media_cfg.ec_tail_len = 256;
+ // use default quality setting
+ //media_cfg.quality = 1;
+ media_cfg.ptime = 20;
+ media_cfg.enable_ice = USE_ICE;
+
+ /* Initialize application callbacks */
+ cfg.cb.on_call_state = &on_call_state;
+ cfg.cb.on_call_media_state = &on_call_media_state;
+ cfg.cb.on_incoming_call = &on_incoming_call;
+ cfg.cb.on_reg_state = &on_reg_state;
+ cfg.cb.on_buddy_state = &on_buddy_state;
+ cfg.cb.on_pager = &on_pager;
+ cfg.cb.on_typing = &on_typing;
+ cfg.cb.on_nat_detect = &nat_detect_cb;
+
+ if (SIP_PROXY) {
+ cfg.outbound_proxy_cnt = 1;
+ cfg.outbound_proxy[0] = pj_str(SIP_PROXY);
+ }
+
+ if (NAMESERVER) {
+ cfg.nameserver_count = 1;
+ cfg.nameserver[0] = pj_str(NAMESERVER);
+ }
+
+ if (NAMESERVER && STUN_DOMAIN) {
+ cfg.stun_domain = pj_str(STUN_DOMAIN);
+ } else if (STUN_SERVER) {
+ cfg.stun_host = pj_str(STUN_SERVER);
+ }
+
+
+ /* Initialize pjsua */
+ status = pjsua_init(&cfg, &log_cfg, &media_cfg);
+ if (status != PJ_SUCCESS) {
+ OnError(TEXT("Initialization error"), status);
+ return FALSE;
+ }
+
+ /* Set codec priority */
+ pjsua_codec_set_priority(pj_cstr(&tmp, "pcmu"), 240);
+ pjsua_codec_set_priority(pj_cstr(&tmp, "pcma"), 230);
+ pjsua_codec_set_priority(pj_cstr(&tmp, "speex/8000"), 190);
+ pjsua_codec_set_priority(pj_cstr(&tmp, "ilbc"), 189);
+ pjsua_codec_set_priority(pj_cstr(&tmp, "speex/16000"), 180);
+ pjsua_codec_set_priority(pj_cstr(&tmp, "speex/32000"), 0);
+ pjsua_codec_set_priority(pj_cstr(&tmp, "gsm"), 100);
+
+
+ /* Add UDP transport and the corresponding PJSUA account */
+ status = pjsua_transport_create(PJSIP_TRANSPORT_UDP,
+ &udp_cfg, &transport_id);
+ if (status != PJ_SUCCESS) {
+ OnError(TEXT("Error starting SIP transport"), status);
+ return FALSE;
+ }
+
+ pjsua_transport_get_info(transport_id, &transport_info);
+
+ g_local_uri.ptr = (char*)pj_pool_alloc(g_pool, 128);
+ g_local_uri.slen = pj_ansi_sprintf(g_local_uri.ptr,
+ "<sip:%.*s:%d>",
+ (int)transport_info.local_name.host.slen,
+ transport_info.local_name.host.ptr,
+ transport_info.local_name.port);
+
+
+ /* Add local account */
+ pjsua_acc_add_local(transport_id, PJ_TRUE, &g_current_acc);
+ pjsua_acc_set_online_status(g_current_acc, PJ_TRUE);
+
+ /* Add account */
+ if (HAS_SIP_ACCOUNT) {
+ pjsua_acc_config cfg;
+
+ pjsua_acc_config_default(&cfg);
+ cfg.id = pj_str("sip:" SIP_USER "@" SIP_DOMAIN);
+ cfg.reg_uri = pj_str("sip:" SIP_DOMAIN);
+ cfg.cred_count = 1;
+ cfg.cred_info[0].realm = pj_str(SIP_REALM);
+ cfg.cred_info[0].scheme = pj_str("digest");
+ cfg.cred_info[0].username = pj_str(SIP_USER);
+ cfg.cred_info[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
+ cfg.cred_info[0].data = pj_str(SIP_PASSWD);
+
+ status = pjsua_acc_add(&cfg, PJ_TRUE, &g_current_acc);
+ if (status != PJ_SUCCESS) {
+ pjsua_destroy();
+ return PJ_FALSE;
+ }
+ }
+
+ /* Add buddy */
+ if (SIP_DST_URI) {
+ pjsua_buddy_config bcfg;
+
+ pjsua_buddy_config_default(&bcfg);
+ bcfg.uri = pj_str(SIP_DST_URI);
+ bcfg.subscribe = PJ_FALSE;
+
+ pjsua_buddy_add(&bcfg, NULL);
+ }
+
+ /* Start pjsua */
+ status = pjsua_start();
+ if (status != PJ_SUCCESS) {
+ OnError(TEXT("Error starting pjsua"), status);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+
+int WINAPI WinMain(HINSTANCE hInstance,
+ HINSTANCE hPrevInstance,
+ LPTSTR lpCmdLine,
+ int nCmdShow)
+{
+ MSG msg;
+ HACCEL hAccelTable;
+
+ PJ_UNUSED_ARG(lpCmdLine);
+ PJ_UNUSED_ARG(hPrevInstance);
+
+ // Perform application initialization:
+ if (!InitInstance (hInstance, nCmdShow))
+ {
+ return FALSE;
+ }
+
+ hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_PJSUA_WINCE);
+
+
+ // Main message loop:
+ while (GetMessage(&msg, NULL, 0, 0))
+ {
+ if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+
+ return msg.wParam;
+}
+
+static ATOM MyRegisterClass(HINSTANCE hInstance, LPTSTR szWindowClass)
+{
+ WNDCLASS wc;
+
+ wc.style = CS_HREDRAW | CS_VREDRAW;
+ wc.lpfnWndProc = (WNDPROC) WndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = hInstance;
+ wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_PJSUA_WINCE));
+ wc.hCursor = 0;
+ wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
+ wc.lpszMenuName = 0;
+ wc.lpszClassName = szWindowClass;
+
+ return RegisterClass(&wc);
+}
+
+
+BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
+{
+ HWND hWnd;
+ TCHAR szTitle[MAX_LOADSTRING];
+ TCHAR szWindowClass[MAX_LOADSTRING];
+
+ hInst = hInstance;
+
+ /* Init stack */
+ if (OnInitStack() == FALSE)
+ return FALSE;
+
+ LoadString(hInstance, IDC_PJSUA_WINCE, szWindowClass, MAX_LOADSTRING);
+ MyRegisterClass(hInstance, szWindowClass);
+
+ LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
+ hWnd = CreateWindow(szWindowClass, szTitle, WS_VISIBLE,
+ CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 200,
+ NULL, NULL, hInstance, NULL);
+
+ if (!hWnd)
+ {
+ return FALSE;
+ }
+
+ hMainWnd = hWnd;
+ ShowWindow(hWnd, nCmdShow);
+ UpdateWindow(hWnd);
+ if (hwndCB)
+ CommandBar_Show(hwndCB, TRUE);
+
+ SetTimer(hMainWnd, ID_POLL_TIMER, 50, NULL);
+
+ pjsua_detect_nat_type();
+ return TRUE;
+}
+
+
+static void OnCreate(HWND hWnd)
+{
+ enum
+ {
+ X = 10,
+ Y = 40,
+ W = 220,
+ H = 30,
+ };
+
+ DWORD dwStyle;
+
+ hMainWnd = hWnd;
+
+ hwndCB = CommandBar_Create(hInst, hWnd, 1);
+ CommandBar_InsertMenubar(hwndCB, hInst, IDM_MENU, 0);
+ CommandBar_AddAdornments(hwndCB, 0, 0);
+
+ // Create global status text
+ dwStyle = WS_CHILD | WS_VISIBLE | WS_DISABLED | ES_LEFT;
+ hwndGlobalStatus = CreateWindow(
+ TEXT("EDIT"), // Class name
+ NULL, // Window text
+ dwStyle, // Window style
+ X, // x-coordinate of the upper-left corner
+ Y+0, // y-coordinate of the upper-left corner
+ W, // Width of the window for the edit
+ // control
+ H-5, // Height of the window for the edit
+ // control
+ hWnd, // Window handle to the parent window
+ (HMENU) ID_GLOBAL_STATUS, // Control identifier
+ hInst, // Instance handle
+ NULL); // Specify NULL for this parameter when
+ // you create a control
+ SetLocalURI(g_local_uri.ptr, g_local_uri.slen, false);
+
+
+ // Create URI edit
+ dwStyle = WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER;
+ hwndURI = CreateWindow (
+ TEXT("EDIT"), // Class name
+ NULL, // Window text
+ dwStyle, // Window style
+ X, // x-coordinate of the upper-left corner
+ Y+H, // y-coordinate of the upper-left corner
+ W, // Width of the window for the edit
+ // control
+ H-5, // Height of the window for the edit
+ // control
+ hWnd, // Window handle to the parent window
+ (HMENU) ID_URI, // Control identifier
+ hInst, // Instance handle
+ NULL); // Specify NULL for this parameter when
+ // you create a control
+
+ // Create action Button
+ hwndActionButton = CreateWindow( L"button", L"Action",
+ WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
+ X, Y+2*H,
+ 60, H-5, hWnd,
+ (HMENU) ID_BTN_ACTION,
+ hInst, NULL );
+
+ // Create exit button
+ hwndExitButton = CreateWindow( L"button", L"E&xit",
+ WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
+ X+70, Y+2*H,
+ 60, H-5, hWnd,
+ (HMENU) ID_EXIT,
+ hInst, NULL );
+
+
+ // Create call status edit
+ dwStyle = WS_CHILD | WS_VISIBLE | WS_DISABLED;
+ hwndCallStatus = CreateWindow (
+ TEXT("EDIT"), // Class name
+ NULL, // Window text
+ dwStyle, // Window style
+ X, // x-coordinate of the upper-left corner
+ Y+3*H, // y-coordinate of the upper-left corner
+ W, // Width of the window for the edit
+ // control
+ H-5, // Height of the window for the edit
+ // control
+ hWnd, // Window handle to the parent window
+ (HMENU) ID_CALL_STATUS, // Control identifier
+ hInst, // Instance handle
+ NULL); // Specify NULL for this parameter when
+ // you create a control
+ SetCallStatus("Ready", 5);
+ SetAction(ID_MENU_CALL);
+ SetURI(SIP_DST_URI, -1);
+ SetFocus(hWnd);
+
+}
+
+
+static void OnDestroy(void)
+{
+ pjsua_destroy();
+}
+
+static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ int wmId, wmEvent;
+
+ switch (message) {
+ case WM_KEYUP:
+ if (wParam==114) {
+ wParam = ID_MENU_CALL;
+ } else if (wParam==115) {
+ if (g_current_call == PJSUA_INVALID_ID)
+ wParam = ID_EXIT;
+ else
+ wParam = ID_MENU_DISCONNECT;
+ } else
+ break;
+
+ case WM_COMMAND:
+ wmId = LOWORD(wParam);
+ wmEvent = HIWORD(wParam);
+ if (wmId == ID_BTN_ACTION)
+ wmId = g_current_action;
+ switch (wmId)
+ {
+ case ID_MENU_CALL:
+ if (g_current_call != PJSUA_INVALID_ID) {
+ MessageBox(NULL, TEXT("Can not make call"),
+ TEXT("You already have one call active"), MB_OK);
+ }
+ pj_str_t dst_uri;
+ wchar_t text[256];
+ char tmp[256];
+ pj_status_t status;
+
+ GetWindowText(hwndURI, text, PJ_ARRAY_SIZE(text));
+ pj_unicode_to_ansi(text, pj_unicode_strlen(text),
+ tmp, sizeof(tmp));
+ dst_uri.ptr = tmp;
+ dst_uri.slen = pj_ansi_strlen(tmp);
+ status = pjsua_call_make_call(g_current_acc,
+ &dst_uri, 0, NULL,
+ NULL, &g_current_call);
+ if (status != PJ_SUCCESS)
+ OnError(TEXT("Unable to make call"), status);
+ break;
+ case ID_MENU_ANSWER:
+ if (g_current_call == PJSUA_INVALID_ID)
+ MessageBox(NULL, TEXT("Can not answer"),
+ TEXT("There is no call!"), MB_OK);
+ else
+ pjsua_call_answer(g_current_call, 200, NULL, NULL);
+ break;
+ case ID_MENU_DISCONNECT:
+ if (g_current_call == PJSUA_INVALID_ID)
+ MessageBox(NULL, TEXT("Can not disconnect"),
+ TEXT("There is no call!"), MB_OK);
+ else
+ pjsua_call_hangup(g_current_call, PJSIP_SC_DECLINE, NULL, NULL);
+ break;
+ case ID_EXIT:
+ DestroyWindow(hWnd);
+ break;
+ default:
+ return DefWindowProc(hWnd, message, wParam, lParam);
+ }
+ break;
+
+ case WM_CREATE:
+ OnCreate(hWnd);
+ break;
+
+ case WM_DESTROY:
+ OnDestroy();
+ CommandBar_Destroy(hwndCB);
+ PostQuitMessage(0);
+ break;
+
+ case WM_TIMER:
+ pjsua_handle_events(1);
+ break;
+
+ default:
+ return DefWindowProc(hWnd, message, wParam, lParam);
+ }
+ return 0;
+}
+
diff --git a/pjsip-apps/src/pjsua_wince/pjsua_wince.h b/pjsip-apps/src/pjsua_wince/pjsua_wince.h
new file mode 100644
index 0000000..14c13bf
--- /dev/null
+++ b/pjsip-apps/src/pjsua_wince/pjsua_wince.h
@@ -0,0 +1,12 @@
+
+#if !defined(AFX_PJSUA_WINCE_H__F6793AE3_47AC_45D8_B00D_AB766E72C6BF__INCLUDED_)
+#define AFX_PJSUA_WINCE_H__F6793AE3_47AC_45D8_B00D_AB766E72C6BF__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "resource.h"
+
+
+#endif // !defined(AFX_PJSUA_WINCE_H__F6793AE3_47AC_45D8_B00D_AB766E72C6BF__INCLUDED_)
diff --git a/pjsip-apps/src/pjsua_wince/pjsua_wince.ico b/pjsip-apps/src/pjsua_wince/pjsua_wince.ico
new file mode 100644
index 0000000..83b3014
--- /dev/null
+++ b/pjsip-apps/src/pjsua_wince/pjsua_wince.ico
Binary files differ
diff --git a/pjsip-apps/src/pjsua_wince/pjsua_wince.rc b/pjsip-apps/src/pjsua_wince/pjsua_wince.rc
new file mode 100644
index 0000000..6acddee
--- /dev/null
+++ b/pjsip-apps/src/pjsua_wince/pjsua_wince.rc
@@ -0,0 +1,108 @@
+//Microsoft eMbedded Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "newres.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
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_PJSUA_WINCE ICON DISCARDABLE "pjsua_wince.ICO"
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""newres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menubar
+//
+
+IDM_MENU MENU DISCARDABLE
+BEGIN
+ MENUITEM "E&xit", ID_EXIT
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Accelerator
+//
+
+IDC_PJSUA_WINCE ACCELERATORS DISCARDABLE
+BEGIN
+ "/", IDM_HELP_ABOUT, ASCII, ALT, NOINVERT
+ VK_F4, IDM_FILE_EXIT, VIRTKEY, ALT, NOINVERT
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_APP_TITLE "pjsua_wince"
+ IDS_HELLO "Hello World!"
+ IDC_PJSUA_WINCE "PJSUA_WINCE"
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/pjsip-apps/src/pjsua_wince/pjsua_wince.vcp b/pjsip-apps/src/pjsua_wince/pjsua_wince.vcp
new file mode 100644
index 0000000..3cded43
--- /dev/null
+++ b/pjsip-apps/src/pjsua_wince/pjsua_wince.vcp
@@ -0,0 +1,1097 @@
+# Microsoft eMbedded Visual Tools Project File - Name="pjsua_wince" - Package Owner=<4>
+# Microsoft eMbedded Visual Tools Generated Build File, Format Version 6.02
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (WCE x86) Application" 0x8301
+# TARGTYPE "Win32 (WCE ARMV4) Application" 0xa301
+# TARGTYPE "Win32 (WCE ARMV4I) Application" 0xa501
+# TARGTYPE "Win32 (WCE emulator) Application" 0xa601
+# TARGTYPE "Win32 (WCE ARMV4T) Application" 0xa401
+
+CFG=pjsua_wince - Win32 (WCE emulator) 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 "pjsua_wince.vcn".
+!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 "pjsua_wince.vcn" CFG="pjsua_wince - Win32 (WCE emulator) Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "pjsua_wince - Win32 (WCE emulator) Release" (based on "Win32 (WCE emulator) Application")
+!MESSAGE "pjsua_wince - Win32 (WCE emulator) Debug" (based on "Win32 (WCE emulator) Application")
+!MESSAGE "pjsua_wince - Win32 (WCE ARMV4I) Release" (based on "Win32 (WCE ARMV4I) Application")
+!MESSAGE "pjsua_wince - Win32 (WCE ARMV4I) Debug" (based on "Win32 (WCE ARMV4I) Application")
+!MESSAGE "pjsua_wince - Win32 (WCE ARMV4) Release" (based on "Win32 (WCE ARMV4) Application")
+!MESSAGE "pjsua_wince - Win32 (WCE ARMV4) Debug" (based on "Win32 (WCE ARMV4) Application")
+!MESSAGE "pjsua_wince - Win32 (WCE ARMV4T) Release" (based on "Win32 (WCE ARMV4T) Application")
+!MESSAGE "pjsua_wince - Win32 (WCE ARMV4T) Debug" (based on "Win32 (WCE ARMV4T) Application")
+!MESSAGE "pjsua_wince - Win32 (WCE x86) Release" (based on "Win32 (WCE x86) Application")
+!MESSAGE "pjsua_wince - Win32 (WCE x86) Debug" (based on "Win32 (WCE x86) Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+# PROP ATL_Project 2
+
+!IF "$(CFG)" == "pjsua_wince - Win32 (WCE emulator) Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "../../build/wince-evc4/output/pjsua-wince-emulatorRel"
+# PROP BASE Intermediate_Dir "../../build/wince-evc4/output/pjsua-wince-emulatorRel"
+# PROP BASE CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}"
+# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "../../build/wince-evc4/output/pjsua-wince-emulatorRel"
+# PROP Intermediate_Dir "../../build/wince-evc4/output/pjsua-wince-emulatorRel"
+# PROP CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}"
+# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "NDEBUG" /d "$(CePlatform)" /d "_X86_" /d "x86" /d "_i386_" /r
+# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "NDEBUG" /d "$(CePlatform)" /d "_X86_" /d "x86" /d "_i386_" /r
+CPP=cl.exe
+# ADD BASE CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "_i386_" /D UNDER_CE=$(CEVersion) /D "i_386_" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /D "NDEBUG" /Yu"stdafx.h" /Gs8192 /GF /O2 /c
+# ADD CPP /nologo /W3 /I "../../include" /I "../../../pjsip/include" /I "../../../pjlib-util/include" /I "../../../pjlib/include" /I "../../../pjmedia/include" /I "../../../pjnath/include" /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "_i386_" /D UNDER_CE=$(CEVersion) /D "i_386_" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /D "NDEBUG" /Yu"stdafx.h" /Gs8192 /GF /O2 /c
+# SUBTRACT CPP /Fr
+MTL=midl.exe
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 commctrl.lib coredll.lib $(CEx86Corelibc) /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /nodefaultlib:"OLDNAMES.lib" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86
+# ADD LINK32 $(CEx86Corelibc) commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /nodefaultlib:"OLDNAMES.lib" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86
+
+!ELSEIF "$(CFG)" == "pjsua_wince - Win32 (WCE emulator) Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "../../build/wince-evc4/output/pjsua-wince-emulatorDbg"
+# PROP BASE Intermediate_Dir "../../build/wince-evc4/output/pjsua-wince-emulatorDbg"
+# PROP BASE CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}"
+# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "../../build/wince-evc4/output/pjsua-wince-emulatorDbg"
+# PROP Intermediate_Dir "../../build/wince-evc4/output/pjsua-wince-emulatorDbg"
+# PROP CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}"
+# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d "$(CePlatform)" /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "DEBUG" /d "_X86_" /d "x86" /d "_i386_" /r
+# ADD RSC /l 0x409 /d "$(CePlatform)" /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "DEBUG" /d "_X86_" /d "x86" /d "_i386_" /r
+CPP=cl.exe
+# ADD BASE CPP /nologo /W3 /Zi /Od /D "DEBUG" /D "_i386_" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "i_386_" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /Yu"stdafx.h" /Gs8192 /GF /c
+# ADD CPP /nologo /W3 /Zi /Od /I "../../../pjsip/include" /I "../../../pjlib-util/include" /I "../../../pjlib/include" /I "../../../pjmedia/include" /I "../../../pjnath/include" /D "DEBUG" /D "_i386_" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "i_386_" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /Yu"stdafx.h" /Gs8192 /GF /c
+# SUBTRACT CPP /Fr
+MTL=midl.exe
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 commctrl.lib coredll.lib $(CEx86Corelibc) /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /debug /nodefaultlib:"OLDNAMES.lib" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86
+# ADD LINK32 $(CEx86Corelibc) commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /debug /nodefaultlib:"OLDNAMES.lib" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86
+
+!ELSEIF "$(CFG)" == "pjsua_wince - Win32 (WCE ARMV4I) Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "../../build/wince-evc4/output/pjsua-wince-ARMV4IRel"
+# PROP BASE Intermediate_Dir "../../build/wince-evc4/output/pjsua-wince-ARMV4IRel"
+# PROP BASE CPU_ID "{DC70F430-E78B-494F-A9D5-62ADC56443B8}"
+# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "../../build/wince-evc4/output/pjsua-wince-ARMV4IRel"
+# PROP Intermediate_Dir "../../build/wince-evc4/output/pjsua-wince-ARMV4IRel"
+# PROP CPU_ID "{DC70F430-E78B-494F-A9D5-62ADC56443B8}"
+# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "NDEBUG" /d "$(CePlatform)" /d "THUMB" /d "_THUMB_" /d "ARM" /d "_ARM_" /d "ARMV4I" /r
+# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "NDEBUG" /d "$(CePlatform)" /d "THUMB" /d "_THUMB_" /d "ARM" /d "_ARM_" /d "ARMV4I" /r
+CPP=clarm.exe
+# ADD BASE CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D "ARM" /D "_ARM_" /D "$(CePlatform)" /D "ARMV4I" /D UNDER_CE=$(CEVersion) /D "UNICODE" /D "_UNICODE" /D "NDEBUG" /Yu"stdafx.h" /QRarch4T /QRinterwork-return /O2 /M$(CECrtMT) /c
+# ADD CPP /nologo /W3 /I "../../include" /I "../../../pjsip/include" /I "../../../pjlib-util/include" /I "../../../pjlib/include" /I "../../../pjmedia/include" /I "../../../pjnath/include" /D _WIN32_WCE=$(CEVersion) /D "ARM" /D "_ARM_" /D "$(CePlatform)" /D "ARMV4I" /D UNDER_CE=$(CEVersion) /D "UNICODE" /D "_UNICODE" /D "NDEBUG" /Yu"stdafx.h" /QRarch4T /QRinterwork-return /O2 /M$(CECrtMT) /c
+# SUBTRACT CPP /Fr
+MTL=midl.exe
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 commctrl.lib coredll.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /nodefaultlib:"$(CENoDefaultLib)" /subsystem:$(CESubsystem) /MACHINE:THUMB
+# ADD LINK32 commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /nodefaultlib:"$(CENoDefaultLib)" /subsystem:$(CESubsystem) /MACHINE:THUMB
+
+!ELSEIF "$(CFG)" == "pjsua_wince - Win32 (WCE ARMV4I) Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "../../build/wince-evc4/output/pjsua-wince-ARMV4IDbg"
+# PROP BASE Intermediate_Dir "../../build/wince-evc4/output/pjsua-wince-ARMV4IDbg"
+# PROP BASE CPU_ID "{DC70F430-E78B-494F-A9D5-62ADC56443B8}"
+# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "../../build/wince-evc4/output/pjsua-wince-ARMV4IDbg"
+# PROP Intermediate_Dir "../../build/wince-evc4/output/pjsua-wince-ARMV4IDbg"
+# PROP CPU_ID "{DC70F430-E78B-494F-A9D5-62ADC56443B8}"
+# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "DEBUG" /d "$(CePlatform)" /d "THUMB" /d "_THUMB_" /d "ARM" /d "_ARM_" /d "ARMV4I" /r
+# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "DEBUG" /d "$(CePlatform)" /d "THUMB" /d "_THUMB_" /d "ARM" /d "_ARM_" /d "ARMV4I" /r
+CPP=clarm.exe
+# ADD BASE CPP /nologo /W3 /Zi /Od /D "DEBUG" /D "ARM" /D "_ARM_" /D "ARMV4I" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "UNICODE" /D "_UNICODE" /Yu"stdafx.h" /QRarch4T /QRinterwork-return /M$(CECrtMTDebug) /c
+# ADD CPP /nologo /W3 /Zi /Od /I "../../include" /I "../../../pjsip/include" /I "../../../pjlib-util/include" /I "../../../pjlib/include" /I "../../../pjmedia/include" /I "../../../pjnath/include" /D "DEBUG" /D "ARM" /D "_ARM_" /D "ARMV4I" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "UNICODE" /D "_UNICODE" /Yu"stdafx.h" /QRarch4T /QRinterwork-return /M$(CECrtMTDebug) /c
+# SUBTRACT CPP /Fr
+MTL=midl.exe
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 commctrl.lib coredll.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /debug /nodefaultlib:"$(CENoDefaultLib)" /subsystem:$(CESubsystem) /MACHINE:THUMB
+# ADD LINK32 commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /debug /nodefaultlib:"$(CENoDefaultLib)" /subsystem:$(CESubsystem) /MACHINE:THUMB
+
+!ELSEIF "$(CFG)" == "pjsua_wince - Win32 (WCE ARMV4) Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "../../build/wince-evc4/output/pjsua-wince-ARMV4Rel"
+# PROP BASE Intermediate_Dir "../../build/wince-evc4/output/pjsua-wince-ARMV4Rel"
+# PROP BASE CPU_ID "{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}"
+# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "../../build/wince-evc4/output/pjsua-wince-ARMV4Rel"
+# PROP Intermediate_Dir "../../build/wince-evc4/output/pjsua-wince-ARMV4Rel"
+# PROP CPU_ID "{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}"
+# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "NDEBUG" /d "UNICODE" /d "_UNICODE" /d "$(CePlatform)" /d "ARM" /d "_ARM_" /d "ARMV4" /r
+# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "NDEBUG" /d "UNICODE" /d "_UNICODE" /d "$(CePlatform)" /d "ARM" /d "_ARM_" /d "ARMV4" /r
+CPP=clarm.exe
+# ADD BASE CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "ARM" /D "_ARM_" /D "ARMV4" /D UNDER_CE=$(CEVersion) /D "UNICODE" /D "_UNICODE" /D "NDEBUG" /Yu"stdafx.h" /O2 /M$(CECrtMT) /c
+# ADD CPP /nologo /W3 /I "../../include" /I "../../../pjsip/include" /I "../../../pjlib-util/include" /I "../../../pjlib/include" /I "../../../pjmedia/include" /I "../../../pjnath/include" /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "ARM" /D "_ARM_" /D "ARMV4" /D UNDER_CE=$(CEVersion) /D "UNICODE" /D "_UNICODE" /D "NDEBUG" /Yu"stdafx.h" /O2 /M$(CECrtMT) /c
+# SUBTRACT CPP /Fr
+MTL=midl.exe
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 commctrl.lib coredll.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /nodefaultlib:"$(CENoDefaultLib)" /subsystem:$(CESubsystem) /align:"4096" /MACHINE:ARM
+# ADD LINK32 commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /nodefaultlib:"$(CENoDefaultLib)" /subsystem:$(CESubsystem) /align:"4096" /MACHINE:ARM
+
+!ELSEIF "$(CFG)" == "pjsua_wince - Win32 (WCE ARMV4) Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "../../build/wince-evc4/output/pjsua-wince-ARMV4Dbg"
+# PROP BASE Intermediate_Dir "../../build/wince-evc4/output/pjsua-wince-ARMV4Dbg"
+# PROP BASE CPU_ID "{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}"
+# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "../../build/wince-evc4/output/pjsua-wince-ARMV4Dbg"
+# PROP Intermediate_Dir "../../build/wince-evc4/output/pjsua-wince-ARMV4Dbg"
+# PROP CPU_ID "{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}"
+# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "DEBUG" /d "UNICODE" /d "_UNICODE" /d "$(CePlatform)" /d "ARM" /d "_ARM_" /d "ARMV4" /r
+# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "DEBUG" /d "UNICODE" /d "_UNICODE" /d "$(CePlatform)" /d "ARM" /d "_ARM_" /d "ARMV4" /r
+CPP=clarm.exe
+# ADD BASE CPP /nologo /W3 /Zi /Od /D "DEBUG" /D "ARM" /D "_ARM_" /D "ARMV4" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "UNICODE" /D "_UNICODE" /Yu"stdafx.h" /M$(CECrtMTDebug) /c
+# ADD CPP /nologo /W3 /Zi /Od /I "../../include" /I "../../../pjsip/include" /I "../../../pjlib-util/include" /I "../../../pjlib/include" /I "../../../pjmedia/include" /I "../../../pjnath/include" /D "DEBUG" /D "ARM" /D "_ARM_" /D "ARMV4" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "UNICODE" /D "_UNICODE" /Yu"stdafx.h" /M$(CECrtMTDebug) /c
+# SUBTRACT CPP /Fr
+MTL=midl.exe
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 commctrl.lib coredll.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /debug /nodefaultlib:"$(CENoDefaultLib)" /subsystem:$(CESubsystem) /align:"4096" /MACHINE:ARM
+# ADD LINK32 commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /debug /nodefaultlib:"$(CENoDefaultLib)" /subsystem:$(CESubsystem) /align:"4096" /MACHINE:ARM
+
+!ELSEIF "$(CFG)" == "pjsua_wince - Win32 (WCE ARMV4T) Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "../../build/wince-evc4/output/pjsua-wince-ARMV4TRel"
+# PROP BASE Intermediate_Dir "../../build/wince-evc4/output/pjsua-wince-ARMV4TRel"
+# PROP BASE CPU_ID "{F52316A9-3B7C-4FE7-A67F-68350B41240D}"
+# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "../../build/wince-evc4/output/pjsua-wince-ARMV4TRel"
+# PROP Intermediate_Dir "../../build/wince-evc4/output/pjsua-wince-ARMV4TRel"
+# PROP CPU_ID "{F52316A9-3B7C-4FE7-A67F-68350B41240D}"
+# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "NDEBUG" /d "$(CePlatform)" /d "THUMB" /d "_THUMB_" /d "ARM" /d "_ARM_" /d "ARMV4T" /r
+# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "NDEBUG" /d "$(CePlatform)" /d "THUMB" /d "_THUMB_" /d "ARM" /d "_ARM_" /d "ARMV4T" /r
+CPP=clthumb.exe
+# ADD BASE CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D "ARM" /D "_ARM_" /D "$(CePlatform)" /D "THUMB" /D "_THUMB_" /D "ARMV4T" /D UNDER_CE=$(CEVersion) /D "UNICODE" /D "_UNICODE" /D "NDEBUG" /Yu"stdafx.h" /QRarch4T /QRinterwork-return /O2 /M$(CECrtMT) /c
+# ADD CPP /nologo /W3 /I "../../include" /I "../../../pjsip/include" /I "../../../pjlib-util/include" /I "../../../pjlib/include" /I "../../../pjmedia/include" /I "../../../pjnath/include" /D _WIN32_WCE=$(CEVersion) /D "ARM" /D "_ARM_" /D "$(CePlatform)" /D "THUMB" /D "_THUMB_" /D "ARMV4T" /D UNDER_CE=$(CEVersion) /D "UNICODE" /D "_UNICODE" /D "NDEBUG" /Yu"stdafx.h" /QRarch4T /QRinterwork-return /O2 /M$(CECrtMT) /c
+# SUBTRACT CPP /Fr
+MTL=midl.exe
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 commctrl.lib coredll.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /nodefaultlib:"$(CENoDefaultLib)" /subsystem:$(CESubsystem) /MACHINE:THUMB
+# ADD LINK32 commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /nodefaultlib:"$(CENoDefaultLib)" /subsystem:$(CESubsystem) /MACHINE:THUMB
+
+!ELSEIF "$(CFG)" == "pjsua_wince - Win32 (WCE ARMV4T) Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "../../build/wince-evc4/output/pjsua-wince-ARMV4TDbg"
+# PROP BASE Intermediate_Dir "../../build/wince-evc4/output/pjsua-wince-ARMV4TDbg"
+# PROP BASE CPU_ID "{F52316A9-3B7C-4FE7-A67F-68350B41240D}"
+# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "../../build/wince-evc4/output/pjsua-wince-ARMV4TDbg"
+# PROP Intermediate_Dir "../../build/wince-evc4/output/pjsua-wince-ARMV4TDbg"
+# PROP CPU_ID "{F52316A9-3B7C-4FE7-A67F-68350B41240D}"
+# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "DEBUG" /d "$(CePlatform)" /d "THUMB" /d "_THUMB_" /d "ARM" /d "_ARM_" /d "ARMV4T" /r
+# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "DEBUG" /d "$(CePlatform)" /d "THUMB" /d "_THUMB_" /d "ARM" /d "_ARM_" /d "ARMV4T" /r
+CPP=clthumb.exe
+# ADD BASE CPP /nologo /W3 /Zi /Od /D "DEBUG" /D "THUMB" /D "_THUMB_" /D "ARMV4T" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "ARM" /D "_ARM_" /D "$(CePlatform)" /D "UNICODE" /D "_UNICODE" /Yu"stdafx.h" /QRarch4T /QRinterwork-return /M$(CECrtMTDebug) /c
+# ADD CPP /nologo /W3 /Zi /Od /I "../../include" /I "../../../pjsip/include" /I "../../../pjlib-util/include" /I "../../../pjlib/include" /I "../../../pjmedia/include" /I "../../../pjnath/include" /D "DEBUG" /D "THUMB" /D "_THUMB_" /D "ARMV4T" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "ARM" /D "_ARM_" /D "$(CePlatform)" /D "UNICODE" /D "_UNICODE" /Yu"stdafx.h" /QRarch4T /QRinterwork-return /M$(CECrtMTDebug) /c
+# SUBTRACT CPP /Fr
+MTL=midl.exe
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 commctrl.lib coredll.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /debug /nodefaultlib:"$(CENoDefaultLib)" /subsystem:$(CESubsystem) /MACHINE:THUMB
+# ADD LINK32 commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /debug /nodefaultlib:"$(CENoDefaultLib)" /subsystem:$(CESubsystem) /MACHINE:THUMB
+
+!ELSEIF "$(CFG)" == "pjsua_wince - Win32 (WCE x86) Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "../../build/wince-evc4/output/pjsua-wince-X86Rel"
+# PROP BASE Intermediate_Dir "../../build/wince-evc4/output/pjsua-wince-X86Rel"
+# PROP BASE CPU_ID "{D6518FF3-710F-11D3-99F2-00105A0DF099}"
+# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "../../build/wince-evc4/output/pjsua-wince-X86Rel"
+# PROP Intermediate_Dir "../../build/wince-evc4/output/pjsua-wince-X86Rel"
+# PROP CPU_ID "{D6518FF3-710F-11D3-99F2-00105A0DF099}"
+# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "NDEBUG" /d "$(CePlatform)" /d "_X86_" /d "x86" /d "_i386_" /r
+# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "NDEBUG" /d "$(CePlatform)" /d "_X86_" /d "x86" /d "_i386_" /r
+CPP=cl.exe
+# ADD BASE CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "_i386_" /D UNDER_CE=$(CEVersion) /D "i_386_" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /D "NDEBUG" /Yu"stdafx.h" /Gs8192 /GF /O2 /c
+# ADD CPP /nologo /W3 /I "../../include" /I "../../../pjsip/include" /I "../../../pjlib-util/include" /I "../../../pjlib/include" /I "../../../pjmedia/include" /I "../../../pjnath/include" /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "_i386_" /D UNDER_CE=$(CEVersion) /D "i_386_" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /D "NDEBUG" /Yu"stdafx.h" /Gs8192 /GF /O2 /c
+# SUBTRACT CPP /Fr
+MTL=midl.exe
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 commctrl.lib coredll.lib $(CEx86Corelibc) /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /nodefaultlib:"OLDNAMES.lib" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86
+# ADD LINK32 $(CEx86Corelibc) commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /nodefaultlib:"OLDNAMES.lib" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86
+
+!ELSEIF "$(CFG)" == "pjsua_wince - Win32 (WCE x86) Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "../../build/wince-evc4/output/pjsua-wince-X86Dbg"
+# PROP BASE Intermediate_Dir "../../build/wince-evc4/output/pjsua-wince-X86Dbg"
+# PROP BASE CPU_ID "{D6518FF3-710F-11D3-99F2-00105A0DF099}"
+# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "../../build/wince-evc4/output/pjsua-wince-X86Dbg"
+# PROP Intermediate_Dir "../../build/wince-evc4/output/pjsua-wince-X86Dbg"
+# PROP CPU_ID "{D6518FF3-710F-11D3-99F2-00105A0DF099}"
+# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d "$(CePlatform)" /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "DEBUG" /d "_X86_" /d "x86" /d "_i386_" /r
+# ADD RSC /l 0x409 /d "$(CePlatform)" /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "DEBUG" /d "_X86_" /d "x86" /d "_i386_" /r
+CPP=cl.exe
+# ADD BASE CPP /nologo /W3 /Zi /Od /D "DEBUG" /D "_i386_" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "i_386_" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /Yu"stdafx.h" /Gs8192 /GF /c
+# ADD CPP /nologo /W3 /Zi /Od /I "../../include" /I "../../../pjsip/include" /I "../../../pjlib-util/include" /I "../../../pjlib/include" /I "../../../pjmedia/include" /I "../../../pjnath/include" /D "DEBUG" /D "_i386_" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "i_386_" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /Yu"stdafx.h" /Gs8192 /GF /c
+# SUBTRACT CPP /Fr
+MTL=midl.exe
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 commctrl.lib coredll.lib $(CEx86Corelibc) /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /debug /nodefaultlib:"OLDNAMES.lib" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86
+# ADD LINK32 $(CEx86Corelibc) commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /debug /nodefaultlib:"OLDNAMES.lib" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86
+
+!ENDIF
+
+# Begin Target
+
+# Name "pjsua_wince - Win32 (WCE emulator) Release"
+# Name "pjsua_wince - Win32 (WCE emulator) Debug"
+# Name "pjsua_wince - Win32 (WCE ARMV4I) Release"
+# Name "pjsua_wince - Win32 (WCE ARMV4I) Debug"
+# Name "pjsua_wince - Win32 (WCE ARMV4) Release"
+# Name "pjsua_wince - Win32 (WCE ARMV4) Debug"
+# Name "pjsua_wince - Win32 (WCE ARMV4T) Release"
+# Name "pjsua_wince - Win32 (WCE ARMV4T) Debug"
+# Name "pjsua_wince - Win32 (WCE x86) Release"
+# Name "pjsua_wince - Win32 (WCE x86) Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\pjsua_wince.cpp
+
+!IF "$(CFG)" == "pjsua_wince - Win32 (WCE emulator) Release"
+
+DEP_CPP_PJSUA=\
+ ".\pjsua_wince.h"\
+ ".\StdAfx.h"\
+
+
+!ELSEIF "$(CFG)" == "pjsua_wince - Win32 (WCE emulator) Debug"
+
+DEP_CPP_PJSUA=\
+ "..\..\..\pjlib-util\include\pjlib-util.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\base64.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\config.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\crc32.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\dns.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\dns_server.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\errno.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\getopt.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\hmac_md5.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\hmac_sha1.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\md5.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\pcap.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\resolver.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\scanner.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\scanner_cis_bitwise.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\scanner_cis_uint.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\sha1.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\srv_resolver.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\stun_simple.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\types.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\xml.h"\
+ "..\..\..\pjlib\include\pj\activesock.h"\
+ "..\..\..\pjlib\include\pj\addr_resolv.h"\
+ "..\..\..\pjlib\include\pj\array.h"\
+ "..\..\..\pjlib\include\pj\assert.h"\
+ "..\..\..\pjlib\include\pj\compat\assert.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_armcc.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_codew.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_gcce.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_mwcc.h"\
+ "..\..\..\pjlib\include\pj\compat\ctype.h"\
+ "..\..\..\pjlib\include\pj\compat\errno.h"\
+ "..\..\..\pjlib\include\pj\compat\high_precision.h"\
+ "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\
+ "..\..\..\pjlib\include\pj\compat\os_linux.h"\
+ "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\
+ "..\..\..\pjlib\include\pj\compat\os_palmos.h"\
+ "..\..\..\pjlib\include\pj\compat\os_rtems.h"\
+ "..\..\..\pjlib\include\pj\compat\os_sunos.h"\
+ "..\..\..\pjlib\include\pj\compat\os_symbian.h"\
+ "..\..\..\pjlib\include\pj\compat\os_win32.h"\
+ "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\
+ "..\..\..\pjlib\include\pj\compat\setjmp.h"\
+ "..\..\..\pjlib\include\pj\compat\size_t.h"\
+ "..\..\..\pjlib\include\pj\compat\stdarg.h"\
+ "..\..\..\pjlib\include\pj\compat\string.h"\
+ "..\..\..\pjlib\include\pj\config.h"\
+ "..\..\..\pjlib\include\pj\config_site.h"\
+ "..\..\..\pjlib\include\pj\config_site_sample.h"\
+ "..\..\..\pjlib\include\pj\ctype.h"\
+ "..\..\..\pjlib\include\pj\errno.h"\
+ "..\..\..\pjlib\include\pj\except.h"\
+ "..\..\..\pjlib\include\pj\fifobuf.h"\
+ "..\..\..\pjlib\include\pj\file_access.h"\
+ "..\..\..\pjlib\include\pj\file_io.h"\
+ "..\..\..\pjlib\include\pj\guid.h"\
+ "..\..\..\pjlib\include\pj\hash.h"\
+ "..\..\..\pjlib\include\pj\ioqueue.h"\
+ "..\..\..\pjlib\include\pj\ip_helper.h"\
+ "..\..\..\pjlib\include\pj\list.h"\
+ "..\..\..\pjlib\include\pj\list_i.h"\
+ "..\..\..\pjlib\include\pj\lock.h"\
+ "..\..\..\pjlib\include\pj\log.h"\
+ "..\..\..\pjlib\include\pj\math.h"\
+ "..\..\..\pjlib\include\pj\os.h"\
+ "..\..\..\pjlib\include\pj\pool.h"\
+ "..\..\..\pjlib\include\pj\pool_alt.h"\
+ "..\..\..\pjlib\include\pj\pool_buf.h"\
+ "..\..\..\pjlib\include\pj\pool_i.h"\
+ "..\..\..\pjlib\include\pj\rand.h"\
+ "..\..\..\pjlib\include\pj\rbtree.h"\
+ "..\..\..\pjlib\include\pj\sock.h"\
+ "..\..\..\pjlib\include\pj\sock_select.h"\
+ "..\..\..\pjlib\include\pj\string.h"\
+ "..\..\..\pjlib\include\pj\string_i.h"\
+ "..\..\..\pjlib\include\pj\timer.h"\
+ "..\..\..\pjlib\include\pj\types.h"\
+ "..\..\..\pjlib\include\pj\unicode.h"\
+ "..\..\..\pjlib\include\pjlib.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\config.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\g722.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\gsm.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\ilbc.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\l16.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\speex.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\types.h"\
+ "..\..\..\pjmedia\include\pjmedia.h"\
+ "..\..\..\pjmedia\include\pjmedia\alaw_ulaw.h"\
+ "..\..\..\pjmedia\include\pjmedia\bidirectional.h"\
+ "..\..\..\pjmedia\include\pjmedia\clock.h"\
+ "..\..\..\pjmedia\include\pjmedia\codec.h"\
+ "..\..\..\pjmedia\include\pjmedia\conference.h"\
+ "..\..\..\pjmedia\include\pjmedia\config.h"\
+ "..\..\..\pjmedia\include\pjmedia\echo.h"\
+ "..\..\..\pjmedia\include\pjmedia\echo_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\endpoint.h"\
+ "..\..\..\pjmedia\include\pjmedia\errno.h"\
+ "..\..\..\pjmedia\include\pjmedia\g711.h"\
+ "..\..\..\pjmedia\include\pjmedia\jbuf.h"\
+ "..\..\..\pjmedia\include\pjmedia\master_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\mem_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\null_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\plc.h"\
+ "..\..\..\pjmedia\include\pjmedia\port.h"\
+ "..\..\..\pjmedia\include\pjmedia\resample.h"\
+ "..\..\..\pjmedia\include\pjmedia\rtcp.h"\
+ "..\..\..\pjmedia\include\pjmedia\rtcp_xr.h"\
+ "..\..\..\pjmedia\include\pjmedia\rtp.h"\
+ "..\..\..\pjmedia\include\pjmedia\sdp.h"\
+ "..\..\..\pjmedia\include\pjmedia\sdp_neg.h"\
+ "..\..\..\pjmedia\include\pjmedia\session.h"\
+ "..\..\..\pjmedia\include\pjmedia\silencedet.h"\
+ "..\..\..\pjmedia\include\pjmedia\sound.h"\
+ "..\..\..\pjmedia\include\pjmedia\sound_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\splitcomb.h"\
+ "..\..\..\pjmedia\include\pjmedia\stereo.h"\
+ "..\..\..\pjmedia\include\pjmedia\stream.h"\
+ "..\..\..\pjmedia\include\pjmedia\tonegen.h"\
+ "..\..\..\pjmedia\include\pjmedia\transport.h"\
+ "..\..\..\pjmedia\include\pjmedia\transport_ice.h"\
+ "..\..\..\pjmedia\include\pjmedia\transport_srtp.h"\
+ "..\..\..\pjmedia\include\pjmedia\transport_udp.h"\
+ "..\..\..\pjmedia\include\pjmedia\types.h"\
+ "..\..\..\pjmedia\include\pjmedia\wav_playlist.h"\
+ "..\..\..\pjmedia\include\pjmedia\wav_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\wave.h"\
+ "..\..\..\pjnath\include\pjnath.h"\
+ "..\..\..\pjnath\include\pjnath\config.h"\
+ "..\..\..\pjnath\include\pjnath\errno.h"\
+ "..\..\..\pjnath\include\pjnath\ice_session.h"\
+ "..\..\..\pjnath\include\pjnath\ice_strans.h"\
+ "..\..\..\pjnath\include\pjnath\nat_detect.h"\
+ "..\..\..\pjnath\include\pjnath\stun_auth.h"\
+ "..\..\..\pjnath\include\pjnath\stun_config.h"\
+ "..\..\..\pjnath\include\pjnath\stun_msg.h"\
+ "..\..\..\pjnath\include\pjnath\stun_session.h"\
+ "..\..\..\pjnath\include\pjnath\stun_sock.h"\
+ "..\..\..\pjnath\include\pjnath\stun_transaction.h"\
+ "..\..\..\pjnath\include\pjnath\turn_session.h"\
+ "..\..\..\pjnath\include\pjnath\turn_sock.h"\
+ "..\..\..\pjnath\include\pjnath\types.h"\
+ "..\..\..\pjsip\include\pjsip-simple\evsub.h"\
+ "..\..\..\pjsip\include\pjsip-simple\iscomposing.h"\
+ "..\..\..\pjsip\include\pjsip-simple\pidf.h"\
+ "..\..\..\pjsip\include\pjsip-simple\presence.h"\
+ "..\..\..\pjsip\include\pjsip-simple\publish.h"\
+ "..\..\..\pjsip\include\pjsip-simple\rpid.h"\
+ "..\..\..\pjsip\include\pjsip-simple\types.h"\
+ "..\..\..\pjsip\include\pjsip-simple\xpidf.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_100rel.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_inv.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_regc.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_replaces.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_xfer.h"\
+ "..\..\..\pjsip\include\pjsip.h"\
+ "..\..\..\pjsip\include\pjsip\sip_auth.h"\
+ "..\..\..\pjsip\include\pjsip\sip_auth_aka.h"\
+ "..\..\..\pjsip\include\pjsip\sip_auth_msg.h"\
+ "..\..\..\pjsip\include\pjsip\sip_config.h"\
+ "..\..\..\pjsip\include\pjsip\sip_dialog.h"\
+ "..\..\..\pjsip\include\pjsip\sip_endpoint.h"\
+ "..\..\..\pjsip\include\pjsip\sip_errno.h"\
+ "..\..\..\pjsip\include\pjsip\sip_event.h"\
+ "..\..\..\pjsip\include\pjsip\sip_module.h"\
+ "..\..\..\pjsip\include\pjsip\sip_msg.h"\
+ "..\..\..\pjsip\include\pjsip\sip_parser.h"\
+ "..\..\..\pjsip\include\pjsip\sip_resolve.h"\
+ "..\..\..\pjsip\include\pjsip\sip_tel_uri.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transaction.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport_loop.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport_tcp.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport_tls.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport_udp.h"\
+ "..\..\..\pjsip\include\pjsip\sip_types.h"\
+ "..\..\..\pjsip\include\pjsip\sip_ua_layer.h"\
+ "..\..\..\pjsip\include\pjsip\sip_uri.h"\
+ "..\..\..\pjsip\include\pjsip\sip_util.h"\
+ "..\..\..\pjsip\include\pjsip_simple.h"\
+ "..\..\..\pjsip\include\pjsip_ua.h"\
+ "..\..\..\pjsip\include\pjsua-lib\pjsua.h"\
+ ".\pjsua_wince.h"\
+ ".\StdAfx.h"\
+
+
+!ELSEIF "$(CFG)" == "pjsua_wince - Win32 (WCE ARMV4I) Release"
+
+DEP_CPP_PJSUA=\
+ ".\pjsua_wince.h"\
+ ".\StdAfx.h"\
+
+
+!ELSEIF "$(CFG)" == "pjsua_wince - Win32 (WCE ARMV4I) Debug"
+
+DEP_CPP_PJSUA=\
+ ".\pjsua_wince.h"\
+ ".\StdAfx.h"\
+
+
+!ELSEIF "$(CFG)" == "pjsua_wince - Win32 (WCE ARMV4) Release"
+
+DEP_CPP_PJSUA=\
+ "..\..\..\pjlib-util\include\pjlib-util.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\errno.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\getopt.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\md5.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\scanner.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\scanner_cis_bitwise.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\scanner_cis_uint.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\xml.h"\
+ "..\..\..\pjlib\include\pj\addr_resolv.h"\
+ "..\..\..\pjlib\include\pj\array.h"\
+ "..\..\..\pjlib\include\pj\assert.h"\
+ "..\..\..\pjlib\include\pj\compat\assert.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\
+ "..\..\..\pjlib\include\pj\compat\ctype.h"\
+ "..\..\..\pjlib\include\pj\compat\errno.h"\
+ "..\..\..\pjlib\include\pj\compat\high_precision.h"\
+ "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\
+ "..\..\..\pjlib\include\pj\compat\os_linux.h"\
+ "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\
+ "..\..\..\pjlib\include\pj\compat\os_palmos.h"\
+ "..\..\..\pjlib\include\pj\compat\os_rtems.h"\
+ "..\..\..\pjlib\include\pj\compat\os_sunos.h"\
+ "..\..\..\pjlib\include\pj\compat\os_win32.h"\
+ "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\
+ "..\..\..\pjlib\include\pj\compat\setjmp.h"\
+ "..\..\..\pjlib\include\pj\compat\size_t.h"\
+ "..\..\..\pjlib\include\pj\compat\string.h"\
+ "..\..\..\pjlib\include\pj\config.h"\
+ "..\..\..\pjlib\include\pj\config_site.h"\
+ "..\..\..\pjlib\include\pj\ctype.h"\
+ "..\..\..\pjlib\include\pj\errno.h"\
+ "..\..\..\pjlib\include\pj\except.h"\
+ "..\..\..\pjlib\include\pj\fifobuf.h"\
+ "..\..\..\pjlib\include\pj\file_access.h"\
+ "..\..\..\pjlib\include\pj\file_io.h"\
+ "..\..\..\pjlib\include\pj\guid.h"\
+ "..\..\..\pjlib\include\pj\hash.h"\
+ "..\..\..\pjlib\include\pj\ioqueue.h"\
+ "..\..\..\pjlib\include\pj\list.h"\
+ "..\..\..\pjlib\include\pj\list_i.h"\
+ "..\..\..\pjlib\include\pj\lock.h"\
+ "..\..\..\pjlib\include\pj\log.h"\
+ "..\..\..\pjlib\include\pj\os.h"\
+ "..\..\..\pjlib\include\pj\pool.h"\
+ "..\..\..\pjlib\include\pj\pool_alt.h"\
+ "..\..\..\pjlib\include\pj\pool_i.h"\
+ "..\..\..\pjlib\include\pj\rand.h"\
+ "..\..\..\pjlib\include\pj\rbtree.h"\
+ "..\..\..\pjlib\include\pj\sock.h"\
+ "..\..\..\pjlib\include\pj\sock_select.h"\
+ "..\..\..\pjlib\include\pj\string.h"\
+ "..\..\..\pjlib\include\pj\string_i.h"\
+ "..\..\..\pjlib\include\pj\timer.h"\
+ "..\..\..\pjlib\include\pj\types.h"\
+ "..\..\..\pjlib\include\pj\unicode.h"\
+ "..\..\..\pjlib\include\pjlib.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\config.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\gsm.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\ilbc.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\l16.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\speex.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\types.h"\
+ "..\..\..\pjmedia\include\pjmedia.h"\
+ "..\..\..\pjmedia\include\pjmedia\clock.h"\
+ "..\..\..\pjmedia\include\pjmedia\codec.h"\
+ "..\..\..\pjmedia\include\pjmedia\conference.h"\
+ "..\..\..\pjmedia\include\pjmedia\config.h"\
+ "..\..\..\pjmedia\include\pjmedia\endpoint.h"\
+ "..\..\..\pjmedia\include\pjmedia\errno.h"\
+ "..\..\..\pjmedia\include\pjmedia\g711.h"\
+ "..\..\..\pjmedia\include\pjmedia\jbuf.h"\
+ "..\..\..\pjmedia\include\pjmedia\master_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\mem_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\null_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\plc.h"\
+ "..\..\..\pjmedia\include\pjmedia\port.h"\
+ "..\..\..\pjmedia\include\pjmedia\resample.h"\
+ "..\..\..\pjmedia\include\pjmedia\rtcp.h"\
+ "..\..\..\pjmedia\include\pjmedia\rtp.h"\
+ "..\..\..\pjmedia\include\pjmedia\sdp.h"\
+ "..\..\..\pjmedia\include\pjmedia\sdp_neg.h"\
+ "..\..\..\pjmedia\include\pjmedia\session.h"\
+ "..\..\..\pjmedia\include\pjmedia\silencedet.h"\
+ "..\..\..\pjmedia\include\pjmedia\sound.h"\
+ "..\..\..\pjmedia\include\pjmedia\sound_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\splitcomb.h"\
+ "..\..\..\pjmedia\include\pjmedia\stream.h"\
+ "..\..\..\pjmedia\include\pjmedia\transport.h"\
+ "..\..\..\pjmedia\include\pjmedia\transport_udp.h"\
+ "..\..\..\pjmedia\include\pjmedia\types.h"\
+ "..\..\..\pjmedia\include\pjmedia\wav_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\wave.h"\
+ "..\..\..\pjsip\include\pjsip-simple\evsub.h"\
+ "..\..\..\pjsip\include\pjsip-simple\iscomposing.h"\
+ "..\..\..\pjsip\include\pjsip-simple\pidf.h"\
+ "..\..\..\pjsip\include\pjsip-simple\presence.h"\
+ "..\..\..\pjsip\include\pjsip-simple\types.h"\
+ "..\..\..\pjsip\include\pjsip-simple\xpidf.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_inv.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_regc.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_xfer.h"\
+ "..\..\..\pjsip\include\pjsip.h"\
+ "..\..\..\pjsip\include\pjsip\sip_auth.h"\
+ "..\..\..\pjsip\include\pjsip\sip_auth_msg.h"\
+ "..\..\..\pjsip\include\pjsip\sip_config.h"\
+ "..\..\..\pjsip\include\pjsip\sip_dialog.h"\
+ "..\..\..\pjsip\include\pjsip\sip_endpoint.h"\
+ "..\..\..\pjsip\include\pjsip\sip_errno.h"\
+ "..\..\..\pjsip\include\pjsip\sip_event.h"\
+ "..\..\..\pjsip\include\pjsip\sip_module.h"\
+ "..\..\..\pjsip\include\pjsip\sip_msg.h"\
+ "..\..\..\pjsip\include\pjsip\sip_parser.h"\
+ "..\..\..\pjsip\include\pjsip\sip_resolve.h"\
+ "..\..\..\pjsip\include\pjsip\sip_tel_uri.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transaction.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport_loop.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport_tcp.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport_udp.h"\
+ "..\..\..\pjsip\include\pjsip\sip_types.h"\
+ "..\..\..\pjsip\include\pjsip\sip_ua_layer.h"\
+ "..\..\..\pjsip\include\pjsip\sip_uri.h"\
+ "..\..\..\pjsip\include\pjsip\sip_util.h"\
+ "..\..\..\pjsip\include\pjsip_simple.h"\
+ "..\..\..\pjsip\include\pjsip_ua.h"\
+ "..\..\..\pjsip\include\pjsua-lib\pjsua.h"\
+ ".\pjsua_wince.h"\
+ ".\StdAfx.h"\
+
+NODEP_CPP_PJSUA=\
+ "..\..\..\pjlib-util\include\pjlib-util\stun.h"\
+
+
+!ELSEIF "$(CFG)" == "pjsua_wince - Win32 (WCE ARMV4) Debug"
+
+DEP_CPP_PJSUA=\
+ "..\..\..\pjlib-util\include\pjlib-util.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\config.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\crc32.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\dns.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\errno.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\getopt.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\hmac_md5.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\hmac_sha1.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\md5.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\resolver.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\scanner.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\scanner_cis_bitwise.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\scanner_cis_uint.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\sha1.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\srv_resolver.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\stun_simple.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\types.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\xml.h"\
+ "..\..\..\pjlib\include\pj\addr_resolv.h"\
+ "..\..\..\pjlib\include\pj\array.h"\
+ "..\..\..\pjlib\include\pj\assert.h"\
+ "..\..\..\pjlib\include\pj\compat\assert.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\
+ "..\..\..\pjlib\include\pj\compat\ctype.h"\
+ "..\..\..\pjlib\include\pj\compat\errno.h"\
+ "..\..\..\pjlib\include\pj\compat\high_precision.h"\
+ "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\
+ "..\..\..\pjlib\include\pj\compat\os_linux.h"\
+ "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\
+ "..\..\..\pjlib\include\pj\compat\os_palmos.h"\
+ "..\..\..\pjlib\include\pj\compat\os_rtems.h"\
+ "..\..\..\pjlib\include\pj\compat\os_sunos.h"\
+ "..\..\..\pjlib\include\pj\compat\os_win32.h"\
+ "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\
+ "..\..\..\pjlib\include\pj\compat\setjmp.h"\
+ "..\..\..\pjlib\include\pj\compat\size_t.h"\
+ "..\..\..\pjlib\include\pj\compat\string.h"\
+ "..\..\..\pjlib\include\pj\config.h"\
+ "..\..\..\pjlib\include\pj\config_site.h"\
+ "..\..\..\pjlib\include\pj\config_site_sample.h"\
+ "..\..\..\pjlib\include\pj\ctype.h"\
+ "..\..\..\pjlib\include\pj\errno.h"\
+ "..\..\..\pjlib\include\pj\except.h"\
+ "..\..\..\pjlib\include\pj\fifobuf.h"\
+ "..\..\..\pjlib\include\pj\file_access.h"\
+ "..\..\..\pjlib\include\pj\file_io.h"\
+ "..\..\..\pjlib\include\pj\guid.h"\
+ "..\..\..\pjlib\include\pj\hash.h"\
+ "..\..\..\pjlib\include\pj\ioqueue.h"\
+ "..\..\..\pjlib\include\pj\ip_helper.h"\
+ "..\..\..\pjlib\include\pj\list.h"\
+ "..\..\..\pjlib\include\pj\list_i.h"\
+ "..\..\..\pjlib\include\pj\lock.h"\
+ "..\..\..\pjlib\include\pj\log.h"\
+ "..\..\..\pjlib\include\pj\os.h"\
+ "..\..\..\pjlib\include\pj\pool.h"\
+ "..\..\..\pjlib\include\pj\pool_alt.h"\
+ "..\..\..\pjlib\include\pj\pool_buf.h"\
+ "..\..\..\pjlib\include\pj\pool_i.h"\
+ "..\..\..\pjlib\include\pj\rand.h"\
+ "..\..\..\pjlib\include\pj\rbtree.h"\
+ "..\..\..\pjlib\include\pj\sock.h"\
+ "..\..\..\pjlib\include\pj\sock_select.h"\
+ "..\..\..\pjlib\include\pj\string.h"\
+ "..\..\..\pjlib\include\pj\string_i.h"\
+ "..\..\..\pjlib\include\pj\timer.h"\
+ "..\..\..\pjlib\include\pj\types.h"\
+ "..\..\..\pjlib\include\pj\unicode.h"\
+ "..\..\..\pjlib\include\pjlib.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\config.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\gsm.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\ilbc.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\l16.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\speex.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\types.h"\
+ "..\..\..\pjmedia\include\pjmedia.h"\
+ "..\..\..\pjmedia\include\pjmedia\alaw_ulaw.h"\
+ "..\..\..\pjmedia\include\pjmedia\bidirectional.h"\
+ "..\..\..\pjmedia\include\pjmedia\clock.h"\
+ "..\..\..\pjmedia\include\pjmedia\codec.h"\
+ "..\..\..\pjmedia\include\pjmedia\conference.h"\
+ "..\..\..\pjmedia\include\pjmedia\config.h"\
+ "..\..\..\pjmedia\include\pjmedia\echo.h"\
+ "..\..\..\pjmedia\include\pjmedia\echo_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\endpoint.h"\
+ "..\..\..\pjmedia\include\pjmedia\errno.h"\
+ "..\..\..\pjmedia\include\pjmedia\g711.h"\
+ "..\..\..\pjmedia\include\pjmedia\jbuf.h"\
+ "..\..\..\pjmedia\include\pjmedia\master_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\mem_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\null_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\plc.h"\
+ "..\..\..\pjmedia\include\pjmedia\port.h"\
+ "..\..\..\pjmedia\include\pjmedia\resample.h"\
+ "..\..\..\pjmedia\include\pjmedia\rtcp.h"\
+ "..\..\..\pjmedia\include\pjmedia\rtp.h"\
+ "..\..\..\pjmedia\include\pjmedia\sdp.h"\
+ "..\..\..\pjmedia\include\pjmedia\sdp_neg.h"\
+ "..\..\..\pjmedia\include\pjmedia\session.h"\
+ "..\..\..\pjmedia\include\pjmedia\silencedet.h"\
+ "..\..\..\pjmedia\include\pjmedia\sound.h"\
+ "..\..\..\pjmedia\include\pjmedia\sound_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\splitcomb.h"\
+ "..\..\..\pjmedia\include\pjmedia\stream.h"\
+ "..\..\..\pjmedia\include\pjmedia\tonegen.h"\
+ "..\..\..\pjmedia\include\pjmedia\transport.h"\
+ "..\..\..\pjmedia\include\pjmedia\transport_ice.h"\
+ "..\..\..\pjmedia\include\pjmedia\transport_udp.h"\
+ "..\..\..\pjmedia\include\pjmedia\types.h"\
+ "..\..\..\pjmedia\include\pjmedia\wav_playlist.h"\
+ "..\..\..\pjmedia\include\pjmedia\wav_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\wave.h"\
+ "..\..\..\pjnath\include\pjnath\config.h"\
+ "..\..\..\pjnath\include\pjnath\ice_session.h"\
+ "..\..\..\pjnath\include\pjnath\ice_strans.h"\
+ "..\..\..\pjnath\include\pjnath\stun_auth.h"\
+ "..\..\..\pjnath\include\pjnath\stun_config.h"\
+ "..\..\..\pjnath\include\pjnath\stun_msg.h"\
+ "..\..\..\pjnath\include\pjnath\stun_session.h"\
+ "..\..\..\pjnath\include\pjnath\stun_transaction.h"\
+ "..\..\..\pjnath\include\pjnath\types.h"\
+ "..\..\..\pjsip\include\pjsip-simple\evsub.h"\
+ "..\..\..\pjsip\include\pjsip-simple\iscomposing.h"\
+ "..\..\..\pjsip\include\pjsip-simple\pidf.h"\
+ "..\..\..\pjsip\include\pjsip-simple\presence.h"\
+ "..\..\..\pjsip\include\pjsip-simple\publish.h"\
+ "..\..\..\pjsip\include\pjsip-simple\types.h"\
+ "..\..\..\pjsip\include\pjsip-simple\xpidf.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_inv.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_regc.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_replaces.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_xfer.h"\
+ "..\..\..\pjsip\include\pjsip.h"\
+ "..\..\..\pjsip\include\pjsip\sip_auth.h"\
+ "..\..\..\pjsip\include\pjsip\sip_auth_msg.h"\
+ "..\..\..\pjsip\include\pjsip\sip_config.h"\
+ "..\..\..\pjsip\include\pjsip\sip_dialog.h"\
+ "..\..\..\pjsip\include\pjsip\sip_endpoint.h"\
+ "..\..\..\pjsip\include\pjsip\sip_errno.h"\
+ "..\..\..\pjsip\include\pjsip\sip_event.h"\
+ "..\..\..\pjsip\include\pjsip\sip_module.h"\
+ "..\..\..\pjsip\include\pjsip\sip_msg.h"\
+ "..\..\..\pjsip\include\pjsip\sip_parser.h"\
+ "..\..\..\pjsip\include\pjsip\sip_resolve.h"\
+ "..\..\..\pjsip\include\pjsip\sip_tel_uri.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transaction.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport_loop.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport_tcp.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport_tls.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport_udp.h"\
+ "..\..\..\pjsip\include\pjsip\sip_types.h"\
+ "..\..\..\pjsip\include\pjsip\sip_ua_layer.h"\
+ "..\..\..\pjsip\include\pjsip\sip_uri.h"\
+ "..\..\..\pjsip\include\pjsip\sip_util.h"\
+ "..\..\..\pjsip\include\pjsip_simple.h"\
+ "..\..\..\pjsip\include\pjsip_ua.h"\
+ "..\..\..\pjsip\include\pjsua-lib\pjsua.h"\
+ ".\pjsua_wince.h"\
+ ".\StdAfx.h"\
+
+NODEP_CPP_PJSUA=\
+ "..\..\..\pjlib\include\pj\compat\m_auto.h"\
+ "..\..\..\pjlib\include\pj\compat\os_auto.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\config_auto.h"\
+ "..\..\..\pjmedia\include\pjmedia\config_auto.h"\
+ "..\..\..\pjmedia\include\pjmedia\mp3_port.h"\
+ "..\..\..\pjsip\include\pjsip\sip_autoconf.h"\
+
+
+!ELSEIF "$(CFG)" == "pjsua_wince - Win32 (WCE ARMV4T) Release"
+
+DEP_CPP_PJSUA=\
+ ".\pjsua_wince.h"\
+ ".\StdAfx.h"\
+
+
+!ELSEIF "$(CFG)" == "pjsua_wince - Win32 (WCE ARMV4T) Debug"
+
+DEP_CPP_PJSUA=\
+ ".\pjsua_wince.h"\
+ ".\StdAfx.h"\
+
+
+!ELSEIF "$(CFG)" == "pjsua_wince - Win32 (WCE x86) Release"
+
+DEP_CPP_PJSUA=\
+ ".\pjsua_wince.h"\
+ ".\StdAfx.h"\
+
+
+!ELSEIF "$(CFG)" == "pjsua_wince - Win32 (WCE x86) Debug"
+
+DEP_CPP_PJSUA=\
+ ".\pjsua_wince.h"\
+ ".\StdAfx.h"\
+
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\pjsua_wince.rc
+
+!IF "$(CFG)" == "pjsua_wince - Win32 (WCE emulator) Release"
+
+!ELSEIF "$(CFG)" == "pjsua_wince - Win32 (WCE emulator) Debug"
+
+!ELSEIF "$(CFG)" == "pjsua_wince - Win32 (WCE ARMV4I) Release"
+
+!ELSEIF "$(CFG)" == "pjsua_wince - Win32 (WCE ARMV4I) Debug"
+
+!ELSEIF "$(CFG)" == "pjsua_wince - Win32 (WCE ARMV4) Release"
+
+!ELSEIF "$(CFG)" == "pjsua_wince - Win32 (WCE ARMV4) Debug"
+
+!ELSEIF "$(CFG)" == "pjsua_wince - Win32 (WCE ARMV4T) Release"
+
+!ELSEIF "$(CFG)" == "pjsua_wince - Win32 (WCE ARMV4T) Debug"
+
+!ELSEIF "$(CFG)" == "pjsua_wince - Win32 (WCE x86) Release"
+
+!ELSEIF "$(CFG)" == "pjsua_wince - Win32 (WCE x86) Debug"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.cpp
+
+!IF "$(CFG)" == "pjsua_wince - Win32 (WCE emulator) Release"
+
+DEP_CPP_STDAF=\
+ ".\StdAfx.h"\
+
+# ADD CPP /Yc"stdafx.h"
+
+!ELSEIF "$(CFG)" == "pjsua_wince - Win32 (WCE emulator) Debug"
+
+DEP_CPP_STDAF=\
+ ".\StdAfx.h"\
+
+# ADD CPP /Yc"stdafx.h"
+
+!ELSEIF "$(CFG)" == "pjsua_wince - Win32 (WCE ARMV4I) Release"
+
+DEP_CPP_STDAF=\
+ ".\StdAfx.h"\
+
+# ADD CPP /Yc"stdafx.h"
+
+!ELSEIF "$(CFG)" == "pjsua_wince - Win32 (WCE ARMV4I) Debug"
+
+DEP_CPP_STDAF=\
+ ".\StdAfx.h"\
+
+# ADD CPP /Yc"stdafx.h"
+
+!ELSEIF "$(CFG)" == "pjsua_wince - Win32 (WCE ARMV4) Release"
+
+DEP_CPP_STDAF=\
+ ".\StdAfx.h"\
+
+# ADD CPP /Yc"stdafx.h"
+
+!ELSEIF "$(CFG)" == "pjsua_wince - Win32 (WCE ARMV4) Debug"
+
+DEP_CPP_STDAF=\
+ ".\StdAfx.h"\
+
+# ADD CPP /Yc"stdafx.h"
+
+!ELSEIF "$(CFG)" == "pjsua_wince - Win32 (WCE ARMV4T) Release"
+
+DEP_CPP_STDAF=\
+ ".\StdAfx.h"\
+
+# ADD CPP /Yc"stdafx.h"
+
+!ELSEIF "$(CFG)" == "pjsua_wince - Win32 (WCE ARMV4T) Debug"
+
+DEP_CPP_STDAF=\
+ ".\StdAfx.h"\
+
+# ADD CPP /Yc"stdafx.h"
+
+!ELSEIF "$(CFG)" == "pjsua_wince - Win32 (WCE x86) Release"
+
+DEP_CPP_STDAF=\
+ ".\StdAfx.h"\
+
+# ADD CPP /Yc"stdafx.h"
+
+!ELSEIF "$(CFG)" == "pjsua_wince - Win32 (WCE x86) Debug"
+
+DEP_CPP_STDAF=\
+ ".\StdAfx.h"\
+
+# ADD CPP /Yc"stdafx.h"
+
+!ENDIF
+
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\newres.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\pjsua_wince.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\resource.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\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=.\pjsua_wince.ico
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\ReadMe.txt
+# End Source File
+# End Target
+# End Project
diff --git a/pjsip-apps/src/pjsua_wince/pjsua_wince.vcproj b/pjsip-apps/src/pjsua_wince/pjsua_wince.vcproj
new file mode 100644
index 0000000..f330776
--- /dev/null
+++ b/pjsip-apps/src/pjsua_wince/pjsua_wince.vcproj
@@ -0,0 +1,3627 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="pjsua_wince"
+ ProjectGUID="{C014B29B-4A42-414B-B567-988469F032D8}"
+ RootNamespace="pjsua_wince"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="Windows Mobile 6 Professional SDK (ARMV4I)"
+ />
+ <Platform
+ Name="Windows Mobile 6 Standard SDK (ARMV4I)"
+ />
+ <Platform
+ Name="Pocket PC 2003 (ARMV4)"
+ />
+ <Platform
+ Name="Smartphone 2003 (ARMV4)"
+ />
+ <Platform
+ Name="Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ />
+ <Platform
+ Name="Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-win32-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../include,../../../pjsip/include,../../../pjlib-util/include,../../../pjlib/include,../../../pjmedia/include,../../../pjnath/include"
+ PreprocessorDefinitions="_CONSOLE;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\pjsua-wince-$(TargetCPU)-$(PlatformName)-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Windows Mobile 6 Professional SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm6-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../include,../../../pjsip/include,../../../pjlib-util/include,../../../pjlib/include,../../../pjmedia/include,../../../pjnath/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\pjsua-wince-$(TargetCPU)-wm6pro-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Windows Mobile 6 Standard SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm6-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../include,../../../pjsip/include,../../../pjlib-util/include,../../../pjlib/include,../../../pjmedia/include,../../../pjnath/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\pjsua-wince-$(TargetCPU)-wm6std-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Pocket PC 2003 (ARMV4)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm2003-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../include,../../../pjsip/include,../../../pjlib-util/include,../../../pjlib/include,../../../pjmedia/include,../../../pjnath/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\pjsua-wince-$(TargetCPU)-wm2003ppc-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Smartphone 2003 (ARMV4)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm2003-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../include,../../../pjsip/include,../../../pjlib-util/include,../../../pjlib/include,../../../pjmedia/include,../../../pjnath/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\pjsua-wince-$(TargetCPU)-wm2003sp-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm5-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../include,../../../pjsip/include,../../../pjlib-util/include,../../../pjlib/include,../../../pjmedia/include,../../../pjnath/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\pjsua-wince-$(TargetCPU)-wm5ppc-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm5-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../include,../../../pjsip/include,../../../pjlib-util/include,../../../pjlib/include,../../../pjmedia/include,../../../pjnath/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\pjsua-wince-$(TargetCPU)-wm5sp-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-win32-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../include,../../../pjsip/include,../../../pjlib-util/include,../../../pjlib/include,../../../pjmedia/include,../../../pjnath/include"
+ PreprocessorDefinitions="_CONSOLE;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\pjsua-wince-$(TargetCPU)-$(PlatformName)-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Windows Mobile 6 Professional SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm6-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../include,../../../pjsip/include,../../../pjlib-util/include,../../../pjlib/include,../../../pjmedia/include,../../../pjnath/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\pjsua-wince-$(TargetCPU)-wm6pro-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles="msvcr80.dll|$(BINDIR)\$(INSTRUCTIONSET)\|%CSIDL_PROGRAM_FILES%\$(ProjectName)|0;atl80.dll|$(BINDIR)\$(INSTRUCTIONSET)\|%CSIDL_PROGRAM_FILES%\$(ProjectName)|0;MFC80U.dll|$(BINDIR)\$(INSTRUCTIONSET)\|%CSIDL_PROGRAM_FILES%\$(ProjectName)|0;"
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Windows Mobile 6 Standard SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm6-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../include,../../../pjsip/include,../../../pjlib-util/include,../../../pjlib/include,../../../pjmedia/include,../../../pjnath/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\pjsua-wince-$(TargetCPU)-wm6std-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Pocket PC 2003 (ARMV4)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm2003-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../include,../../../pjsip/include,../../../pjlib-util/include,../../../pjlib/include,../../../pjmedia/include,../../../pjnath/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\pjsua-wince-$(TargetCPU)-wm2003ppc-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Smartphone 2003 (ARMV4)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm2003-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../include,../../../pjsip/include,../../../pjlib-util/include,../../../pjlib/include,../../../pjmedia/include,../../../pjnath/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\pjsua-wince-$(TargetCPU)-wm2003sp-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm5-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../include,../../../pjsip/include,../../../pjlib-util/include,../../../pjlib/include,../../../pjmedia/include,../../../pjnath/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\pjsua-wince-$(TargetCPU)-wm5ppc-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm5-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../include,../../../pjsip/include,../../../pjlib-util/include,../../../pjlib/include,../../../pjmedia/include,../../../pjnath/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\pjsua-wince-$(TargetCPU)-wm5sp-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Dynamic|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-debug-dynamic-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-win32-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../include,../../../pjsip/include,../../../pjlib-util/include,../../../pjlib/include,../../../pjmedia/include,../../../pjnath/include"
+ PreprocessorDefinitions="_CONSOLE;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\pjsua-wince-$(TargetCPU)-$(PlatformName)-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Dynamic|Windows Mobile 6 Professional SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-debug-dynamic-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm6-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../include,../../../pjsip/include,../../../pjlib-util/include,../../../pjlib/include,../../../pjmedia/include,../../../pjnath/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\pjsua-wince-$(TargetCPU)-wm6pro-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Dynamic|Windows Mobile 6 Standard SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-debug-dynamic-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm6-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../include,../../../pjsip/include,../../../pjlib-util/include,../../../pjlib/include,../../../pjmedia/include,../../../pjnath/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\pjsua-wince-$(TargetCPU)-wm6std-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Dynamic|Pocket PC 2003 (ARMV4)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-debug-dynamic-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm2003-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../include,../../../pjsip/include,../../../pjlib-util/include,../../../pjlib/include,../../../pjmedia/include,../../../pjnath/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\pjsua-wince-$(TargetCPU)-wm2003ppc-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Dynamic|Smartphone 2003 (ARMV4)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-debug-dynamic-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm2003-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../include,../../../pjsip/include,../../../pjlib-util/include,../../../pjlib/include,../../../pjmedia/include,../../../pjnath/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\pjsua-wince-$(TargetCPU)-wm2003sp-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Dynamic|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-debug-dynamic-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm5-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../include,../../../pjsip/include,../../../pjlib-util/include,../../../pjlib/include,../../../pjmedia/include,../../../pjnath/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\pjsua-wince-$(TargetCPU)-wm5ppc-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Dynamic|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-debug-dynamic-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm5-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../include,../../../pjsip/include,../../../pjlib-util/include,../../../pjlib/include,../../../pjmedia/include,../../../pjnath/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\pjsua-wince-$(TargetCPU)-wm5sp-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Static|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-win32-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../include,../../../pjsip/include,../../../pjlib-util/include,../../../pjlib/include,../../../pjmedia/include,../../../pjnath/include"
+ PreprocessorDefinitions="_CONSOLE;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\pjsua-wince-$(TargetCPU)-$(PlatformName)-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Static|Windows Mobile 6 Professional SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm6-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../include,../../../pjsip/include,../../../pjlib-util/include,../../../pjlib/include,../../../pjmedia/include,../../../pjnath/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\pjsua-wince-$(TargetCPU)-wm6pro-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Static|Windows Mobile 6 Standard SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm6-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../include,../../../pjsip/include,../../../pjlib-util/include,../../../pjlib/include,../../../pjmedia/include,../../../pjnath/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\pjsua-wince-$(TargetCPU)-wm6std-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Static|Pocket PC 2003 (ARMV4)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm2003-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../include,../../../pjsip/include,../../../pjlib-util/include,../../../pjlib/include,../../../pjmedia/include,../../../pjnath/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\pjsua-wince-$(TargetCPU)-wm2003ppc-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Static|Smartphone 2003 (ARMV4)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm2003-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../include,../../../pjsip/include,../../../pjlib-util/include,../../../pjlib/include,../../../pjmedia/include,../../../pjnath/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\pjsua-wince-$(TargetCPU)-wm2003sp-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Static|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm5-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../include,../../../pjsip/include,../../../pjlib-util/include,../../../pjlib/include,../../../pjmedia/include,../../../pjnath/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\pjsua-wince-$(TargetCPU)-wm5ppc-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Static|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm5-common-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../include,../../../pjsip/include,../../../pjlib-util/include,../../../pjlib/include,../../../pjmedia/include,../../../pjnath/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\pjsua-wince-$(TargetCPU)-wm5sp-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Dynamic|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-win32-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../include,../../../pjsip/include,../../../pjlib-util/include,../../../pjlib/include,../../../pjmedia/include,../../../pjnath/include"
+ PreprocessorDefinitions="_CONSOLE;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\pjsua-wince-$(TargetCPU)-$(PlatformName)-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Dynamic|Windows Mobile 6 Professional SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm6-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../include,../../../pjsip/include,../../../pjlib-util/include,../../../pjlib/include,../../../pjmedia/include,../../../pjnath/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\pjsua-wince-$(TargetCPU)-wm6pro-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Dynamic|Windows Mobile 6 Standard SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm6-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../include,../../../pjsip/include,../../../pjlib-util/include,../../../pjlib/include,../../../pjmedia/include,../../../pjnath/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\pjsua-wince-$(TargetCPU)-wm6std-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Dynamic|Pocket PC 2003 (ARMV4)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm2003-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../include,../../../pjsip/include,../../../pjlib-util/include,../../../pjlib/include,../../../pjmedia/include,../../../pjnath/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\pjsua-wince-$(TargetCPU)-wm2003ppc-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Dynamic|Smartphone 2003 (ARMV4)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm2003-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../include,../../../pjsip/include,../../../pjlib-util/include,../../../pjlib/include,../../../pjmedia/include,../../../pjnath/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\pjsua-wince-$(TargetCPU)-wm2003sp-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Dynamic|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm5-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../include,../../../pjsip/include,../../../pjlib-util/include,../../../pjlib/include,../../../pjmedia/include,../../../pjnath/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\pjsua-wince-$(TargetCPU)-wm5ppc-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Dynamic|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm5-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../include,../../../pjsip/include,../../../pjlib-util/include,../../../pjlib/include,../../../pjmedia/include,../../../pjnath/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\pjsua-wince-$(TargetCPU)-wm5sp-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Static|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-release-static-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-win32-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../include,../../../pjsip/include,../../../pjlib-util/include,../../../pjlib/include,../../../pjmedia/include,../../../pjnath/include"
+ PreprocessorDefinitions="_CONSOLE;"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\pjsua-wince-$(TargetCPU)-$(PlatformName)-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Static|Windows Mobile 6 Professional SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-release-static-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm6-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../include,../../../pjsip/include,../../../pjlib-util/include,../../../pjlib/include,../../../pjmedia/include,../../../pjnath/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\pjsua-wince-$(TargetCPU)-wm6pro-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Static|Windows Mobile 6 Standard SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-release-static-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm6-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../include,../../../pjsip/include,../../../pjlib-util/include,../../../pjlib/include,../../../pjmedia/include,../../../pjnath/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\pjsua-wince-$(TargetCPU)-wm6std-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Static|Pocket PC 2003 (ARMV4)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-release-static-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm2003-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../include,../../../pjsip/include,../../../pjlib-util/include,../../../pjlib/include,../../../pjmedia/include,../../../pjnath/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\pjsua-wince-$(TargetCPU)-wm2003ppc-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Static|Smartphone 2003 (ARMV4)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-release-static-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm2003-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../include,../../../pjsip/include,../../../pjlib-util/include,../../../pjlib/include,../../../pjmedia/include,../../../pjnath/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\pjsua-wince-$(TargetCPU)-wm2003sp-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Static|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-release-static-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm5-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../include,../../../pjsip/include,../../../pjlib-util/include,../../../pjlib/include,../../../pjmedia/include,../../../pjnath/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\pjsua-wince-$(TargetCPU)-wm5ppc-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Static|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ ConfigurationType="1"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-release-static-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm5-release-defaults.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../include,../../../pjsip/include,../../../pjlib-util/include,../../../pjlib/include,../../../pjmedia/include,../../../pjnath/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\pjsua-wince-$(TargetCPU)-wm5sp-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath="pjsua_wince.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="pjsua_wince.rc"
+ >
+ </File>
+ <File
+ RelativePath="StdAfx.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath="newres.h"
+ >
+ </File>
+ <File
+ RelativePath="pjsua_wince.h"
+ >
+ </File>
+ <File
+ RelativePath="resource.h"
+ >
+ </File>
+ <File
+ RelativePath="StdAfx.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+ >
+ <File
+ RelativePath="pjsua_wince.ico"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath="ReadMe.txt"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/pjsip-apps/src/pjsua_wince/resource.h b/pjsip-apps/src/pjsua_wince/resource.h
new file mode 100644
index 0000000..43e3888
--- /dev/null
+++ b/pjsip-apps/src/pjsua_wince/resource.h
@@ -0,0 +1,28 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft eMbedded Visual C++ generated include file.
+// Used by pjsua_wince.rc
+//
+#define IDS_APP_TITLE 1
+#define IDS_HELLO 2
+#define IDC_PJSUA_WINCE 3
+#define IDI_PJSUA_WINCE 101
+#define IDM_MENU 102
+#define IDD_ABOUTBOX 103
+#define IDM_FILE_EXIT 40002
+#define IDM_HELP_ABOUT 40003
+#define ID_MAKECALL 40004
+#define ID_ANSWER 40005
+#define ID_DISCONNECT 40006
+#define ID_ACTION 40007
+#define ID_EXIT 65535
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 104
+#define _APS_NEXT_COMMAND_VALUE 40008
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/pjsip-apps/src/pjsystest/gui.h b/pjsip-apps/src/pjsystest/gui.h
new file mode 100644
index 0000000..ae7d8f4
--- /dev/null
+++ b/pjsip-apps/src/pjsystest/gui.h
@@ -0,0 +1,72 @@
+/* $Id: gui.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __GUI_H__
+#define __GUI_H__
+
+#include <pj/types.h>
+
+PJ_BEGIN_DECL
+
+typedef char gui_title[32];
+
+typedef void (*gui_menu_handler) (void);
+
+typedef struct gui_menu
+{
+ gui_title title;
+ gui_menu_handler handler;
+ unsigned submenu_cnt;
+ struct gui_menu *submenus[16];
+} gui_menu;
+
+enum gui_flag
+{
+ WITH_OK = 0,
+ WITH_YESNO = 1,
+ WITH_OKCANCEL = 2
+};
+
+enum gui_key
+{
+ KEY_CANCEL = '9',
+ KEY_NO = '0',
+ KEY_YES = '1',
+ KEY_OK = '1',
+};
+
+/* Initialize GUI with the menus and stuff */
+pj_status_t gui_init(gui_menu *menu);
+
+/* Run GUI main loop */
+pj_status_t gui_start(gui_menu *menu);
+
+/* Signal GUI mainloop to stop */
+void gui_destroy(void);
+
+/* AUX: display messagebox */
+enum gui_key gui_msgbox(const char *title, const char *message, enum gui_flag flag);
+
+/* AUX: sleep */
+void gui_sleep(unsigned sec);
+
+
+PJ_END_DECL
+
+
+#endif /* __GUI_H__ */
diff --git a/pjsip-apps/src/pjsystest/main_console.c b/pjsip-apps/src/pjsystest/main_console.c
new file mode 100644
index 0000000..02aa3f2
--- /dev/null
+++ b/pjsip-apps/src/pjsystest/main_console.c
@@ -0,0 +1,144 @@
+/* $Id: main_console.c 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include "systest.h"
+#include "gui.h"
+#include <stdio.h>
+#include <pjlib.h>
+
+static pj_bool_t console_quit;
+
+enum gui_key gui_msgbox(const char *title, const char *message, enum gui_flag flag)
+{
+ puts(title);
+ puts(message);
+
+ for (;;) {
+ char input[10], *ret;
+
+ if (flag == WITH_YESNO)
+ printf("%c:Yes %c:No ", KEY_YES, KEY_NO);
+ else if (flag == WITH_OK)
+ printf("%c:OK ", KEY_OK);
+ else if (flag == WITH_OKCANCEL)
+ printf("%c:OK %c:Cancel ", KEY_OK, KEY_CANCEL);
+ puts("");
+
+ ret = fgets(input, sizeof(input), stdin);
+ if (!ret)
+ return KEY_CANCEL;
+
+ if (input[0]==KEY_NO || input[0]==KEY_YES || input[0]==KEY_CANCEL)
+ return (enum gui_key)input[0];
+ }
+}
+
+pj_status_t gui_init(gui_menu *menu)
+{
+ PJ_UNUSED_ARG(menu);
+ return PJ_SUCCESS;
+}
+
+static void print_menu(const char *indent, char *menu_id, gui_menu *menu)
+{
+ char child_indent[16];
+ unsigned i;
+
+ pj_ansi_snprintf(child_indent, sizeof(child_indent), "%s ", indent);
+
+ printf("%s%s: %s\n", indent, menu_id, menu->title);
+
+ for (i=0; i<menu->submenu_cnt; ++i) {
+ char child_id[10];
+
+ pj_ansi_sprintf(child_id, "%s%u", menu_id, i);
+
+ if (!menu->submenus[i])
+ puts("");
+ else
+ print_menu(child_indent, child_id, menu->submenus[i]);
+ }
+}
+
+pj_status_t gui_start(gui_menu *menu)
+{
+ while (!console_quit) {
+ unsigned i;
+ char input[10], *p;
+ gui_menu *choice;
+
+ puts("M E N U :");
+ puts("---------");
+ for (i=0; i<menu->submenu_cnt; ++i) {
+ char menu_id[4];
+ pj_ansi_sprintf(menu_id, "%u", i);
+ print_menu("", menu_id, menu->submenus[i]);
+ }
+ puts("");
+ printf("Enter the menu number: ");
+
+ if (!fgets(input, sizeof(input), stdin))
+ break;
+
+ p = input;
+ choice = menu;
+ while (*p && *p!='\r' && *p!='\n') {
+ unsigned d = (*p - '0');
+ if (d < 0 || d >= choice->submenu_cnt) {
+ puts("Invalid selection");
+ choice = NULL;
+ break;
+ }
+
+ choice = choice->submenus[d];
+ ++p;
+ }
+
+ if (choice && *p!='\r' && *p!='\n') {
+ puts("Invalid characters entered");
+ continue;
+ }
+
+ if (choice && choice->handler)
+ (*choice->handler)();
+ }
+
+ return PJ_SUCCESS;
+}
+
+void gui_destroy(void)
+{
+ console_quit = PJ_TRUE;
+}
+
+void gui_sleep(unsigned sec)
+{
+ pj_thread_sleep(sec * 1000);
+}
+
+int main()
+{
+ if (systest_init() != PJ_SUCCESS)
+ return 1;
+
+ systest_run();
+ systest_deinit();
+
+ return 0;
+}
+
diff --git a/pjsip-apps/src/pjsystest/main_wm.c b/pjsip-apps/src/pjsystest/main_wm.c
new file mode 100644
index 0000000..aaaac1e
--- /dev/null
+++ b/pjsip-apps/src/pjsystest/main_wm.c
@@ -0,0 +1,444 @@
+/* $Id: main_wm.c 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include "gui.h"
+#include "systest.h"
+#include <windows.h>
+
+
+#include "gui.h"
+#include <pjlib.h>
+#include <windows.h>
+#include <winuserm.h>
+#include <aygshell.h>
+
+#define MAINWINDOWCLASS TEXT("SysTestDlg")
+#define MAINWINDOWTITLE TEXT("PJSYSTEST")
+
+typedef struct menu_handler_t {
+ UINT id;
+ gui_menu_handler handler;
+} menu_handler_t;
+
+static HINSTANCE g_hInst;
+static HWND g_hWndMenuBar;
+static HWND g_hWndMain;
+static HWND g_hWndLog;
+static pj_thread_t *g_log_thread;
+static gui_menu *g_menu;
+static unsigned g_menu_handler_cnt;
+static menu_handler_t g_menu_handlers[64];
+
+static pj_log_func *g_log_writer_orig;
+
+static pj_status_t gui_update_menu(gui_menu *menu);
+
+static void log_writer(int level, const char *buffer, int len)
+{
+ wchar_t buf[512];
+ int cur_len;
+
+ PJ_UNUSED_ARG(level);
+
+ pj_ansi_to_unicode(buffer, len, buf, 512);
+
+ if (!g_hWndLog)
+ return;
+
+ /* For now, ignore log messages from other thread to avoid deadlock */
+ if (g_log_thread == pj_thread_this()) {
+ cur_len = (int)SendMessage(g_hWndLog, WM_GETTEXTLENGTH, 0, 0);
+ SendMessage(g_hWndLog, EM_SETSEL, (WPARAM)cur_len, (LPARAM)cur_len);
+ SendMessage(g_hWndLog, EM_REPLACESEL, (WPARAM)0, (LPARAM)buf);
+ }
+
+ //uncomment to forward to the original log writer
+ if (g_log_writer_orig)
+ (*g_log_writer_orig)(level, buffer, len);
+}
+
+/* execute menu handler for id menu specified, return FALSE if menu handler
+ * is not found.
+ */
+static BOOL handle_menu(UINT id)
+{
+ unsigned i;
+
+ for (i = 0; i < g_menu_handler_cnt; ++i) {
+ if (g_menu_handlers[i].id == id) {
+ /* menu handler found, execute it */
+ (*g_menu_handlers[i].handler)();
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/* generate submenu and register the menu handler, then return next menu id */
+static UINT generate_submenu(HMENU parent, UINT id_start, gui_menu *menu)
+{
+ unsigned i;
+ UINT id = id_start;
+
+ if (!menu)
+ return id;
+
+ /* generate submenu */
+ for (i = 0; i < menu->submenu_cnt; ++i) {
+
+ if (menu->submenus[i] == NULL) {
+
+ /* add separator */
+ AppendMenu(parent, MF_SEPARATOR, 0, 0);
+
+ } else if (menu->submenus[i]->submenu_cnt != 0) {
+
+ /* this submenu item has children, generate popup menu */
+ HMENU hMenu;
+ wchar_t buf[64];
+
+ pj_ansi_to_unicode(menu->submenus[i]->title,
+ pj_ansi_strlen(menu->submenus[i]->title),
+ buf, 64);
+
+ hMenu = CreatePopupMenu();
+ AppendMenu(parent, MF_STRING|MF_ENABLED|MF_POPUP, (UINT)hMenu, buf);
+ id = generate_submenu(hMenu, id, menu->submenus[i]);
+
+ } else {
+
+ /* this submenu item is leaf, register the handler */
+ wchar_t buf[64];
+
+ pj_ansi_to_unicode(menu->submenus[i]->title,
+ pj_ansi_strlen(menu->submenus[i]->title),
+ buf, 64);
+
+ AppendMenu(parent, MF_STRING, id, buf);
+
+ if (menu->submenus[i]->handler) {
+ g_menu_handlers[g_menu_handler_cnt].id = id;
+ g_menu_handlers[g_menu_handler_cnt].handler =
+ menu->submenus[i]->handler;
+ ++g_menu_handler_cnt;
+ }
+
+ ++id;
+ }
+ }
+
+ return id;
+}
+
+BOOL InitDialog()
+{
+ /* update menu */
+ if (gui_update_menu(g_menu) != PJ_SUCCESS)
+ return FALSE;
+
+ return TRUE;
+}
+
+LRESULT CALLBACK DialogProc(const HWND hWnd,
+ const UINT Msg,
+ const WPARAM wParam,
+ const LPARAM lParam)
+{
+ LRESULT res = 0;
+
+ switch (Msg) {
+ case WM_CREATE:
+ g_hWndMain = hWnd;
+ if (FALSE == InitDialog()){
+ DestroyWindow(g_hWndMain);
+ }
+ break;
+
+ case WM_CLOSE:
+ DestroyWindow(g_hWndMain);
+ break;
+
+ case WM_DESTROY:
+ if (g_hWndMenuBar)
+ DestroyWindow(g_hWndMenuBar);
+ g_hWndMenuBar = NULL;
+ g_hWndMain = NULL;
+ PostQuitMessage(0);
+ break;
+
+ case WM_HOTKEY:
+ /* Exit app when back is pressed. */
+ if (VK_TBACK == HIWORD(lParam) && (0 != (MOD_KEYUP & LOWORD(lParam)))) {
+ DestroyWindow(g_hWndMain);
+ } else {
+ return DefWindowProc(hWnd, Msg, wParam, lParam);
+ }
+ break;
+
+ case WM_COMMAND:
+ res = handle_menu(LOWORD(wParam));
+ break;
+
+ default:
+ return DefWindowProc(hWnd, Msg, wParam, lParam);
+ }
+
+ return res;
+}
+
+
+/* === API === */
+
+pj_status_t gui_init(gui_menu *menu)
+{
+ WNDCLASS wc;
+ HWND hWnd = NULL;
+ RECT r;
+ DWORD dwStyle;
+
+ pj_status_t status = PJ_SUCCESS;
+
+ /* Check if app is running. If it's running then focus on the window */
+ hWnd = FindWindow(MAINWINDOWCLASS, MAINWINDOWTITLE);
+
+ if (NULL != hWnd) {
+ SetForegroundWindow(hWnd);
+ return status;
+ }
+
+ g_menu = menu;
+
+ wc.style = CS_HREDRAW | CS_VREDRAW;
+ wc.lpfnWndProc = (WNDPROC)DialogProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = g_hInst;
+ wc.hIcon = 0;
+ wc.hCursor = 0;
+ wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
+ wc.lpszMenuName = 0;
+ wc.lpszClassName = MAINWINDOWCLASS;
+
+ if (!RegisterClass(&wc) != 0) {
+ DWORD err = GetLastError();
+ return PJ_RETURN_OS_ERROR(err);
+ }
+
+ /* Create the app. window */
+ g_hWndMain = CreateWindow(MAINWINDOWCLASS, MAINWINDOWTITLE,
+ WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ (HWND)NULL, NULL, g_hInst, (LPSTR)NULL);
+
+ /* Create edit control to print log */
+ GetClientRect(g_hWndMain, &r);
+ dwStyle = WS_CHILD | WS_VISIBLE | WS_VSCROLL |
+ ES_MULTILINE | ES_READONLY | ES_AUTOVSCROLL | ES_LEFT;
+ g_hWndLog = CreateWindow(
+ TEXT("EDIT"), // Class name
+ NULL, // Window text
+ dwStyle, // Window style
+ 0, // x-coordinate of the upper-left corner
+ 0, // y-coordinate of the upper-left corner
+ r.right-r.left, // Width of the window for the edit
+ // control
+ r.bottom-r.top, // Height of the window for the edit
+ // control
+ g_hWndMain, // Window handle to the parent window
+ (HMENU) 0, // Control identifier
+ g_hInst, // Instance handle
+ NULL); // Specify NULL for this parameter when
+ // you create a control
+
+ /* Resize the log */
+ if (g_hWndMenuBar) {
+ RECT r_menu = {0};
+
+ GetWindowRect(g_hWndLog, &r);
+ GetWindowRect(g_hWndMenuBar, &r_menu);
+ if (r.bottom > r_menu.top) {
+ MoveWindow(g_hWndLog, 0, 0, r.right-r.left,
+ (r.bottom-r.top)-(r_menu.bottom-r_menu.top), TRUE);
+ }
+ }
+
+ /* Focus it, so SP user can scroll the log */
+ SetFocus(g_hWndLog);
+
+ /* Get the log thread */
+ g_log_thread = pj_thread_this();
+
+ /* Redirect log & update log decor setting */
+ /*
+ log_decor = pj_log_get_decor();
+ log_decor = PJ_LOG_HAS_NEWLINE | PJ_LOG_HAS_CR;
+ pj_log_set_decor(log_decor);
+ */
+ g_log_writer_orig = pj_log_get_log_func();
+ pj_log_set_log_func(&log_writer);
+
+ return status;
+}
+
+static pj_status_t gui_update_menu(gui_menu *menu)
+{
+ enum { MENU_ID_START = 50000 };
+ UINT id_start = MENU_ID_START;
+ HMENU hRootMenu;
+ SHMENUBARINFO mbi;
+
+ /* delete existing menu */
+ if (g_hWndMenuBar) {
+ DestroyWindow(g_hWndMenuBar);
+ g_hWndMenuBar = NULL;
+ }
+
+ /* delete menu handler map */
+ g_menu_handler_cnt = 0;
+
+ /* smartphone can only have two root menus */
+ pj_assert(menu->submenu_cnt <= 2);
+
+ /* generate menu tree */
+ hRootMenu = CreateMenu();
+ id_start = generate_submenu(hRootMenu, id_start, menu);
+
+ /* initialize menubar */
+ ZeroMemory(&mbi, sizeof(SHMENUBARINFO));
+ mbi.cbSize = sizeof(SHMENUBARINFO);
+ mbi.hwndParent = g_hWndMain;
+ mbi.dwFlags = SHCMBF_HIDESIPBUTTON|SHCMBF_HMENU;
+ mbi.nToolBarId = (UINT)hRootMenu;
+ mbi.hInstRes = g_hInst;
+
+ if (FALSE == SHCreateMenuBar(&mbi)) {
+ DWORD err = GetLastError();
+ return PJ_RETURN_OS_ERROR(err);
+ }
+
+ /* store menu window handle */
+ g_hWndMenuBar = mbi.hwndMB;
+
+ /* store current menu */
+ g_menu = menu;
+
+ /* show the menu */
+ DrawMenuBar(g_hWndMain);
+ ShowWindow(g_hWndMenuBar, SW_SHOW);
+
+ /* override back button */
+ SendMessage(g_hWndMenuBar, SHCMBM_OVERRIDEKEY, VK_TBACK,
+ MAKELPARAM(SHMBOF_NODEFAULT | SHMBOF_NOTIFY,
+ SHMBOF_NODEFAULT | SHMBOF_NOTIFY));
+
+
+ return PJ_SUCCESS;
+}
+
+enum gui_key gui_msgbox(const char *title, const char *message, enum gui_flag flag)
+{
+ wchar_t buf_title[64];
+ wchar_t buf_msg[512];
+ UINT wflag = 0;
+ int retcode;
+
+ pj_ansi_to_unicode(title, pj_ansi_strlen(title), buf_title, 64);
+ pj_ansi_to_unicode(message, pj_ansi_strlen(message), buf_msg, 512);
+
+ switch (flag) {
+ case WITH_OK:
+ wflag = MB_OK;
+ break;
+ case WITH_YESNO:
+ wflag = MB_YESNO;
+ break;
+ case WITH_OKCANCEL:
+ wflag = MB_OKCANCEL;
+ break;
+ }
+
+ retcode = MessageBox(g_hWndMain, buf_msg, buf_title, wflag);
+
+ switch (retcode) {
+ case IDOK:
+ return KEY_OK;
+ case IDYES:
+ return KEY_YES;
+ case IDNO:
+ return KEY_NO;
+ default:
+ return KEY_CANCEL;
+ }
+}
+
+void gui_sleep(unsigned sec)
+{
+ pj_thread_sleep(sec * 1000);
+}
+
+pj_status_t gui_start(gui_menu *menu)
+{
+ MSG msg;
+
+ PJ_UNUSED_ARG(menu);
+
+ while (GetMessage(&msg, NULL, 0, 0)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+
+ return (msg.wParam);
+}
+
+void gui_destroy(void)
+{
+ if (g_hWndMain) {
+ DestroyWindow(g_hWndMain);
+ g_hWndMain = NULL;
+ }
+}
+
+
+int WINAPI WinMain(
+ HINSTANCE hInstance,
+ HINSTANCE hPrevInstance,
+ LPWSTR lpCmdLine,
+ int nShowCmd
+)
+{
+ int status;
+
+ PJ_UNUSED_ARG(hPrevInstance);
+ PJ_UNUSED_ARG(lpCmdLine);
+ PJ_UNUSED_ARG(nShowCmd);
+
+ // store the hInstance in global
+ g_hInst = hInstance;
+
+ status = systest_init();
+ if (status != 0)
+ goto on_return;
+
+ status = systest_run();
+
+on_return:
+ systest_deinit();
+
+ return status;
+}
diff --git a/pjsip-apps/src/pjsystest/pjsystest_wince.rc b/pjsip-apps/src/pjsystest/pjsystest_wince.rc
new file mode 100644
index 0000000..c76ef68
--- /dev/null
+++ b/pjsip-apps/src/pjsystest/pjsystest_wince.rc
@@ -0,0 +1,108 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.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
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "#include ""pjsystest_wince.rc2""\r\n"
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_MAIN_DIALOG DIALOG 0, 0, 82, 73
+STYLE DS_SETFONT | WS_VISIBLE | WS_VSCROLL
+FONT 8, "MS Sans Serif"
+BEGIN
+ EDITTEXT IDC_EDIT1,7,7,57,59,ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_MAIN_DIALOG, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 64
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 66
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE
+BEGIN
+ IDS_MAIN_TITLE "PJSYSTEST"
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+#include "pjsystest_wince.rc2"
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/pjsip-apps/src/pjsystest/pjsystest_wince.rc2 b/pjsip-apps/src/pjsystest/pjsystest_wince.rc2
new file mode 100644
index 0000000..3bee66b
--- /dev/null
+++ b/pjsip-apps/src/pjsystest/pjsystest_wince.rc2
@@ -0,0 +1,10 @@
+#ifdef APSTUDIO_INVOKED
+ #error this file is not editable by Microsoft Visual C++
+#endif //APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Add manually edited resources here...
+
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/pjsip-apps/src/pjsystest/resource.h b/pjsip-apps/src/pjsystest/resource.h
new file mode 100644
index 0000000..f5208b6
--- /dev/null
+++ b/pjsip-apps/src/pjsystest/resource.h
@@ -0,0 +1,18 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by pjsystest_wince.rc
+//
+#define IDD_MAIN_DIALOG 101
+#define IDS_MAIN_TITLE 102
+#define IDC_EDIT1 1001
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 103
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1002
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/pjsip-apps/src/pjsystest/systest.c b/pjsip-apps/src/pjsystest/systest.c
new file mode 100644
index 0000000..0767763
--- /dev/null
+++ b/pjsip-apps/src/pjsystest/systest.c
@@ -0,0 +1,1369 @@
+/* $Id: systest.c 4087 2012-04-26 03:39:24Z ming $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include "systest.h"
+#include "gui.h"
+
+#define THIS_FILE "systest.c"
+
+unsigned test_item_count;
+test_item_t test_items[SYSTEST_MAX_TEST];
+char doc_path[PATH_LENGTH] = {0};
+char res_path[PATH_LENGTH] = {0};
+char fpath[PATH_LENGTH];
+
+#define USER_ERROR "User used said not okay"
+
+static void systest_wizard(void);
+static void systest_list_audio_devs(void);
+static void systest_display_settings(void);
+static void systest_play_tone(void);
+static void systest_play_wav1(void);
+static void systest_play_wav2(void);
+static void systest_rec_audio(void);
+static void systest_audio_test(void);
+static void systest_latency_test(void);
+static void systest_aec_test(void);
+static void exit_app(void);
+
+/* Menus */
+static gui_menu menu_exit = { "Exit", &exit_app };
+
+static gui_menu menu_wizard = { "Run test wizard", &systest_wizard };
+static gui_menu menu_playtn = { "Play Tone", &systest_play_tone };
+static gui_menu menu_playwv1 = { "Play WAV File1", &systest_play_wav1 };
+static gui_menu menu_playwv2 = { "Play WAV File2", &systest_play_wav2 };
+static gui_menu menu_recaud = { "Record Audio", &systest_rec_audio };
+static gui_menu menu_audtest = { "Device Test", &systest_audio_test };
+static gui_menu menu_calclat = { "Latency Test", &systest_latency_test };
+static gui_menu menu_sndaec = { "AEC/AES Test", &systest_aec_test };
+
+static gui_menu menu_listdev = { "View Devices", &systest_list_audio_devs };
+static gui_menu menu_getsets = { "View Settings", &systest_display_settings };
+
+static gui_menu menu_tests = {
+ "Tests", NULL,
+ 10,
+ {
+ &menu_wizard,
+ &menu_audtest,
+ &menu_playtn,
+ &menu_playwv1,
+ &menu_playwv2,
+ &menu_recaud,
+ &menu_calclat,
+ &menu_sndaec,
+ NULL,
+ &menu_exit
+ }
+};
+
+static gui_menu menu_options = {
+ "Options", NULL,
+ 2,
+ {
+ &menu_listdev,
+ &menu_getsets,
+ }
+};
+
+static gui_menu root_menu = {
+ "Root", NULL, 2, {&menu_tests, &menu_options}
+};
+
+/*****************************************************************/
+
+#if defined(PJ_DARWINOS) && PJ_DARWINOS!=0
+PJ_INLINE(char *) add_path(const char *path, const char *fname)
+{
+ strncpy(fpath, path, PATH_LENGTH);
+ strncat(fpath, fname, PATH_LENGTH);
+ return fpath;
+}
+#else
+# define add_path(path, fname) fname
+#endif
+
+static void exit_app(void)
+{
+ systest_save_result(add_path(doc_path, RESULT_OUT_PATH));
+ gui_destroy();
+}
+
+
+#include <pjsua-lib/pjsua.h>
+#include <pjmedia_audiodev.h>
+
+typedef struct systest_t
+{
+ pjsua_config ua_cfg;
+ pjsua_media_config media_cfg;
+ pjmedia_aud_dev_index rec_id;
+ pjmedia_aud_dev_index play_id;
+} systest_t;
+
+static systest_t systest;
+static char textbuf[600];
+
+/* Device ID to test */
+int systest_cap_dev_id = PJMEDIA_AUD_DEFAULT_CAPTURE_DEV;
+int systest_play_dev_id = PJMEDIA_AUD_DEFAULT_PLAYBACK_DEV;
+
+static void systest_perror(const char *title, pj_status_t status)
+{
+ char errmsg[PJ_ERR_MSG_SIZE];
+ char themsg[PJ_ERR_MSG_SIZE + 100];
+
+ if (status != PJ_SUCCESS)
+ pj_strerror(status, errmsg, sizeof(errmsg));
+ else
+ errmsg[0] = '\0';
+
+ strcpy(themsg, title);
+ strncat(themsg, errmsg, sizeof(themsg)-1);
+ themsg[sizeof(themsg)-1] = '\0';
+
+ gui_msgbox("Error", themsg, WITH_OK);
+}
+
+test_item_t *systest_alloc_test_item(const char *title)
+{
+ test_item_t *ti;
+
+ if (test_item_count == SYSTEST_MAX_TEST) {
+ gui_msgbox("Error", "You have done too many tests", WITH_OK);
+ return NULL;
+ }
+
+ ti = &test_items[test_item_count++];
+ pj_bzero(ti, sizeof(*ti));
+ pj_ansi_strcpy(ti->title, title);
+
+ return ti;
+}
+
+/*****************************************************************************
+ * test: play simple ringback tone and hear it
+ */
+static void systest_play_tone(void)
+{
+ /* Ringtones */
+ #define RINGBACK_FREQ1 440 /* 400 */
+ #define RINGBACK_FREQ2 480 /* 450 */
+ #define RINGBACK_ON 3000 /* 400 */
+ #define RINGBACK_OFF 4000 /* 200 */
+ #define RINGBACK_CNT 1 /* 2 */
+ #define RINGBACK_INTERVAL 4000 /* 2000 */
+
+ unsigned i, samples_per_frame;
+ pjmedia_tone_desc tone[RINGBACK_CNT];
+ pj_pool_t *pool = NULL;
+ pjmedia_port *ringback_port = NULL;
+ enum gui_key key;
+ int ringback_slot = -1;
+ test_item_t *ti;
+ pj_str_t name;
+ const char *title = "Audio Tone Playback Test";
+ pj_status_t status;
+
+ ti = systest_alloc_test_item(title);
+ if (!ti)
+ return;
+
+ key = gui_msgbox(title,
+ "This test will play simple ringback tone to "
+ "the speaker. Please listen carefully for audio "
+ "impairments such as stutter. You may need "
+ "to let this test running for a while to "
+ "make sure that everything is okay. Press "
+ "OK to start, CANCEL to skip",
+ WITH_OKCANCEL);
+ if (key != KEY_OK) {
+ ti->skipped = PJ_TRUE;
+ return;
+ }
+
+ PJ_LOG(3,(THIS_FILE, "Running %s", title));
+
+ pool = pjsua_pool_create("ringback", 512, 512);
+ samples_per_frame = systest.media_cfg.audio_frame_ptime *
+ systest.media_cfg.clock_rate *
+ systest.media_cfg.channel_count / 1000;
+
+ /* Ringback tone (call is ringing) */
+ name = pj_str("ringback");
+ status = pjmedia_tonegen_create2(pool, &name,
+ systest.media_cfg.clock_rate,
+ systest.media_cfg.channel_count,
+ samples_per_frame,
+ 16, PJMEDIA_TONEGEN_LOOP,
+ &ringback_port);
+ if (status != PJ_SUCCESS)
+ goto on_return;
+
+ pj_bzero(&tone, sizeof(tone));
+ for (i=0; i<RINGBACK_CNT; ++i) {
+ tone[i].freq1 = RINGBACK_FREQ1;
+ tone[i].freq2 = RINGBACK_FREQ2;
+ tone[i].on_msec = RINGBACK_ON;
+ tone[i].off_msec = RINGBACK_OFF;
+ }
+ tone[RINGBACK_CNT-1].off_msec = RINGBACK_INTERVAL;
+
+ status = pjmedia_tonegen_play(ringback_port, RINGBACK_CNT, tone,
+ PJMEDIA_TONEGEN_LOOP);
+ if (status != PJ_SUCCESS)
+ goto on_return;
+
+ status = pjsua_conf_add_port(pool, ringback_port, &ringback_slot);
+ if (status != PJ_SUCCESS)
+ goto on_return;
+
+ status = pjsua_conf_connect(ringback_slot, 0);
+ if (status != PJ_SUCCESS)
+ goto on_return;
+
+ key = gui_msgbox(title,
+ "Ringback tone should be playing now in the "
+ "speaker. Press OK to stop. ", WITH_OK);
+
+ status = PJ_SUCCESS;
+
+on_return:
+ if (ringback_slot != -1)
+ pjsua_conf_remove_port(ringback_slot);
+ if (ringback_port)
+ pjmedia_port_destroy(ringback_port);
+ if (pool)
+ pj_pool_release(pool);
+
+ if (status != PJ_SUCCESS) {
+ systest_perror("Sorry we encounter error when initializing "
+ "the tone generator: ", status);
+ ti->success = PJ_FALSE;
+ pj_strerror(status, ti->reason, sizeof(ti->reason));
+ } else {
+ key = gui_msgbox(title, "Is the audio okay?", WITH_YESNO);
+ ti->success = (key == KEY_YES);
+ if (!ti->success)
+ pj_ansi_strcpy(ti->reason, USER_ERROR);
+ }
+ return;
+}
+
+/* Util: create file player, each time trying different paths until we get
+ * the file.
+ */
+static pj_status_t create_player(unsigned path_cnt, const char *paths[],
+ pjsua_player_id *p_id)
+{
+ pj_str_t name;
+ pj_status_t status = PJ_ENOTFOUND;
+ unsigned i;
+
+ for (i=0; i<path_cnt; ++i) {
+ status = pjsua_player_create(pj_cstr(&name, paths[i]), 0, p_id);
+ if (status == PJ_SUCCESS)
+ return PJ_SUCCESS;
+ }
+ return status;
+}
+
+/*****************************************************************************
+ * test: play WAV file
+ */
+static void systest_play_wav(unsigned path_cnt, const char *paths[])
+{
+ pjsua_player_id play_id = PJSUA_INVALID_ID;
+ enum gui_key key;
+ test_item_t *ti;
+ const char *title = "WAV File Playback Test";
+ pj_status_t status;
+
+ ti = systest_alloc_test_item(title);
+ if (!ti)
+ return;
+
+ pj_ansi_snprintf(textbuf, sizeof(textbuf),
+ "This test will play %s file to "
+ "the speaker. Please listen carefully for audio "
+ "impairments such as stutter. Let this test run "
+ "for a while to make sure that everything is okay."
+ " Press OK to start, CANCEL to skip",
+ paths[0]);
+
+ key = gui_msgbox(title, textbuf,
+ WITH_OKCANCEL);
+ if (key != KEY_OK) {
+ ti->skipped = PJ_TRUE;
+ return;
+ }
+
+ PJ_LOG(3,(THIS_FILE, "Running %s", title));
+
+ /* WAV port */
+ status = create_player(path_cnt, paths, &play_id);
+ if (status != PJ_SUCCESS)
+ goto on_return;
+
+ status = pjsua_conf_connect(pjsua_player_get_conf_port(play_id), 0);
+ if (status != PJ_SUCCESS)
+ goto on_return;
+
+ key = gui_msgbox(title,
+ "WAV file should be playing now in the "
+ "speaker. Press OK to stop. ", WITH_OK);
+
+ status = PJ_SUCCESS;
+
+on_return:
+ if (play_id != -1)
+ pjsua_player_destroy(play_id);
+
+ if (status != PJ_SUCCESS) {
+ systest_perror("Sorry we've encountered error", status);
+ ti->success = PJ_FALSE;
+ pj_strerror(status, ti->reason, sizeof(ti->reason));
+ } else {
+ key = gui_msgbox(title, "Is the audio okay?", WITH_YESNO);
+ ti->success = (key == KEY_YES);
+ if (!ti->success)
+ pj_ansi_strcpy(ti->reason, USER_ERROR);
+ }
+ return;
+}
+
+static void systest_play_wav1(void)
+{
+ const char *paths[] = { add_path(res_path, WAV_PLAYBACK_PATH),
+ ALT_PATH1 WAV_PLAYBACK_PATH };
+ systest_play_wav(PJ_ARRAY_SIZE(paths), paths);
+}
+
+static void systest_play_wav2(void)
+{
+ const char *paths[] = { add_path(res_path, WAV_TOCK8_PATH),
+ ALT_PATH1 WAV_TOCK8_PATH};
+ systest_play_wav(PJ_ARRAY_SIZE(paths), paths);
+}
+
+
+/*****************************************************************************
+ * test: record audio
+ */
+static void systest_rec_audio(void)
+{
+ const pj_str_t filename = pj_str(add_path(doc_path, WAV_REC_OUT_PATH));
+ pj_pool_t *pool = NULL;
+ enum gui_key key;
+ pjsua_recorder_id rec_id = PJSUA_INVALID_ID;
+ pjsua_player_id play_id = PJSUA_INVALID_ID;
+ pjsua_conf_port_id rec_slot = PJSUA_INVALID_ID;
+ pjsua_conf_port_id play_slot = PJSUA_INVALID_ID;
+ pj_status_t status = PJ_SUCCESS;
+ const char *title = "Audio Recording";
+ test_item_t *ti;
+
+ ti = systest_alloc_test_item(title);
+ if (!ti)
+ return;
+
+ key = gui_msgbox(title,
+ "This test will allow you to record audio "
+ "from the microphone, and playback the "
+ "audio to the speaker. Press OK to start recording, "
+ "CANCEL to skip.",
+ WITH_OKCANCEL);
+ if (key != KEY_OK) {
+ ti->skipped = PJ_TRUE;
+ return;
+ }
+
+ PJ_LOG(3,(THIS_FILE, "Running %s", title));
+
+ pool = pjsua_pool_create("rectest", 512, 512);
+
+ status = pjsua_recorder_create(&filename, 0, NULL, -1, 0, &rec_id);
+ if (status != PJ_SUCCESS)
+ goto on_return;
+
+ rec_slot = pjsua_recorder_get_conf_port(rec_id);
+
+ status = pjsua_conf_connect(0, rec_slot);
+ if (status != PJ_SUCCESS)
+ goto on_return;
+
+ key = gui_msgbox(title,
+ "Recording is in progress now, please say "
+ "something in the microphone. Press OK "
+ "to stop recording", WITH_OK);
+
+ pjsua_conf_disconnect(0, rec_slot);
+ rec_slot = PJSUA_INVALID_ID;
+ pjsua_recorder_destroy(rec_id);
+ rec_id = PJSUA_INVALID_ID;
+
+ status = pjsua_player_create(&filename, 0, &play_id);
+ if (status != PJ_SUCCESS)
+ goto on_return;
+
+ play_slot = pjsua_player_get_conf_port(play_id);
+
+ status = pjsua_conf_connect(play_slot, 0);
+ if (status != PJ_SUCCESS)
+ goto on_return;
+
+ key = gui_msgbox(title,
+ "Recording has been stopped. "
+ "The recorded audio is being played now to "
+ "the speaker device, in a loop. Listen for "
+ "any audio impairments. Press OK to stop.",
+ WITH_OK);
+
+on_return:
+ if (rec_slot != PJSUA_INVALID_ID)
+ pjsua_conf_disconnect(0, rec_slot);
+ if (rec_id != PJSUA_INVALID_ID)
+ pjsua_recorder_destroy(rec_id);
+ if (play_slot != PJSUA_INVALID_ID)
+ pjsua_conf_disconnect(play_slot, 0);
+ if (play_id != PJSUA_INVALID_ID)
+ pjsua_player_destroy(play_id);
+ if (pool)
+ pj_pool_release(pool);
+
+ if (status != PJ_SUCCESS) {
+ systest_perror("Sorry we encountered an error: ", status);
+ ti->success = PJ_FALSE;
+ pj_strerror(status, ti->reason, sizeof(ti->reason));
+ } else {
+ key = gui_msgbox(title, "Is the audio okay?", WITH_YESNO);
+ ti->success = (key == KEY_YES);
+ if (!ti->success) {
+ pj_ansi_snprintf(textbuf, sizeof(textbuf),
+ "You will probably need to copy the recorded "
+ "WAV file %s to a desktop computer and analyze "
+ "it, to find out whether it's a recording "
+ "or playback problem.",
+ WAV_REC_OUT_PATH);
+ gui_msgbox(title, textbuf, WITH_OK);
+ pj_ansi_strcpy(ti->reason, USER_ERROR);
+ }
+ }
+}
+
+
+/****************************************************************************
+ * test: audio system test
+ */
+static void systest_audio_test(void)
+{
+ enum {
+ GOOD_MAX_INTERVAL = 5,
+ };
+ const pjmedia_dir dir = PJMEDIA_DIR_CAPTURE_PLAYBACK;
+ pjmedia_aud_param param;
+ pjmedia_aud_test_results result;
+ int textbufpos;
+ enum gui_key key;
+ unsigned problem_count = 0;
+ const char *problems[16];
+ char drifttext[120];
+ test_item_t *ti;
+ const char *title = "Audio Device Test";
+ pj_status_t status;
+
+ ti = systest_alloc_test_item(title);
+ if (!ti)
+ return;
+
+ key = gui_msgbox(title,
+ "This will run an automated test for about "
+ "ten seconds or so, and display some "
+ "statistics about your sound device. "
+ "Please don't do anything until the test completes. "
+ "Press OK to start, or CANCEL to skip this test.",
+ WITH_OKCANCEL);
+ if (key != KEY_OK) {
+ ti->skipped = PJ_TRUE;
+ return;
+ }
+
+ PJ_LOG(3,(THIS_FILE, "Running %s", title));
+
+ /* Disable sound device in pjsua first */
+ pjsua_set_no_snd_dev();
+
+ /* Setup parameters */
+ status = pjmedia_aud_dev_default_param(systest.play_id, &param);
+ if (status != PJ_SUCCESS) {
+ systest_perror("Sorry we had error in pjmedia_aud_dev_default_param()", status);
+ pjsua_set_snd_dev(systest.rec_id, systest.play_id);
+ ti->success = PJ_FALSE;
+ pj_strerror(status, ti->reason, sizeof(ti->reason));
+ ti->reason[sizeof(ti->reason)-1] = '\0';
+ return;
+ }
+
+ param.dir = dir;
+ param.rec_id = systest.rec_id;
+ param.play_id = systest.play_id;
+ param.clock_rate = systest.media_cfg.snd_clock_rate;
+ param.channel_count = systest.media_cfg.channel_count;
+ param.samples_per_frame = param.clock_rate * param.channel_count *
+ systest.media_cfg.audio_frame_ptime / 1000;
+
+ /* Latency settings */
+ param.flags |= (PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY |
+ PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY);
+ param.input_latency_ms = systest.media_cfg.snd_rec_latency;
+ param.output_latency_ms = systest.media_cfg.snd_play_latency;
+
+ /* Run the test */
+ status = pjmedia_aud_test(&param, &result);
+ if (status != PJ_SUCCESS) {
+ systest_perror("Sorry we encountered error with the test", status);
+ pjsua_set_snd_dev(systest.rec_id, systest.play_id);
+ ti->success = PJ_FALSE;
+ pj_strerror(status, ti->reason, sizeof(ti->reason));
+ ti->reason[sizeof(ti->reason)-1] = '\0';
+ return;
+ }
+
+ /* Restore pjsua sound device */
+ pjsua_set_snd_dev(systest.rec_id, systest.play_id);
+
+ /* Analyze the result! */
+ strcpy(textbuf, "Here are the audio statistics:\r\n");
+ textbufpos = strlen(textbuf);
+
+ if (result.rec.frame_cnt==0) {
+ problems[problem_count++] =
+ "No audio frames were captured from the microphone. "
+ "This means the audio device is not working properly.";
+ } else {
+ pj_ansi_snprintf(textbuf+textbufpos,
+ sizeof(textbuf)-textbufpos,
+ "Rec : interval (min/max/avg/dev)=\r\n"
+ " %u/%u/%u/%u (ms)\r\n"
+ " max burst=%u\r\n",
+ result.rec.min_interval,
+ result.rec.max_interval,
+ result.rec.avg_interval,
+ result.rec.dev_interval,
+ result.rec.max_burst);
+ textbufpos = strlen(textbuf);
+
+ if (result.rec.max_burst > GOOD_MAX_INTERVAL) {
+ problems[problem_count++] =
+ "Recording max burst is quite high";
+ }
+ }
+
+ if (result.play.frame_cnt==0) {
+ problems[problem_count++] =
+ "No audio frames were played to the speaker. "
+ "This means the audio device is not working properly.";
+ } else {
+ pj_ansi_snprintf(textbuf+textbufpos,
+ sizeof(textbuf)-textbufpos,
+ "Play: interval (min/max/avg/dev)=\r\n"
+ " %u/%u/%u/%u (ms)\r\n"
+ " burst=%u\r\n",
+ result.play.min_interval,
+ result.play.max_interval,
+ result.play.avg_interval,
+ result.play.dev_interval,
+ result.play.max_burst);
+ textbufpos = strlen(textbuf);
+
+ if (result.play.max_burst > GOOD_MAX_INTERVAL) {
+ problems[problem_count++] =
+ "Playback max burst is quite high";
+ }
+ }
+
+ if (result.rec_drift_per_sec) {
+ const char *which = result.rec_drift_per_sec>=0 ? "faster" : "slower";
+ unsigned drift = result.rec_drift_per_sec>=0 ?
+ result.rec_drift_per_sec :
+ -result.rec_drift_per_sec;
+
+ pj_ansi_snprintf(drifttext, sizeof(drifttext),
+ "Clock drifts detected. Capture "
+ "is %d samples/sec %s "
+ "than the playback device",
+ drift, which);
+ problems[problem_count++] = drifttext;
+ }
+
+ if (problem_count == 0) {
+ pj_ansi_snprintf(textbuf+textbufpos,
+ sizeof(textbuf)-textbufpos,
+ "\r\nThe sound device seems to be okay!");
+ textbufpos = strlen(textbuf);
+
+ key = gui_msgbox("Audio Device Test", textbuf, WITH_OK);
+ } else {
+ unsigned i;
+
+ pj_ansi_snprintf(textbuf+textbufpos,
+ sizeof(textbuf)-textbufpos,
+ "There could be %d problem(s) with the "
+ "sound device:\r\n",
+ problem_count);
+ textbufpos = strlen(textbuf);
+
+ for (i=0; i<problem_count; ++i) {
+ pj_ansi_snprintf(textbuf+textbufpos,
+ sizeof(textbuf)-textbufpos,
+ " %d: %s\r\n", i+1, problems[i]);
+ textbufpos = strlen(textbuf);
+ }
+
+ key = gui_msgbox(title, textbuf, WITH_OK);
+ }
+
+ ti->success = PJ_TRUE;
+ pj_ansi_strncpy(ti->reason, textbuf, sizeof(ti->reason));
+ ti->reason[sizeof(ti->reason)-1] = '\0';
+}
+
+
+/****************************************************************************
+ * sound latency test
+ */
+static int calculate_latency(pj_pool_t *pool, pjmedia_port *wav,
+ unsigned *lat_sum, unsigned *lat_cnt,
+ unsigned *lat_min, unsigned *lat_max)
+{
+ pjmedia_frame frm;
+ short *buf;
+ unsigned i, clock_rate, samples_per_frame, read, len;
+ unsigned start_pos;
+ pj_bool_t first;
+ pj_status_t status;
+
+ *lat_sum = 0;
+ *lat_cnt = 0;
+ *lat_min = 10000;
+ *lat_max = 0;
+
+ samples_per_frame = PJMEDIA_PIA_SPF(&wav->info);
+ clock_rate = PJMEDIA_PIA_SRATE(&wav->info);
+ frm.buf = pj_pool_alloc(pool, samples_per_frame * 2);
+ frm.size = samples_per_frame * 2;
+ len = pjmedia_wav_player_get_len(wav);
+ buf = pj_pool_alloc(pool, len + samples_per_frame);
+
+ /* Read the whole file */
+ read = 0;
+ while (read < len/2) {
+ status = pjmedia_port_get_frame(wav, &frm);
+ if (status != PJ_SUCCESS)
+ break;
+
+ pjmedia_copy_samples(buf+read, (short*)frm.buf, samples_per_frame);
+ read += samples_per_frame;
+ }
+
+ if (read < 2 * clock_rate) {
+ systest_perror("The WAV file is too short", PJ_SUCCESS);
+ return -1;
+ }
+
+ /* Zero the first 500ms to remove loud click noises
+ * (keypad press, etc.)
+ */
+ pjmedia_zero_samples(buf, clock_rate / 2);
+
+ /* Loop to calculate latency */
+ start_pos = 0;
+ first = PJ_TRUE;
+ while (start_pos < len/2 - clock_rate) {
+ int max_signal = 0;
+ unsigned max_signal_pos = start_pos;
+ unsigned max_echo_pos = 0;
+ unsigned pos;
+ unsigned lat;
+
+ /* Get the largest signal in the next 0.7s */
+ for (i=start_pos; i<start_pos + clock_rate * 700 / 1000; ++i) {
+ if (abs(buf[i]) > max_signal) {
+ max_signal = abs(buf[i]);
+ max_signal_pos = i;
+ }
+ }
+
+ /* Advance 10ms from max_signal_pos */
+ pos = max_signal_pos + 10 * clock_rate / 1000;
+
+ /* Get the largest signal in the next 800ms */
+ max_signal = 0;
+ max_echo_pos = pos;
+ for (i=pos; i<pos+clock_rate * 8 / 10; ++i) {
+ if (abs(buf[i]) > max_signal) {
+ max_signal = abs(buf[i]);
+ max_echo_pos = i;
+ }
+ }
+
+ lat = (max_echo_pos - max_signal_pos) * 1000 / clock_rate;
+
+#if 0
+ PJ_LOG(4,(THIS_FILE, "Signal at %dms, echo at %d ms, latency %d ms",
+ max_signal_pos * 1000 / clock_rate,
+ max_echo_pos * 1000 / clock_rate,
+ lat));
+#endif
+
+ *lat_sum += lat;
+ (*lat_cnt)++;
+ if (lat < *lat_min)
+ *lat_min = lat;
+ if (lat > *lat_max)
+ *lat_max = lat;
+
+ /* Advance next loop */
+ if (first) {
+ start_pos = max_signal_pos + clock_rate * 9 / 10;
+ first = PJ_FALSE;
+ } else {
+ start_pos += clock_rate;
+ }
+ }
+
+ return 0;
+}
+
+
+static void systest_latency_test(void)
+{
+ const char *ref_wav_paths[] = { add_path(res_path, WAV_TOCK8_PATH), ALT_PATH1 WAV_TOCK8_PATH };
+ pj_str_t rec_wav_file;
+ pjsua_player_id play_id = PJSUA_INVALID_ID;
+ pjsua_conf_port_id play_slot = PJSUA_INVALID_ID;
+ pjsua_recorder_id rec_id = PJSUA_INVALID_ID;
+ pjsua_conf_port_id rec_slot = PJSUA_INVALID_ID;
+ pj_pool_t *pool = NULL;
+ pjmedia_port *wav_port = NULL;
+ unsigned lat_sum=0, lat_cnt=0, lat_min=0, lat_max=0;
+ enum gui_key key;
+ test_item_t *ti;
+ const char *title = "Audio Latency Test";
+ pj_status_t status;
+
+ ti = systest_alloc_test_item(title);
+ if (!ti)
+ return;
+
+ key = gui_msgbox(title,
+ "This test will try to find the audio device's "
+ "latency. We will play a special WAV file to the "
+ "speaker for ten seconds, then at the end "
+ "calculate the latency. Please don't do anything "
+ "until the test is done.", WITH_OKCANCEL);
+ if (key != KEY_OK) {
+ ti->skipped = PJ_TRUE;
+ return;
+ }
+ key = gui_msgbox(title,
+ "For this test to work, we must be able to capture "
+ "the audio played in the speaker (the echo), and only"
+ " that audio (i.e. you must be in relatively quiet "
+ "place to run this test). "
+ "Press OK to start, or CANCEL to skip.",
+ WITH_OKCANCEL);
+ if (key != KEY_OK) {
+ ti->skipped = PJ_TRUE;
+ return;
+ }
+
+ PJ_LOG(3,(THIS_FILE, "Running %s", title));
+
+ status = create_player(PJ_ARRAY_SIZE(ref_wav_paths), ref_wav_paths,
+ &play_id);
+ if (status != PJ_SUCCESS)
+ goto on_return;
+
+ play_slot = pjsua_player_get_conf_port(play_id);
+
+ rec_wav_file = pj_str(add_path(doc_path, WAV_LATENCY_OUT_PATH));
+ status = pjsua_recorder_create(&rec_wav_file, 0, NULL, -1, 0, &rec_id);
+ if (status != PJ_SUCCESS)
+ goto on_return;
+
+ rec_slot = pjsua_recorder_get_conf_port(rec_id);
+
+ /* Setup the test */
+ //status = pjsua_conf_connect(0, 0);
+ status = pjsua_conf_connect(play_slot, 0);
+ status = pjsua_conf_connect(0, rec_slot);
+ status = pjsua_conf_connect(play_slot, rec_slot);
+
+
+ /* We're running */
+ PJ_LOG(3,(THIS_FILE, "Please wait while test is running (~10 sec)"));
+ gui_sleep(10);
+
+ /* Done with the test */
+ //status = pjsua_conf_disconnect(0, 0);
+ status = pjsua_conf_disconnect(play_slot, rec_slot);
+ status = pjsua_conf_disconnect(0, rec_slot);
+ status = pjsua_conf_disconnect(play_slot, 0);
+
+ pjsua_recorder_destroy(rec_id);
+ rec_id = PJSUA_INVALID_ID;
+
+ pjsua_player_destroy(play_id);
+ play_id = PJSUA_INVALID_ID;
+
+ /* Confirm that echo is heard */
+ gui_msgbox(title,
+ "Test is done. Now we need to confirm that we indeed "
+ "captured the echo. We will play the captured audio "
+ "and please confirm that you can hear the 'tock' echo.",
+ WITH_OK);
+
+ status = pjsua_player_create(&rec_wav_file, 0, &play_id);
+ if (status != PJ_SUCCESS)
+ goto on_return;
+
+ play_slot = pjsua_player_get_conf_port(play_id);
+
+ status = pjsua_conf_connect(play_slot, 0);
+ if (status != PJ_SUCCESS)
+ goto on_return;
+
+ key = gui_msgbox(title,
+ "The captured audio is being played back now. "
+ "Can you hear the 'tock' echo?",
+ WITH_YESNO);
+
+ pjsua_player_destroy(play_id);
+ play_id = PJSUA_INVALID_ID;
+
+ if (key != KEY_YES)
+ goto on_return;
+
+ /* Now analyze the latency */
+ pool = pjsua_pool_create("latency", 512, 512);
+
+ status = pjmedia_wav_player_port_create(pool, rec_wav_file.ptr, 0, 0, 0, &wav_port);
+ if (status != PJ_SUCCESS)
+ goto on_return;
+
+ status = calculate_latency(pool, wav_port, &lat_sum, &lat_cnt,
+ &lat_min, &lat_max);
+ if (status != PJ_SUCCESS)
+ goto on_return;
+
+on_return:
+ if (wav_port)
+ pjmedia_port_destroy(wav_port);
+ if (pool)
+ pj_pool_release(pool);
+ if (play_id != PJSUA_INVALID_ID)
+ pjsua_player_destroy(play_id);
+ if (rec_id != PJSUA_INVALID_ID)
+ pjsua_recorder_destroy(rec_id);
+
+ if (status != PJ_SUCCESS) {
+ systest_perror("Sorry we encountered an error: ", status);
+ ti->success = PJ_FALSE;
+ pj_strerror(status, ti->reason, sizeof(ti->reason));
+ } else if (key != KEY_YES) {
+ ti->success = PJ_FALSE;
+ if (!ti->success) {
+ pj_ansi_strcpy(ti->reason, USER_ERROR);
+ }
+ } else {
+ char msg[200];
+ int msglen;
+
+ pj_ansi_snprintf(msg, sizeof(msg),
+ "The sound device latency:\r\n"
+ " Min=%u, Max=%u, Avg=%u\r\n",
+ lat_min, lat_max, lat_sum/lat_cnt);
+ msglen = strlen(msg);
+
+ if (lat_sum/lat_cnt > 500) {
+ pj_ansi_snprintf(msg+msglen, sizeof(msg)-msglen,
+ "The latency is huge!\r\n");
+ msglen = strlen(msg);
+ } else if (lat_sum/lat_cnt > 200) {
+ pj_ansi_snprintf(msg+msglen, sizeof(msg)-msglen,
+ "The latency is quite high\r\n");
+ msglen = strlen(msg);
+ }
+
+ key = gui_msgbox(title, msg, WITH_OK);
+
+ ti->success = PJ_TRUE;
+ pj_ansi_strncpy(ti->reason, msg, sizeof(ti->reason));
+ ti->reason[sizeof(ti->reason)-1] = '\0';
+ }
+}
+
+
+static void systest_aec_test(void)
+{
+ const char *ref_wav_paths[] = { add_path(res_path, WAV_PLAYBACK_PATH),
+ ALT_PATH1 WAV_PLAYBACK_PATH };
+ pjsua_player_id player_id = PJSUA_INVALID_ID;
+ pjsua_recorder_id writer_id = PJSUA_INVALID_ID;
+ enum gui_key key;
+ test_item_t *ti;
+ const char *title = "AEC/AES Test";
+ unsigned last_ec_tail = 0;
+ pj_status_t status;
+ pj_str_t tmp;
+
+ ti = systest_alloc_test_item(title);
+ if (!ti)
+ return;
+
+ key = gui_msgbox(title,
+ "This test will try to find whether the AEC/AES "
+ "works good on this system. Test will play a file "
+ "while recording from mic. The recording will be "
+ "played back later so you can check if echo is there. "
+ "Press OK to start.",
+ WITH_OKCANCEL);
+ if (key != KEY_OK) {
+ ti->skipped = PJ_TRUE;
+ return;
+ }
+
+ /* Save current EC tail */
+ status = pjsua_get_ec_tail(&last_ec_tail);
+ if (status != PJ_SUCCESS)
+ goto on_return;
+
+ /* Set EC tail setting to default */
+ status = pjsua_set_ec(PJSUA_DEFAULT_EC_TAIL_LEN, 0);
+ if (status != PJ_SUCCESS)
+ goto on_return;
+
+ /*
+ * Create player and recorder
+ */
+ status = create_player(PJ_ARRAY_SIZE(ref_wav_paths), ref_wav_paths,
+ &player_id);
+ if (status != PJ_SUCCESS) {
+ PJ_PERROR(1,(THIS_FILE, status, "Error opening WAV file %s",
+ WAV_PLAYBACK_PATH));
+ goto on_return;
+ }
+
+ status = pjsua_recorder_create(
+ pj_cstr(&tmp, add_path(doc_path, AEC_REC_PATH)), 0, 0, -1,
+ 0, &writer_id);
+ if (status != PJ_SUCCESS) {
+ PJ_PERROR(1,(THIS_FILE, status, "Error writing WAV file %s",
+ AEC_REC_PATH));
+ goto on_return;
+ }
+
+ /*
+ * Start playback and recording.
+ */
+ pjsua_conf_connect(pjsua_player_get_conf_port(player_id), 0);
+ pj_thread_sleep(100);
+ pjsua_conf_connect(0, pjsua_recorder_get_conf_port(writer_id));
+
+ /* Wait user signal */
+ gui_msgbox(title, "AEC/AES test is running. Press OK to stop this test.",
+ WITH_OK);
+
+ /*
+ * Stop and close playback and recorder
+ */
+ pjsua_conf_disconnect(0, pjsua_recorder_get_conf_port(writer_id));
+ pjsua_conf_disconnect(pjsua_player_get_conf_port(player_id), 0);
+ pjsua_recorder_destroy(writer_id);
+ pjsua_player_destroy(player_id);
+ player_id = PJSUA_INVALID_ID;
+ writer_id = PJSUA_INVALID_ID;
+
+ /*
+ * Play the result.
+ */
+ status = pjsua_player_create(
+ pj_cstr(&tmp, add_path(doc_path, AEC_REC_PATH)),
+ 0, &player_id);
+ if (status != PJ_SUCCESS) {
+ PJ_PERROR(1,(THIS_FILE, status, "Error opening WAV file %s", AEC_REC_PATH));
+ goto on_return;
+ }
+ pjsua_conf_connect(pjsua_player_get_conf_port(player_id), 0);
+
+ /* Wait user signal */
+ gui_msgbox(title, "We are now playing the captured audio from the mic. "
+ "Check if echo (of the audio played back previously) is "
+ "present in the audio. The recording is stored in "
+ AEC_REC_PATH " for offline analysis. "
+ "Press OK to stop.",
+ WITH_OK);
+
+ pjsua_conf_disconnect(pjsua_player_get_conf_port(player_id), 0);
+
+ key = gui_msgbox(title,
+ "Did you notice any echo in the recording?",
+ WITH_YESNO);
+
+
+on_return:
+ if (player_id != PJSUA_INVALID_ID)
+ pjsua_player_destroy(player_id);
+ if (writer_id != PJSUA_INVALID_ID)
+ pjsua_recorder_destroy(writer_id);
+
+ /* Wait until sound device closed before restoring back EC tail setting */
+ while (pjsua_snd_is_active())
+ pj_thread_sleep(10);
+ pjsua_set_ec(last_ec_tail, 0);
+
+
+ if (status != PJ_SUCCESS) {
+ systest_perror("Sorry we encountered an error: ", status);
+ ti->success = PJ_FALSE;
+ pj_strerror(status, ti->reason, sizeof(ti->reason));
+ } else if (key == KEY_YES) {
+ ti->success = PJ_FALSE;
+ if (!ti->success) {
+ pj_ansi_strcpy(ti->reason, USER_ERROR);
+ }
+ } else {
+ char msg[200];
+
+ pj_ansi_snprintf(msg, sizeof(msg), "Test succeeded.\r\n");
+
+ ti->success = PJ_TRUE;
+ pj_ansi_strncpy(ti->reason, msg, sizeof(ti->reason));
+ ti->reason[sizeof(ti->reason)-1] = '\0';
+ }
+}
+
+
+/****************************************************************************
+ * configurations
+ */
+static void systest_list_audio_devs()
+{
+ unsigned i, dev_count, len=0;
+ pj_status_t status;
+ test_item_t *ti;
+ enum gui_key key;
+ const char *title = "Audio Device List";
+
+ ti = systest_alloc_test_item(title);
+ if (!ti)
+ return;
+
+ PJ_LOG(3,(THIS_FILE, "Running %s", title));
+
+ dev_count = pjmedia_aud_dev_count();
+ if (dev_count == 0) {
+ key = gui_msgbox(title,
+ "No audio devices are found", WITH_OK);
+ ti->success = PJ_FALSE;
+ pj_ansi_strcpy(ti->reason, "No device found");
+ return;
+ }
+
+ pj_ansi_snprintf(ti->reason+len, sizeof(ti->reason)-len,
+ "Found %u devices\r\n", dev_count);
+ len = strlen(ti->reason);
+
+ for (i=0; i<dev_count; ++i) {
+ pjmedia_aud_dev_info info;
+
+ status = pjmedia_aud_dev_get_info(i, &info);
+ if (status != PJ_SUCCESS) {
+ systest_perror("Error retrieving device info: ", status);
+ ti->success = PJ_FALSE;
+ pj_strerror(status, ti->reason, sizeof(ti->reason));
+ return;
+ }
+
+ pj_ansi_snprintf(ti->reason+len, sizeof(ti->reason)-len,
+ " %2d: %s [%s] (%d/%d)\r\n",
+ i, info.driver, info.name,
+ info.input_count, info.output_count);
+ len = strlen(ti->reason);
+ }
+
+ ti->reason[len] = '\0';
+ key = gui_msgbox(title, ti->reason, WITH_OK);
+
+ ti->success = PJ_TRUE;
+}
+
+static void systest_display_settings(void)
+{
+ pjmedia_aud_dev_info di;
+ int len = 0;
+ enum gui_key key;
+ test_item_t *ti;
+ const char *title = "Audio Settings";
+ pj_status_t status;
+
+ ti = systest_alloc_test_item(title);
+ if (!ti)
+ return;
+
+ PJ_LOG(3,(THIS_FILE, "Running %s", title));
+
+ pj_ansi_snprintf(textbuf+len, sizeof(textbuf)-len, "Version: %s\r\n",
+ pj_get_version());
+ len = strlen(textbuf);
+
+ pj_ansi_snprintf(textbuf+len, sizeof(textbuf)-len, "Test clock rate: %d\r\n",
+ systest.media_cfg.clock_rate);
+ len = strlen(textbuf);
+
+ pj_ansi_snprintf(textbuf+len, sizeof(textbuf)-len, "Device clock rate: %d\r\n",
+ systest.media_cfg.snd_clock_rate);
+ len = strlen(textbuf);
+
+ pj_ansi_snprintf(textbuf+len, sizeof(textbuf)-len, "Aud frame ptime: %d\r\n",
+ systest.media_cfg.audio_frame_ptime);
+ len = strlen(textbuf);
+
+ pj_ansi_snprintf(textbuf+len, sizeof(textbuf)-len, "Channel count: %d\r\n",
+ systest.media_cfg.channel_count);
+ len = strlen(textbuf);
+
+ pj_ansi_snprintf(textbuf+len, sizeof(textbuf)-len, "Audio switching: %s\r\n",
+ (PJMEDIA_CONF_USE_SWITCH_BOARD ? "Switchboard" : "Conf bridge"));
+ len = strlen(textbuf);
+
+ pj_ansi_snprintf(textbuf+len, sizeof(textbuf)-len, "Snd buff count: %d\r\n",
+ PJMEDIA_SOUND_BUFFER_COUNT);
+ len = strlen(textbuf);
+
+ /* Capture device */
+ status = pjmedia_aud_dev_get_info(systest.rec_id, &di);
+ if (status != PJ_SUCCESS) {
+ systest_perror("Error querying device info", status);
+ ti->success = PJ_FALSE;
+ pj_strerror(status, ti->reason, sizeof(ti->reason));
+ return;
+ }
+
+ pj_ansi_snprintf(textbuf+len, sizeof(textbuf)-len,
+ "Rec dev : %d (%s) [%s]\r\n",
+ systest.rec_id,
+ di.name,
+ di.driver);
+ len = strlen(textbuf);
+
+ pj_ansi_snprintf(textbuf+len, sizeof(textbuf)-len,
+ "Rec buf : %d msec\r\n",
+ systest.media_cfg.snd_rec_latency);
+ len = strlen(textbuf);
+
+ /* Playback device */
+ status = pjmedia_aud_dev_get_info(systest.play_id, &di);
+ if (status != PJ_SUCCESS) {
+ systest_perror("Error querying device info", status);
+ return;
+ }
+
+ pj_ansi_snprintf(textbuf+len, sizeof(textbuf)-len,
+ "Play dev: %d (%s) [%s]\r\n",
+ systest.play_id,
+ di.name,
+ di.driver);
+ len = strlen(textbuf);
+
+ pj_ansi_snprintf(textbuf+len, sizeof(textbuf)-len,
+ "Play buf: %d msec\r\n",
+ systest.media_cfg.snd_play_latency);
+ len = strlen(textbuf);
+
+ ti->success = PJ_TRUE;
+ pj_ansi_strncpy(ti->reason, textbuf, sizeof(ti->reason));
+ ti->reason[sizeof(ti->reason)-1] = '\0';
+ key = gui_msgbox(title, textbuf, WITH_OK);
+
+}
+
+/*****************************************************************/
+
+int systest_init(void)
+{
+ pjsua_logging_config log_cfg;
+ pj_status_t status = PJ_SUCCESS;
+
+ status = pjsua_create();
+ if (status != PJ_SUCCESS) {
+ systest_perror("Sorry we've had error in pjsua_create(): ", status);
+ return status;
+ }
+
+ pjsua_logging_config_default(&log_cfg);
+ log_cfg.log_filename = pj_str(add_path(doc_path, LOG_OUT_PATH));
+
+ pjsua_config_default(&systest.ua_cfg);
+ pjsua_media_config_default(&systest.media_cfg);
+ systest.media_cfg.clock_rate = TEST_CLOCK_RATE;
+ systest.media_cfg.snd_clock_rate = DEV_CLOCK_RATE;
+ if (OVERRIDE_AUD_FRAME_PTIME)
+ systest.media_cfg.audio_frame_ptime = OVERRIDE_AUD_FRAME_PTIME;
+ systest.media_cfg.channel_count = CHANNEL_COUNT;
+ systest.rec_id = REC_DEV_ID;
+ systest.play_id = PLAY_DEV_ID;
+ systest.media_cfg.ec_tail_len = 0;
+ systest.media_cfg.snd_auto_close_time = 0;
+
+#if defined(OVERRIDE_AUDDEV_PLAY_LAT) && OVERRIDE_AUDDEV_PLAY_LAT!=0
+ systest.media_cfg.snd_play_latency = OVERRIDE_AUDDEV_PLAY_LAT;
+#endif
+
+#if defined(OVERRIDE_AUDDEV_REC_LAT) && OVERRIDE_AUDDEV_REC_LAT!=0
+ systest.media_cfg.snd_rec_latency = OVERRIDE_AUDDEV_REC_LAT;
+#endif
+
+ status = pjsua_init(&systest.ua_cfg, &log_cfg, &systest.media_cfg);
+ if (status != PJ_SUCCESS) {
+ pjsua_destroy();
+ systest_perror("Sorry we've had error in pjsua_init(): ", status);
+ return status;
+ }
+
+ status = pjsua_start();
+ if (status != PJ_SUCCESS) {
+ pjsua_destroy();
+ systest_perror("Sorry we've had error in pjsua_start(): ", status);
+ return status;
+ }
+
+ status = gui_init(&root_menu);
+ if (status != 0)
+ goto on_return;
+
+ return 0;
+
+on_return:
+ gui_destroy();
+ return status;
+}
+
+
+int systest_set_dev(int cap_dev, int play_dev)
+{
+ systest.rec_id = systest_cap_dev_id = cap_dev;
+ systest.play_id = systest_play_dev_id = play_dev;
+ return pjsua_set_snd_dev(cap_dev, play_dev);
+}
+
+static void systest_wizard(void)
+{
+ PJ_LOG(3,(THIS_FILE, "Running test wizard"));
+ systest_list_audio_devs();
+ systest_display_settings();
+ systest_play_tone();
+ systest_play_wav1();
+ systest_rec_audio();
+ systest_audio_test();
+ systest_latency_test();
+ systest_aec_test();
+ gui_msgbox("Test wizard", "Test wizard complete.", WITH_OK);
+}
+
+
+int systest_run(void)
+{
+ gui_start(&root_menu);
+ return 0;
+}
+
+void systest_save_result(const char *filename)
+{
+ unsigned i;
+ pj_oshandle_t fd;
+ pj_time_val tv;
+ pj_parsed_time pt;
+ pj_ssize_t size;
+ const char *text;
+ pj_status_t status;
+
+ status = pj_file_open(NULL, filename, PJ_O_WRONLY | PJ_O_APPEND, &fd);
+ if (status != PJ_SUCCESS) {
+ pj_ansi_snprintf(textbuf, sizeof(textbuf),
+ "Error opening file %s",
+ filename);
+ systest_perror(textbuf, status);
+ return;
+ }
+
+ text = "\r\n\r\nPJSYSTEST Report\r\n";
+ size = strlen(text);
+ pj_file_write(fd, text, &size);
+
+ /* Put timestamp */
+ pj_gettimeofday(&tv);
+ if (pj_time_decode(&tv, &pt) == PJ_SUCCESS) {
+ pj_ansi_snprintf(textbuf, sizeof(textbuf),
+ "Time: %04d/%02d/%02d %02d:%02d:%02d\r\n",
+ pt.year, pt.mon+1, pt.day,
+ pt.hour, pt.min, pt.sec);
+ size = strlen(textbuf);
+ pj_file_write(fd, textbuf, &size);
+ }
+
+ pj_ansi_snprintf(textbuf, sizeof(textbuf),
+ "Tests invoked: %u\r\n"
+ "-----------------------------------------------\r\n",
+ test_item_count);
+ size = strlen(textbuf);
+ pj_file_write(fd, textbuf, &size);
+
+ for (i=0; i<test_item_count; ++i) {
+ test_item_t *ti = &test_items[i];
+ pj_ansi_snprintf(textbuf, sizeof(textbuf),
+ "\r\nTEST %d: %s %s\r\n",
+ i, ti->title,
+ (ti->skipped? "Skipped" : (ti->success ? "Success" : "Failed")));
+ size = strlen(textbuf);
+ pj_file_write(fd, textbuf, &size);
+
+ size = strlen(ti->reason);
+ pj_file_write(fd, ti->reason, &size);
+
+ size = 2;
+ pj_file_write(fd, "\r\n", &size);
+ }
+
+
+ pj_file_close(fd);
+
+ pj_ansi_snprintf(textbuf, sizeof(textbuf),
+ "Test result successfully appended to file %s",
+ filename);
+ gui_msgbox("Test result saved", textbuf, WITH_OK);
+}
+
+void systest_deinit(void)
+{
+ gui_destroy();
+ pjsua_destroy();
+}
+
diff --git a/pjsip-apps/src/pjsystest/systest.h b/pjsip-apps/src/pjsystest/systest.h
new file mode 100644
index 0000000..9b5aadb
--- /dev/null
+++ b/pjsip-apps/src/pjsystest/systest.h
@@ -0,0 +1,106 @@
+/* $Id: systest.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __SYSTEST_H__
+#define __SYSTEST_H__
+
+#include <pjlib.h>
+
+/*
+ * Overrideable parameters
+ */
+#define REC_DEV_ID systest_cap_dev_id
+#define PLAY_DEV_ID systest_play_dev_id
+//#define REC_DEV_ID 5
+//#define PLAY_DEV_ID 5
+#define OVERRIDE_AUDDEV_REC_LAT 0
+#define OVERRIDE_AUDDEV_PLAY_LAT 0
+#define OVERRIDE_AUD_FRAME_PTIME 0
+
+/* Don't change this */
+#define CHANNEL_COUNT 1
+
+/* If you change CLOCK_RATE then the input WAV files need to be
+ * changed, so normally don't need to change this.
+ */
+#define TEST_CLOCK_RATE 8000
+
+/* You may change sound device's clock rate as long as resampling
+ * is enabled.
+ */
+#define DEV_CLOCK_RATE 8000
+
+
+#if defined(PJ_WIN32_WINCE) && PJ_WIN32_WINCE
+ #define LOG_OUT_PATH "\\PJSYSTEST.TXT"
+ #define RESULT_OUT_PATH "\\PJSYSTEST_RESULT.TXT"
+ #define WAV_PLAYBACK_PATH "\\Program Files\\pjsystest\\input.8.wav"
+ #define WAV_REC_OUT_PATH "\\PJSYSTEST_TESTREC.WAV"
+ #define WAV_TOCK8_PATH "\\Program Files\\pjsystest\\tock8.WAV"
+ #define WAV_LATENCY_OUT_PATH "\\PJSYSTEST_LATREC.WAV"
+ #define ALT_PATH1 ""
+ #define AEC_REC_PATH "\\PJSYSTEST_AECREC.WAV"
+#else
+ #define LOG_OUT_PATH "PJSYSTEST.TXT"
+ #define RESULT_OUT_PATH "PJSYSTEST_RESULT.TXT"
+ #define WAV_PLAYBACK_PATH "input.8.wav"
+ #define WAV_REC_OUT_PATH "PJSYSTEST_TESTREC.WAV"
+ #define WAV_TOCK8_PATH "tock8.wav"
+ #define WAV_LATENCY_OUT_PATH "PJSYSTEST_LATREC.WAV"
+ #define ALT_PATH1 "../../tests/pjsua/wavs/"
+ #define AEC_REC_PATH "PJSYSTEST_AECREC.WAV"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* API, to be called by main() */
+int systest_init(void);
+int systest_set_dev(int cap_dev, int play_dev);
+int systest_run(void);
+void systest_save_result(const char *filename);
+void systest_deinit(void);
+
+/* Device ID to test */
+extern int systest_cap_dev_id;
+extern int systest_play_dev_id;
+
+/* Test item is used to record the test result */
+typedef struct test_item_t
+{
+ char title[80];
+ pj_bool_t skipped;
+ pj_bool_t success;
+ char reason[1024];
+} test_item_t;
+
+#define SYSTEST_MAX_TEST 32
+extern unsigned test_item_count;
+extern test_item_t test_items[SYSTEST_MAX_TEST];
+#define PATH_LENGTH PJ_MAXPATH
+extern char doc_path[PATH_LENGTH];
+extern char res_path[PATH_LENGTH];
+
+test_item_t *systest_alloc_test_item(const char *title);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SYSTEST_H__ */
diff --git a/pjsip-apps/src/pocketpj/PocketPJ.cpp b/pjsip-apps/src/pocketpj/PocketPJ.cpp
new file mode 100644
index 0000000..2d42d96
--- /dev/null
+++ b/pjsip-apps/src/pocketpj/PocketPJ.cpp
@@ -0,0 +1,66 @@
+// PocketPJ.cpp : Defines the class behaviors for the application.
+//
+
+#include "stdafx.h"
+#include "PocketPJ.h"
+#include "PocketPJDlg.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CPocketPJApp
+
+BEGIN_MESSAGE_MAP(CPocketPJApp, CWinApp)
+ //{{AFX_MSG_MAP(CPocketPJApp)
+ // NOTE - the ClassWizard will add and remove mapping macros here.
+ // DO NOT EDIT what you see in these blocks of generated code!
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CPocketPJApp construction
+
+CPocketPJApp::CPocketPJApp()
+ : CWinApp()
+{
+ // TODO: add construction code here,
+ // Place all significant initialization in InitInstance
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// The one and only CPocketPJApp object
+
+CPocketPJApp theApp;
+
+/////////////////////////////////////////////////////////////////////////////
+// CPocketPJApp initialization
+
+BOOL CPocketPJApp::InitInstance()
+{
+ // Standard initialization
+ // If you are not using these features and wish to reduce the size
+ // of your final executable, you should remove from the following
+ // the specific initialization routines you do not need.
+
+ CPocketPJDlg dlg;
+ m_pMainWnd = &dlg;
+ int nResponse = dlg.DoModal();
+ if (nResponse == IDOK)
+ {
+ // TODO: Place code here to handle when the dialog is
+ // dismissed with OK
+ }
+ else if (nResponse == IDCANCEL)
+ {
+ // TODO: Place code here to handle when the dialog is
+ // dismissed with Cancel
+ }
+
+ // Since the dialog has been closed, return FALSE so that we exit the
+ // application, rather than start the application's message pump.
+ return FALSE;
+}
diff --git a/pjsip-apps/src/pocketpj/PocketPJ.h b/pjsip-apps/src/pocketpj/PocketPJ.h
new file mode 100644
index 0000000..eb53152
--- /dev/null
+++ b/pjsip-apps/src/pocketpj/PocketPJ.h
@@ -0,0 +1,49 @@
+// PocketPJ.h : main header file for the POCKETPJ application
+//
+
+#if !defined(AFX_POCKETPJ_H__D90320F8_01F9_4F5C_8655_13CF2FFDDF48__INCLUDED_)
+#define AFX_POCKETPJ_H__D90320F8_01F9_4F5C_8655_13CF2FFDDF48__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+#ifndef __AFXWIN_H__
+ #error include 'stdafx.h' before including this file for PCH
+#endif
+
+#include "resource.h" // main symbols
+
+/////////////////////////////////////////////////////////////////////////////
+// CPocketPJApp:
+// See PocketPJ.cpp for the implementation of this class
+//
+
+class CPocketPJApp : public CWinApp
+{
+public:
+ CPocketPJApp();
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CPocketPJApp)
+ public:
+ virtual BOOL InitInstance();
+ //}}AFX_VIRTUAL
+
+// Implementation
+
+ //{{AFX_MSG(CPocketPJApp)
+ // NOTE - the ClassWizard will add and remove member functions here.
+ // DO NOT EDIT what you see in these blocks of generated code !
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft eMbedded Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_POCKETPJ_H__D90320F8_01F9_4F5C_8655_13CF2FFDDF48__INCLUDED_)
diff --git a/pjsip-apps/src/pocketpj/PocketPJ.rc b/pjsip-apps/src/pocketpj/PocketPJ.rc
new file mode 100644
index 0000000..8972974
--- /dev/null
+++ b/pjsip-apps/src/pocketpj/PocketPJ.rc
@@ -0,0 +1,316 @@
+//Microsoft eMbedded Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+#include "newres.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 ""afxres.h""\r\n"
+ "#include ""newres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#define _AFX_NO_SPLITTER_RESOURCES\r\n"
+ "#define _AFX_NO_OLE_RESOURCES\r\n"
+ "#define _AFX_NO_TRACKER_RESOURCES\r\n"
+ "#define _AFX_NO_PROPERTY_RESOURCES\r\n"
+ "\r\n"
+ "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n"
+ "#ifdef _WIN32\r\n"
+ "LANGUAGE 9, 1\r\n"
+ "#pragma code_page(1252)\r\n"
+ "#endif //_WIN32\r\n"
+ "#include ""res\\PocketPJ.rc2"" // non-Microsoft eMbedded Visual C++ edited resources\r\n"
+ "#include ""afxres.rc"" // Standard components\r\n"
+ "#include ""wceres.rc"" // WCE-specific components\r\n"
+ "#endif\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDR_MAINFRAME ICON DISCARDABLE "res\\PocketPJ.ico"
+IDI_ONLINE ICON DISCARDABLE "res\\online.ico"
+IDI_OFFLINE ICON DISCARDABLE "res\\offline.ico"
+IDI_INVISIBLE ICON DISCARDABLE "res\\invisibl.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_POCKETPJ_DIALOG DIALOGEX 0, 0, 139, 151
+STYLE WS_POPUP | WS_VISIBLE | WS_CAPTION
+EXSTYLE WS_EX_APPWINDOW | 0x80000000L
+CAPTION "PocketPJ"
+FONT 8, "System"
+BEGIN
+ LTEXT "sip:user@pjsip.lab",IDC_ACC_ID,22,5,115,8
+ CONTROL 135,IDC_BTN_ACC,"Static",SS_BITMAP | SS_NOTIFY |
+ WS_BORDER | WS_TABSTOP,7,3,12,11
+ CONTROL "List1",IDC_BUDDY_LIST,"SysListView32",LVS_SMALLICON |
+ LVS_SINGLESEL | LVS_SORTASCENDING | WS_BORDER |
+ WS_TABSTOP,7,35,127,109
+ LTEXT "URL:",IDC_STATIC,7,19,16,8
+ EDITTEXT IDC_URL,25,16,97,12,ES_AUTOHSCROLL
+ CONTROL 138,IDC_BTN_ACTION,"Static",SS_BITMAP | SS_NOTIFY |
+ WS_BORDER,125,16,12,11
+END
+
+IDD_SETTING DIALOG DISCARDABLE 0, 0, 140, 143
+STYLE WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "PocketPJ Settings.."
+FONT 8, "System"
+BEGIN
+ EDITTEXT IDC_DOMAIN,38,7,78,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_USER,38,21,78,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_PASSWD,38,35,78,12,ES_PASSWORD | ES_AUTOHSCROLL
+ EDITTEXT IDC_DNS,38,49,78,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_STUN_SRV,56,64,77,12,ES_AUTOHSCROLL
+ CONTROL "ICE",IDC_ICE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,79,
+ 24,10
+ CONTROL "TCP",IDC_TCP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,33,
+ 79,24,10
+ CONTROL "SRTP",IDC_SRTP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,61,
+ 79,29,10
+ CONTROL "PUBLISH",IDC_PUBLISH,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,93,79,40,10
+ CONTROL "EC, tail:",IDC_ECHO_SUPPRESS,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,7,92,37,10
+ EDITTEXT IDC_EC_TAIL,47,91,23,12,ES_AUTOHSCROLL
+ CONTROL "VAD",IDC_VAD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,93,
+ 92,25,10
+ COMBOBOX IDC_CODECS,59,105,42,39,CBS_DROPDOWNLIST | WS_VSCROLL |
+ WS_TABSTOP
+ PUSHBUTTON "OK",IDOK,17,122,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,73,122,50,14
+ LTEXT "Domain:",IDC_STATIC,7,8,30,9
+ LTEXT "User:",IDC_STATIC,7,22,30,9
+ LTEXT "Passwd:",IDC_STATIC,7,36,30,9
+ CONTROL "STUN Srv:",IDC_STUN,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,7,65,47,10
+ LTEXT "DNS:",IDC_STATIC,8,50,30,9
+ LTEXT "ms",IDC_STATIC,75,92,13,9
+ LTEXT "Codec priority:",IDC_STATIC,7,107,49,9
+ CONTROL "AA",IDC_AA,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,107,
+ 107,25,10
+END
+
+
+#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 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904B0"
+ BEGIN
+ VALUE "CompanyName", "HP\0"
+ VALUE "FileDescription", "PocketPJ WCE MFC Application\0"
+ VALUE "FileVersion", "1, 0, 0, 1\0"
+ VALUE "InternalName", "PocketPJ\0"
+ VALUE "LegalCopyright", "Copyright © 2008\0"
+ VALUE "LegalTrademarks", "\0"
+ VALUE "OriginalFilename", "PocketPJ.exe\0"
+ VALUE "ProductName", "PocketPJ Application\0"
+ VALUE "ProductVersion", "1, 0, 0, 1\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
+#endif // !_MAC
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ IDD_POCKETPJ_DIALOG, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 137
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 144
+ HORZGUIDE, 28
+ END
+
+ IDD_SETTING, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 133
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 136
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Bitmap
+//
+
+IDB_ONLINE BITMAP DISCARDABLE "res\\online.bmp"
+IDB_OFFLINE BITMAP DISCARDABLE "res\\offline.bmp"
+IDB_INVISIBLE BITMAP DISCARDABLE "res\\invisibl.bmp"
+IDB_ACTION BITMAP DISCARDABLE "res\\action.bmp"
+IDB_BLANK BITMAP DISCARDABLE "res\\blank.bmp"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menubar
+//
+
+IDR_ACC_MENU MENU DISCARDABLE
+BEGIN
+ POPUP "Set Online Status:"
+ BEGIN
+ MENUITEM "&Online", IDC_ACC_ONLINE
+ MENUITEM "&Invisible", IDC_ACC_INVISIBLE
+ MENUITEM SEPARATOR
+ MENUITEM "&Settings...", IDC_ACC_SETTINGS
+ MENUITEM SEPARATOR
+ MENUITEM "E&xit", IDOK
+ END
+END
+
+IDR_URI_MENU MENU DISCARDABLE
+BEGIN
+ POPUP "URI Action"
+ BEGIN
+ MENUITEM "&Call...", IDC_URI_CALL
+ MENUITEM "Add to Buddy List", IDC_URI_ADD_BUDDY
+ MENUITEM "&Del Buddy", IDC_URI_DEL_BUDDY
+ END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Data
+//
+
+IDR_ACC_MENU SHMENUBAR DISCARDABLE
+BEGIN
+ IDR_ACC_MENU, 1,
+ I_IMAGENONE, IDC_MENU1, TBSTATE_ENABLED,
+ TBSTYLE_DROPDOWN | TBSTYLE_AUTOSIZE, IDS_CAP_MENUITEM32786, 0, 0,
+END
+
+IDR_URI_MENU SHMENUBAR DISCARDABLE
+BEGIN
+ IDR_URI_MENU, 1,
+ I_IMAGENONE, IDC_MENU2, TBSTATE_ENABLED,
+ TBSTYLE_DROPDOWN | TBSTYLE_AUTOSIZE, IDS_CAP_MENUITEM32790, 0, 0,
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_CAP_ONLINE "Online"
+ IDS_CAP_OFFLINE "Offline"
+ IDS_CAP_INVISIBLE "Invisible"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_CAP_MENUITEM32786 "Set Online Status:"
+ IDS_CAP_MENUITEM32790 "URI Action"
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+#define _AFX_NO_SPLITTER_RESOURCES
+#define _AFX_NO_OLE_RESOURCES
+#define _AFX_NO_TRACKER_RESOURCES
+#define _AFX_NO_PROPERTY_RESOURCES
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE 9, 1
+#pragma code_page(1252)
+#endif //_WIN32
+#include "res\PocketPJ.rc2" // non-Microsoft eMbedded Visual C++ edited resources
+#include "afxres.rc" // Standard components
+// #include "wceres.rc" // WCE-specific components
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/pjsip-apps/src/pocketpj/PocketPJ.vcc b/pjsip-apps/src/pocketpj/PocketPJ.vcc
new file mode 100644
index 0000000..5320b2d
--- /dev/null
+++ b/pjsip-apps/src/pocketpj/PocketPJ.vcc
@@ -0,0 +1,102 @@
+; CLW file contains information for the MFC ClassWizard
+
+[General Info]
+Version=1
+LastClass=CSettingsDlg
+LastTemplate=CDialog
+NewFileInclude1=#include "stdafx.h"
+NewFileInclude2=#include "PocketPJ.h"
+
+ClassCount=3
+Class1=CPocketPJApp
+Class2=CPocketPJDlg
+
+ResourceCount=5
+Resource2=IDR_ACC_MENU
+Resource3=IDD_POCKETPJ_DIALOG
+Resource4=IDD_SETTING
+Resource1=IDR_MAINFRAME
+Class3=CSettingsDlg
+Resource5=IDR_URI_MENU
+
+[CLS:CPocketPJApp]
+Type=0
+HeaderFile=PocketPJ.h
+ImplementationFile=PocketPJ.cpp
+Filter=N
+
+[CLS:CPocketPJDlg]
+Type=0
+HeaderFile=PocketPJDlg.h
+ImplementationFile=PocketPJDlg.cpp
+Filter=D
+BaseClass=CDialog
+VirtualFilter=dWC
+LastObject=CPocketPJDlg
+
+
+[DLG:IDD_POCKETPJ_DIALOG]
+Type=1
+Class=CPocketPJDlg
+ControlCount=6
+Control1=IDC_ACC_ID,static,1342308352
+Control2=IDC_BTN_ACC,static,1350631694
+Control3=IDC_BUDDY_LIST,SysListView32,1350631446
+Control4=IDC_STATIC,static,1342308352
+Control5=IDC_URL,edit,1350631552
+Control6=IDC_BTN_ACTION,static,1350566158
+
+[MNU:IDR_ACC_MENU]
+Type=1
+Class=CPocketPJDlg
+Command1=IDC_ACC_ONLINE
+Command2=IDC_ACC_INVISIBLE
+Command3=IDC_ACC_SETTINGS
+Command4=IDOK
+CommandCount=4
+
+[MNU:IDR_URI_MENU]
+Type=1
+Class=CPocketPJDlg
+Command1=IDC_URI_CALL
+Command2=IDC_URI_ADD_BUDDY
+Command3=IDC_URI_DEL_BUDDY
+CommandCount=3
+
+[DLG:IDD_SETTING]
+Type=1
+Class=CSettingsDlg
+ControlCount=23
+Control1=IDC_DOMAIN,edit,1350631552
+Control2=IDC_USER,edit,1350631552
+Control3=IDC_PASSWD,edit,1350631584
+Control4=IDC_DNS,edit,1350631552
+Control5=IDC_STUN_SRV,edit,1350631552
+Control6=IDC_ICE,button,1342242819
+Control7=IDC_TCP,button,1342242819
+Control8=IDC_SRTP,button,1342242819
+Control9=IDC_PUBLISH,button,1342242819
+Control10=IDC_ECHO_SUPPRESS,button,1342242819
+Control11=IDC_EC_TAIL,edit,1350631552
+Control12=IDC_VAD,button,1342242819
+Control13=IDC_CODECS,combobox,1344339971
+Control14=IDOK,button,1342242816
+Control15=IDCANCEL,button,1342242816
+Control16=IDC_STATIC,static,1342308352
+Control17=IDC_STATIC,static,1342308352
+Control18=IDC_STATIC,static,1342308352
+Control19=IDC_STUN,button,1342242819
+Control20=IDC_STATIC,static,1342308352
+Control21=IDC_STATIC,static,1342308352
+Control22=IDC_STATIC,static,1342308352
+Control23=IDC_AA,button,1342242819
+
+[CLS:CSettingsDlg]
+Type=0
+HeaderFile=SettingsDlg.h
+ImplementationFile=SettingsDlg.cpp
+BaseClass=CDialog
+Filter=D
+VirtualFilter=dWC
+LastObject=CSettingsDlg
+
diff --git a/pjsip-apps/src/pocketpj/PocketPJ.vcp b/pjsip-apps/src/pocketpj/PocketPJ.vcp
new file mode 100644
index 0000000..071cc15
--- /dev/null
+++ b/pjsip-apps/src/pocketpj/PocketPJ.vcp
@@ -0,0 +1,1923 @@
+# Microsoft eMbedded Visual Tools Project File - Name="PocketPJ" - Package Owner=<4>
+# Microsoft eMbedded Visual Tools Generated Build File, Format Version 6.02
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (WCE ARMV4) Application" 0xa301
+# TARGTYPE "Win32 (WCE emulator) Application" 0xa601
+
+CFG=PocketPJ - Win32 (WCE emulator) 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 "PocketPJ.vcn".
+!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 "PocketPJ.vcn" CFG="PocketPJ - Win32 (WCE emulator) Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "PocketPJ - Win32 (WCE emulator) Release" (based on "Win32 (WCE emulator) Application")
+!MESSAGE "PocketPJ - Win32 (WCE emulator) Debug" (based on "Win32 (WCE emulator) Application")
+!MESSAGE "PocketPJ - Win32 (WCE ARMV4) Release" (based on "Win32 (WCE ARMV4) Application")
+!MESSAGE "PocketPJ - Win32 (WCE ARMV4) Debug" (based on "Win32 (WCE ARMV4) Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+# PROP ATL_Project 2
+
+!IF "$(CFG)" == "PocketPJ - Win32 (WCE emulator) Release"
+
+# PROP BASE Use_MFC 2
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "emulatorRel"
+# PROP BASE Intermediate_Dir "emulatorRel"
+# PROP BASE CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}"
+# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 2
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "emulatorRel"
+# PROP Intermediate_Dir "emulatorRel"
+# PROP CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}"
+# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP Target_Dir ""
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "NDEBUG" /d "$(CePlatform)" /d "_X86_" /d "x86" /d "_i386_" /d "_AFXDLL" /r
+# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "NDEBUG" /d "$(CePlatform)" /d "_X86_" /d "x86" /d "_i386_" /d "_AFXDLL" /r
+CPP=cl.exe
+# ADD BASE CPP /nologo /W3 /D "_i386_" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /D "NDEBUG" /D "_WIN32_WCE_CEPC" /D "_AFXDLL" /Yu"stdafx.h" /Gs8192 /GF /O2 /c
+# ADD CPP /nologo /W3 /D "_i386_" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /D "NDEBUG" /D "_WIN32_WCE_CEPC" /D "_AFXDLL" /Yu"stdafx.h" /Gs8192 /GF /O2 /c
+MTL=midl.exe
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"wWinMainCRTStartup" /subsystem:$(CESubsystem) /MACHINE:IX86
+# ADD LINK32 /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"wWinMainCRTStartup" /subsystem:$(CESubsystem) /MACHINE:IX86
+
+!ELSEIF "$(CFG)" == "PocketPJ - Win32 (WCE emulator) Debug"
+
+# PROP BASE Use_MFC 2
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "emulatorDbg"
+# PROP BASE Intermediate_Dir "emulatorDbg"
+# PROP BASE CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}"
+# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 2
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "emulatorDbg"
+# PROP Intermediate_Dir "emulatorDbg"
+# PROP CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}"
+# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "DEBUG" /d "$(CePlatform)" /d "_X86_" /d "x86" /d "_i386_" /d "_AFXDLL" /r
+# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "DEBUG" /d "$(CePlatform)" /d "_X86_" /d "x86" /d "_i386_" /d "_AFXDLL" /r
+CPP=cl.exe
+# ADD BASE CPP /nologo /W3 /Zi /Od /D "DEBUG" /D "_i386_" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /D "_WIN32_WCE_CEPC" /D "_AFXDLL" /Yu"stdafx.h" /Gs8192 /GF /c
+# ADD CPP /nologo /W3 /Zi /Od /I "../../../pjlib/include" /I "../../../pjlib-util/include" /I "../../../pjnath/include" /I "../../../pjmedia/include" /I "../../../pjsip/include" /D "DEBUG" /D "_i386_" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /D "_WIN32_WCE_CEPC" /D "_AFXDLL" /FR /Yu"stdafx.h" /Gs8192 /GF /c
+MTL=midl.exe
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"wWinMainCRTStartup" /debug /subsystem:$(CESubsystem) /MACHINE:IX86
+# ADD LINK32 commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"wWinMainCRTStartup" /debug /subsystem:$(CESubsystem) /MACHINE:IX86
+
+!ELSEIF "$(CFG)" == "PocketPJ - Win32 (WCE ARMV4) Release"
+
+# PROP BASE Use_MFC 2
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "ARMV4Rel"
+# PROP BASE Intermediate_Dir "ARMV4Rel"
+# PROP BASE CPU_ID "{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}"
+# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 2
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "ARMV4Rel"
+# PROP Intermediate_Dir "ARMV4Rel"
+# PROP CPU_ID "{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}"
+# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "NDEBUG" /d "UNICODE" /d "_UNICODE" /d "$(CePlatform)" /d "ARM" /d "_ARM_" /d "ARMV4" /d "_AFXDLL" /r
+# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "NDEBUG" /d "UNICODE" /d "_UNICODE" /d "$(CePlatform)" /d "ARM" /d "_ARM_" /d "ARMV4" /d "_AFXDLL" /r
+CPP=clarm.exe
+# ADD BASE CPP /nologo /W3 /D "ARM" /D "_ARM_" /D "ARMV4" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "UNICODE" /D "_UNICODE" /D "NDEBUG" /D "_AFXDLL" /Yu"stdafx.h" /O2 /M$(CECrtMT) /c
+# ADD CPP /nologo /W3 /I "../../../pjlib/include" /I "../../../pjlib-util/include" /I "../../../pjnath/include" /I "../../../pjmedia/include" /I "../../../pjsip/include" /D "ARM" /D "_ARM_" /D "ARMV4" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "UNICODE" /D "_UNICODE" /D "NDEBUG" /D "_AFXDLL" /Yu"stdafx.h" /O2 /M$(CECrtMT) /c
+MTL=midl.exe
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"wWinMainCRTStartup" /subsystem:$(CESubsystem) /align:"4096" /MACHINE:ARM
+# ADD LINK32 commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"wWinMainCRTStartup" /subsystem:$(CESubsystem) /align:"4096" /MACHINE:ARM
+
+!ELSEIF "$(CFG)" == "PocketPJ - Win32 (WCE ARMV4) Debug"
+
+# PROP BASE Use_MFC 2
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "ARMV4Dbg"
+# PROP BASE Intermediate_Dir "ARMV4Dbg"
+# PROP BASE CPU_ID "{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}"
+# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 2
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "ARMV4Dbg"
+# PROP Intermediate_Dir "ARMV4Dbg"
+# PROP CPU_ID "{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}"
+# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "DEBUG" /d "UNICODE" /d "_UNICODE" /d "$(CePlatform)" /d "ARM" /d "_ARM_" /d "ARMV4" /d "_AFXDLL" /r
+# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "DEBUG" /d "UNICODE" /d "_UNICODE" /d "$(CePlatform)" /d "ARM" /d "_ARM_" /d "ARMV4" /d "_AFXDLL" /r
+CPP=clarm.exe
+# ADD BASE CPP /nologo /W3 /Zi /Od /D "DEBUG" /D "ARM" /D "_ARM_" /D "ARMV4" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "UNICODE" /D "_UNICODE" /D "_AFXDLL" /Yu"stdafx.h" /M$(CECrtMTDebug) /c
+# ADD CPP /nologo /W3 /Zi /Od /I "../../../pjlib/include" /I "../../../pjlib-util/include" /I "../../../pjnath/include" /I "../../../pjmedia/include" /I "../../../pjsip/include" /D "DEBUG" /D "ARM" /D "_ARM_" /D "ARMV4" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "UNICODE" /D "_UNICODE" /D "_AFXDLL" /FR /Yu"stdafx.h" /M$(CECrtMTDebug) /c
+MTL=midl.exe
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"wWinMainCRTStartup" /debug /subsystem:$(CESubsystem) /align:"4096" /MACHINE:ARM
+# ADD LINK32 commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"wWinMainCRTStartup" /debug /subsystem:$(CESubsystem) /align:"4096" /MACHINE:ARM
+
+!ENDIF
+
+# Begin Target
+
+# Name "PocketPJ - Win32 (WCE emulator) Release"
+# Name "PocketPJ - Win32 (WCE emulator) Debug"
+# Name "PocketPJ - Win32 (WCE ARMV4) Release"
+# Name "PocketPJ - Win32 (WCE ARMV4) Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\PocketPJ.cpp
+
+!IF "$(CFG)" == "PocketPJ - Win32 (WCE emulator) Release"
+
+DEP_CPP_POCKE=\
+ ".\PocketPJ.h"\
+ ".\PocketPJDlg.h"\
+ ".\StdAfx.h"\
+
+
+!ELSEIF "$(CFG)" == "PocketPJ - Win32 (WCE emulator) Debug"
+
+DEP_CPP_POCKE=\
+ "..\..\..\pjlib-util\include\pjlib-util.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\base64.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\config.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\crc32.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\dns.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\errno.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\getopt.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\hmac_md5.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\hmac_sha1.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\md5.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\pcap.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\resolver.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\scanner.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\scanner_cis_bitwise.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\scanner_cis_uint.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\sha1.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\srv_resolver.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\stun_simple.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\types.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\xml.h"\
+ "..\..\..\pjlib\include\pj\addr_resolv.h"\
+ "..\..\..\pjlib\include\pj\array.h"\
+ "..\..\..\pjlib\include\pj\assert.h"\
+ "..\..\..\pjlib\include\pj\compat\assert.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_armcc.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_codew.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_gcce.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_mwcc.h"\
+ "..\..\..\pjlib\include\pj\compat\ctype.h"\
+ "..\..\..\pjlib\include\pj\compat\errno.h"\
+ "..\..\..\pjlib\include\pj\compat\high_precision.h"\
+ "..\..\..\pjlib\include\pj\compat\m_auto.h"\
+ "..\..\..\pjlib\include\pj\compat\os_auto.h"\
+ "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\
+ "..\..\..\pjlib\include\pj\compat\os_linux.h"\
+ "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\
+ "..\..\..\pjlib\include\pj\compat\os_palmos.h"\
+ "..\..\..\pjlib\include\pj\compat\os_rtems.h"\
+ "..\..\..\pjlib\include\pj\compat\os_sunos.h"\
+ "..\..\..\pjlib\include\pj\compat\os_symbian.h"\
+ "..\..\..\pjlib\include\pj\compat\os_win32.h"\
+ "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\
+ "..\..\..\pjlib\include\pj\compat\setjmp.h"\
+ "..\..\..\pjlib\include\pj\compat\size_t.h"\
+ "..\..\..\pjlib\include\pj\compat\stdarg.h"\
+ "..\..\..\pjlib\include\pj\compat\string.h"\
+ "..\..\..\pjlib\include\pj\config.h"\
+ "..\..\..\pjlib\include\pj\config_site.h"\
+ "..\..\..\pjlib\include\pj\config_site_sample.h"\
+ "..\..\..\pjlib\include\pj\ctype.h"\
+ "..\..\..\pjlib\include\pj\errno.h"\
+ "..\..\..\pjlib\include\pj\except.h"\
+ "..\..\..\pjlib\include\pj\fifobuf.h"\
+ "..\..\..\pjlib\include\pj\file_access.h"\
+ "..\..\..\pjlib\include\pj\file_io.h"\
+ "..\..\..\pjlib\include\pj\guid.h"\
+ "..\..\..\pjlib\include\pj\hash.h"\
+ "..\..\..\pjlib\include\pj\ioqueue.h"\
+ "..\..\..\pjlib\include\pj\ip_helper.h"\
+ "..\..\..\pjlib\include\pj\list.h"\
+ "..\..\..\pjlib\include\pj\list_i.h"\
+ "..\..\..\pjlib\include\pj\lock.h"\
+ "..\..\..\pjlib\include\pj\log.h"\
+ "..\..\..\pjlib\include\pj\os.h"\
+ "..\..\..\pjlib\include\pj\pool.h"\
+ "..\..\..\pjlib\include\pj\pool_alt.h"\
+ "..\..\..\pjlib\include\pj\pool_buf.h"\
+ "..\..\..\pjlib\include\pj\pool_i.h"\
+ "..\..\..\pjlib\include\pj\rand.h"\
+ "..\..\..\pjlib\include\pj\rbtree.h"\
+ "..\..\..\pjlib\include\pj\sock.h"\
+ "..\..\..\pjlib\include\pj\sock_select.h"\
+ "..\..\..\pjlib\include\pj\string.h"\
+ "..\..\..\pjlib\include\pj\string_i.h"\
+ "..\..\..\pjlib\include\pj\timer.h"\
+ "..\..\..\pjlib\include\pj\types.h"\
+ "..\..\..\pjlib\include\pj\unicode.h"\
+ "..\..\..\pjlib\include\pjlib.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\config.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\config_auto.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\gsm.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\ilbc.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\l16.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\speex.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\types.h"\
+ "..\..\..\pjmedia\include\pjmedia.h"\
+ "..\..\..\pjmedia\include\pjmedia\alaw_ulaw.h"\
+ "..\..\..\pjmedia\include\pjmedia\bidirectional.h"\
+ "..\..\..\pjmedia\include\pjmedia\clock.h"\
+ "..\..\..\pjmedia\include\pjmedia\codec.h"\
+ "..\..\..\pjmedia\include\pjmedia\conference.h"\
+ "..\..\..\pjmedia\include\pjmedia\config.h"\
+ "..\..\..\pjmedia\include\pjmedia\config_auto.h"\
+ "..\..\..\pjmedia\include\pjmedia\echo.h"\
+ "..\..\..\pjmedia\include\pjmedia\echo_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\endpoint.h"\
+ "..\..\..\pjmedia\include\pjmedia\errno.h"\
+ "..\..\..\pjmedia\include\pjmedia\g711.h"\
+ "..\..\..\pjmedia\include\pjmedia\jbuf.h"\
+ "..\..\..\pjmedia\include\pjmedia\master_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\mem_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\null_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\plc.h"\
+ "..\..\..\pjmedia\include\pjmedia\port.h"\
+ "..\..\..\pjmedia\include\pjmedia\resample.h"\
+ "..\..\..\pjmedia\include\pjmedia\rtcp.h"\
+ "..\..\..\pjmedia\include\pjmedia\rtp.h"\
+ "..\..\..\pjmedia\include\pjmedia\sdp.h"\
+ "..\..\..\pjmedia\include\pjmedia\sdp_neg.h"\
+ "..\..\..\pjmedia\include\pjmedia\session.h"\
+ "..\..\..\pjmedia\include\pjmedia\silencedet.h"\
+ "..\..\..\pjmedia\include\pjmedia\sound.h"\
+ "..\..\..\pjmedia\include\pjmedia\sound_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\splitcomb.h"\
+ "..\..\..\pjmedia\include\pjmedia\stream.h"\
+ "..\..\..\pjmedia\include\pjmedia\tonegen.h"\
+ "..\..\..\pjmedia\include\pjmedia\transport.h"\
+ "..\..\..\pjmedia\include\pjmedia\transport_ice.h"\
+ "..\..\..\pjmedia\include\pjmedia\transport_srtp.h"\
+ "..\..\..\pjmedia\include\pjmedia\transport_udp.h"\
+ "..\..\..\pjmedia\include\pjmedia\types.h"\
+ "..\..\..\pjmedia\include\pjmedia\wav_playlist.h"\
+ "..\..\..\pjmedia\include\pjmedia\wav_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\wave.h"\
+ "..\..\..\pjnath\include\pjnath.h"\
+ "..\..\..\pjnath\include\pjnath\config.h"\
+ "..\..\..\pjnath\include\pjnath\errno.h"\
+ "..\..\..\pjnath\include\pjnath\ice_session.h"\
+ "..\..\..\pjnath\include\pjnath\ice_strans.h"\
+ "..\..\..\pjnath\include\pjnath\nat_detect.h"\
+ "..\..\..\pjnath\include\pjnath\stun_auth.h"\
+ "..\..\..\pjnath\include\pjnath\stun_config.h"\
+ "..\..\..\pjnath\include\pjnath\stun_msg.h"\
+ "..\..\..\pjnath\include\pjnath\stun_session.h"\
+ "..\..\..\pjnath\include\pjnath\stun_transaction.h"\
+ "..\..\..\pjnath\include\pjnath\types.h"\
+ "..\..\..\pjsip\include\pjsip-simple\evsub.h"\
+ "..\..\..\pjsip\include\pjsip-simple\iscomposing.h"\
+ "..\..\..\pjsip\include\pjsip-simple\pidf.h"\
+ "..\..\..\pjsip\include\pjsip-simple\presence.h"\
+ "..\..\..\pjsip\include\pjsip-simple\publish.h"\
+ "..\..\..\pjsip\include\pjsip-simple\rpid.h"\
+ "..\..\..\pjsip\include\pjsip-simple\types.h"\
+ "..\..\..\pjsip\include\pjsip-simple\xpidf.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_100rel.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_inv.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_regc.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_replaces.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_xfer.h"\
+ "..\..\..\pjsip\include\pjsip.h"\
+ "..\..\..\pjsip\include\pjsip\sip_auth.h"\
+ "..\..\..\pjsip\include\pjsip\sip_auth_aka.h"\
+ "..\..\..\pjsip\include\pjsip\sip_auth_msg.h"\
+ "..\..\..\pjsip\include\pjsip\sip_autoconf.h"\
+ "..\..\..\pjsip\include\pjsip\sip_config.h"\
+ "..\..\..\pjsip\include\pjsip\sip_dialog.h"\
+ "..\..\..\pjsip\include\pjsip\sip_endpoint.h"\
+ "..\..\..\pjsip\include\pjsip\sip_errno.h"\
+ "..\..\..\pjsip\include\pjsip\sip_event.h"\
+ "..\..\..\pjsip\include\pjsip\sip_module.h"\
+ "..\..\..\pjsip\include\pjsip\sip_msg.h"\
+ "..\..\..\pjsip\include\pjsip\sip_parser.h"\
+ "..\..\..\pjsip\include\pjsip\sip_resolve.h"\
+ "..\..\..\pjsip\include\pjsip\sip_tel_uri.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transaction.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport_loop.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport_tcp.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport_tls.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport_udp.h"\
+ "..\..\..\pjsip\include\pjsip\sip_types.h"\
+ "..\..\..\pjsip\include\pjsip\sip_ua_layer.h"\
+ "..\..\..\pjsip\include\pjsip\sip_uri.h"\
+ "..\..\..\pjsip\include\pjsip\sip_util.h"\
+ "..\..\..\pjsip\include\pjsip_simple.h"\
+ "..\..\..\pjsip\include\pjsip_ua.h"\
+ "..\..\..\pjsip\include\pjsua-lib\pjsua.h"\
+ ".\PocketPJ.h"\
+ ".\PocketPJDlg.h"\
+ ".\PopUpWnd.h"\
+ ".\SettingsDlg.h"\
+ ".\StdAfx.h"\
+
+
+!ELSEIF "$(CFG)" == "PocketPJ - Win32 (WCE ARMV4) Release"
+
+DEP_CPP_POCKE=\
+ "..\..\..\pjlib-util\include\pjlib-util.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\base64.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\config.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\crc32.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\dns.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\errno.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\getopt.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\hmac_md5.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\hmac_sha1.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\md5.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\pcap.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\resolver.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\scanner.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\scanner_cis_bitwise.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\scanner_cis_uint.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\sha1.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\srv_resolver.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\stun_simple.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\types.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\xml.h"\
+ "..\..\..\pjlib\include\pj\addr_resolv.h"\
+ "..\..\..\pjlib\include\pj\array.h"\
+ "..\..\..\pjlib\include\pj\assert.h"\
+ "..\..\..\pjlib\include\pj\compat\assert.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_armcc.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_codew.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_gcce.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_mwcc.h"\
+ "..\..\..\pjlib\include\pj\compat\ctype.h"\
+ "..\..\..\pjlib\include\pj\compat\errno.h"\
+ "..\..\..\pjlib\include\pj\compat\high_precision.h"\
+ "..\..\..\pjlib\include\pj\compat\m_auto.h"\
+ "..\..\..\pjlib\include\pj\compat\os_auto.h"\
+ "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\
+ "..\..\..\pjlib\include\pj\compat\os_linux.h"\
+ "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\
+ "..\..\..\pjlib\include\pj\compat\os_palmos.h"\
+ "..\..\..\pjlib\include\pj\compat\os_rtems.h"\
+ "..\..\..\pjlib\include\pj\compat\os_sunos.h"\
+ "..\..\..\pjlib\include\pj\compat\os_symbian.h"\
+ "..\..\..\pjlib\include\pj\compat\os_win32.h"\
+ "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\
+ "..\..\..\pjlib\include\pj\compat\setjmp.h"\
+ "..\..\..\pjlib\include\pj\compat\size_t.h"\
+ "..\..\..\pjlib\include\pj\compat\stdarg.h"\
+ "..\..\..\pjlib\include\pj\compat\string.h"\
+ "..\..\..\pjlib\include\pj\config.h"\
+ "..\..\..\pjlib\include\pj\config_site.h"\
+ "..\..\..\pjlib\include\pj\config_site_sample.h"\
+ "..\..\..\pjlib\include\pj\ctype.h"\
+ "..\..\..\pjlib\include\pj\errno.h"\
+ "..\..\..\pjlib\include\pj\except.h"\
+ "..\..\..\pjlib\include\pj\fifobuf.h"\
+ "..\..\..\pjlib\include\pj\file_access.h"\
+ "..\..\..\pjlib\include\pj\file_io.h"\
+ "..\..\..\pjlib\include\pj\guid.h"\
+ "..\..\..\pjlib\include\pj\hash.h"\
+ "..\..\..\pjlib\include\pj\ioqueue.h"\
+ "..\..\..\pjlib\include\pj\ip_helper.h"\
+ "..\..\..\pjlib\include\pj\list.h"\
+ "..\..\..\pjlib\include\pj\list_i.h"\
+ "..\..\..\pjlib\include\pj\lock.h"\
+ "..\..\..\pjlib\include\pj\log.h"\
+ "..\..\..\pjlib\include\pj\os.h"\
+ "..\..\..\pjlib\include\pj\pool.h"\
+ "..\..\..\pjlib\include\pj\pool_alt.h"\
+ "..\..\..\pjlib\include\pj\pool_buf.h"\
+ "..\..\..\pjlib\include\pj\pool_i.h"\
+ "..\..\..\pjlib\include\pj\rand.h"\
+ "..\..\..\pjlib\include\pj\rbtree.h"\
+ "..\..\..\pjlib\include\pj\sock.h"\
+ "..\..\..\pjlib\include\pj\sock_select.h"\
+ "..\..\..\pjlib\include\pj\string.h"\
+ "..\..\..\pjlib\include\pj\string_i.h"\
+ "..\..\..\pjlib\include\pj\timer.h"\
+ "..\..\..\pjlib\include\pj\types.h"\
+ "..\..\..\pjlib\include\pj\unicode.h"\
+ "..\..\..\pjlib\include\pjlib.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\config.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\config_auto.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\gsm.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\ilbc.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\l16.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\speex.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\types.h"\
+ "..\..\..\pjmedia\include\pjmedia.h"\
+ "..\..\..\pjmedia\include\pjmedia\alaw_ulaw.h"\
+ "..\..\..\pjmedia\include\pjmedia\bidirectional.h"\
+ "..\..\..\pjmedia\include\pjmedia\clock.h"\
+ "..\..\..\pjmedia\include\pjmedia\codec.h"\
+ "..\..\..\pjmedia\include\pjmedia\conference.h"\
+ "..\..\..\pjmedia\include\pjmedia\config.h"\
+ "..\..\..\pjmedia\include\pjmedia\config_auto.h"\
+ "..\..\..\pjmedia\include\pjmedia\echo.h"\
+ "..\..\..\pjmedia\include\pjmedia\echo_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\endpoint.h"\
+ "..\..\..\pjmedia\include\pjmedia\errno.h"\
+ "..\..\..\pjmedia\include\pjmedia\g711.h"\
+ "..\..\..\pjmedia\include\pjmedia\jbuf.h"\
+ "..\..\..\pjmedia\include\pjmedia\master_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\mem_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\null_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\plc.h"\
+ "..\..\..\pjmedia\include\pjmedia\port.h"\
+ "..\..\..\pjmedia\include\pjmedia\resample.h"\
+ "..\..\..\pjmedia\include\pjmedia\rtcp.h"\
+ "..\..\..\pjmedia\include\pjmedia\rtp.h"\
+ "..\..\..\pjmedia\include\pjmedia\sdp.h"\
+ "..\..\..\pjmedia\include\pjmedia\sdp_neg.h"\
+ "..\..\..\pjmedia\include\pjmedia\session.h"\
+ "..\..\..\pjmedia\include\pjmedia\silencedet.h"\
+ "..\..\..\pjmedia\include\pjmedia\sound.h"\
+ "..\..\..\pjmedia\include\pjmedia\sound_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\splitcomb.h"\
+ "..\..\..\pjmedia\include\pjmedia\stream.h"\
+ "..\..\..\pjmedia\include\pjmedia\tonegen.h"\
+ "..\..\..\pjmedia\include\pjmedia\transport.h"\
+ "..\..\..\pjmedia\include\pjmedia\transport_ice.h"\
+ "..\..\..\pjmedia\include\pjmedia\transport_srtp.h"\
+ "..\..\..\pjmedia\include\pjmedia\transport_udp.h"\
+ "..\..\..\pjmedia\include\pjmedia\types.h"\
+ "..\..\..\pjmedia\include\pjmedia\wav_playlist.h"\
+ "..\..\..\pjmedia\include\pjmedia\wav_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\wave.h"\
+ "..\..\..\pjnath\include\pjnath.h"\
+ "..\..\..\pjnath\include\pjnath\config.h"\
+ "..\..\..\pjnath\include\pjnath\errno.h"\
+ "..\..\..\pjnath\include\pjnath\ice_session.h"\
+ "..\..\..\pjnath\include\pjnath\ice_strans.h"\
+ "..\..\..\pjnath\include\pjnath\nat_detect.h"\
+ "..\..\..\pjnath\include\pjnath\stun_auth.h"\
+ "..\..\..\pjnath\include\pjnath\stun_config.h"\
+ "..\..\..\pjnath\include\pjnath\stun_msg.h"\
+ "..\..\..\pjnath\include\pjnath\stun_session.h"\
+ "..\..\..\pjnath\include\pjnath\stun_transaction.h"\
+ "..\..\..\pjnath\include\pjnath\types.h"\
+ "..\..\..\pjsip\include\pjsip-simple\evsub.h"\
+ "..\..\..\pjsip\include\pjsip-simple\iscomposing.h"\
+ "..\..\..\pjsip\include\pjsip-simple\pidf.h"\
+ "..\..\..\pjsip\include\pjsip-simple\presence.h"\
+ "..\..\..\pjsip\include\pjsip-simple\publish.h"\
+ "..\..\..\pjsip\include\pjsip-simple\rpid.h"\
+ "..\..\..\pjsip\include\pjsip-simple\types.h"\
+ "..\..\..\pjsip\include\pjsip-simple\xpidf.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_100rel.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_inv.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_regc.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_replaces.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_xfer.h"\
+ "..\..\..\pjsip\include\pjsip.h"\
+ "..\..\..\pjsip\include\pjsip\sip_auth.h"\
+ "..\..\..\pjsip\include\pjsip\sip_auth_aka.h"\
+ "..\..\..\pjsip\include\pjsip\sip_auth_msg.h"\
+ "..\..\..\pjsip\include\pjsip\sip_autoconf.h"\
+ "..\..\..\pjsip\include\pjsip\sip_config.h"\
+ "..\..\..\pjsip\include\pjsip\sip_dialog.h"\
+ "..\..\..\pjsip\include\pjsip\sip_endpoint.h"\
+ "..\..\..\pjsip\include\pjsip\sip_errno.h"\
+ "..\..\..\pjsip\include\pjsip\sip_event.h"\
+ "..\..\..\pjsip\include\pjsip\sip_module.h"\
+ "..\..\..\pjsip\include\pjsip\sip_msg.h"\
+ "..\..\..\pjsip\include\pjsip\sip_parser.h"\
+ "..\..\..\pjsip\include\pjsip\sip_resolve.h"\
+ "..\..\..\pjsip\include\pjsip\sip_tel_uri.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transaction.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport_loop.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport_tcp.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport_tls.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport_udp.h"\
+ "..\..\..\pjsip\include\pjsip\sip_types.h"\
+ "..\..\..\pjsip\include\pjsip\sip_ua_layer.h"\
+ "..\..\..\pjsip\include\pjsip\sip_uri.h"\
+ "..\..\..\pjsip\include\pjsip\sip_util.h"\
+ "..\..\..\pjsip\include\pjsip_simple.h"\
+ "..\..\..\pjsip\include\pjsip_ua.h"\
+ "..\..\..\pjsip\include\pjsua-lib\pjsua.h"\
+ ".\PocketPJ.h"\
+ ".\PocketPJDlg.h"\
+ ".\PopUpWnd.h"\
+ ".\SettingsDlg.h"\
+ ".\StdAfx.h"\
+
+
+!ELSEIF "$(CFG)" == "PocketPJ - Win32 (WCE ARMV4) Debug"
+
+DEP_CPP_POCKE=\
+ "..\..\..\pjlib-util\include\pjlib-util.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\base64.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\config.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\crc32.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\dns.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\errno.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\getopt.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\hmac_md5.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\hmac_sha1.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\md5.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\pcap.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\resolver.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\scanner.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\scanner_cis_bitwise.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\scanner_cis_uint.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\sha1.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\srv_resolver.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\stun_simple.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\types.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\xml.h"\
+ "..\..\..\pjlib\include\pj\addr_resolv.h"\
+ "..\..\..\pjlib\include\pj\array.h"\
+ "..\..\..\pjlib\include\pj\assert.h"\
+ "..\..\..\pjlib\include\pj\compat\assert.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_armcc.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_codew.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_gcce.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_mwcc.h"\
+ "..\..\..\pjlib\include\pj\compat\ctype.h"\
+ "..\..\..\pjlib\include\pj\compat\errno.h"\
+ "..\..\..\pjlib\include\pj\compat\high_precision.h"\
+ "..\..\..\pjlib\include\pj\compat\m_auto.h"\
+ "..\..\..\pjlib\include\pj\compat\os_auto.h"\
+ "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\
+ "..\..\..\pjlib\include\pj\compat\os_linux.h"\
+ "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\
+ "..\..\..\pjlib\include\pj\compat\os_palmos.h"\
+ "..\..\..\pjlib\include\pj\compat\os_rtems.h"\
+ "..\..\..\pjlib\include\pj\compat\os_sunos.h"\
+ "..\..\..\pjlib\include\pj\compat\os_symbian.h"\
+ "..\..\..\pjlib\include\pj\compat\os_win32.h"\
+ "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\
+ "..\..\..\pjlib\include\pj\compat\setjmp.h"\
+ "..\..\..\pjlib\include\pj\compat\size_t.h"\
+ "..\..\..\pjlib\include\pj\compat\stdarg.h"\
+ "..\..\..\pjlib\include\pj\compat\string.h"\
+ "..\..\..\pjlib\include\pj\config.h"\
+ "..\..\..\pjlib\include\pj\config_site.h"\
+ "..\..\..\pjlib\include\pj\config_site_sample.h"\
+ "..\..\..\pjlib\include\pj\ctype.h"\
+ "..\..\..\pjlib\include\pj\errno.h"\
+ "..\..\..\pjlib\include\pj\except.h"\
+ "..\..\..\pjlib\include\pj\fifobuf.h"\
+ "..\..\..\pjlib\include\pj\file_access.h"\
+ "..\..\..\pjlib\include\pj\file_io.h"\
+ "..\..\..\pjlib\include\pj\guid.h"\
+ "..\..\..\pjlib\include\pj\hash.h"\
+ "..\..\..\pjlib\include\pj\ioqueue.h"\
+ "..\..\..\pjlib\include\pj\ip_helper.h"\
+ "..\..\..\pjlib\include\pj\list.h"\
+ "..\..\..\pjlib\include\pj\list_i.h"\
+ "..\..\..\pjlib\include\pj\lock.h"\
+ "..\..\..\pjlib\include\pj\log.h"\
+ "..\..\..\pjlib\include\pj\os.h"\
+ "..\..\..\pjlib\include\pj\pool.h"\
+ "..\..\..\pjlib\include\pj\pool_alt.h"\
+ "..\..\..\pjlib\include\pj\pool_buf.h"\
+ "..\..\..\pjlib\include\pj\pool_i.h"\
+ "..\..\..\pjlib\include\pj\rand.h"\
+ "..\..\..\pjlib\include\pj\rbtree.h"\
+ "..\..\..\pjlib\include\pj\sock.h"\
+ "..\..\..\pjlib\include\pj\sock_select.h"\
+ "..\..\..\pjlib\include\pj\string.h"\
+ "..\..\..\pjlib\include\pj\string_i.h"\
+ "..\..\..\pjlib\include\pj\timer.h"\
+ "..\..\..\pjlib\include\pj\types.h"\
+ "..\..\..\pjlib\include\pj\unicode.h"\
+ "..\..\..\pjlib\include\pjlib.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\config.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\config_auto.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\gsm.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\ilbc.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\l16.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\speex.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\types.h"\
+ "..\..\..\pjmedia\include\pjmedia.h"\
+ "..\..\..\pjmedia\include\pjmedia\alaw_ulaw.h"\
+ "..\..\..\pjmedia\include\pjmedia\bidirectional.h"\
+ "..\..\..\pjmedia\include\pjmedia\clock.h"\
+ "..\..\..\pjmedia\include\pjmedia\codec.h"\
+ "..\..\..\pjmedia\include\pjmedia\conference.h"\
+ "..\..\..\pjmedia\include\pjmedia\config.h"\
+ "..\..\..\pjmedia\include\pjmedia\config_auto.h"\
+ "..\..\..\pjmedia\include\pjmedia\echo.h"\
+ "..\..\..\pjmedia\include\pjmedia\echo_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\endpoint.h"\
+ "..\..\..\pjmedia\include\pjmedia\errno.h"\
+ "..\..\..\pjmedia\include\pjmedia\g711.h"\
+ "..\..\..\pjmedia\include\pjmedia\jbuf.h"\
+ "..\..\..\pjmedia\include\pjmedia\master_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\mem_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\null_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\plc.h"\
+ "..\..\..\pjmedia\include\pjmedia\port.h"\
+ "..\..\..\pjmedia\include\pjmedia\resample.h"\
+ "..\..\..\pjmedia\include\pjmedia\rtcp.h"\
+ "..\..\..\pjmedia\include\pjmedia\rtp.h"\
+ "..\..\..\pjmedia\include\pjmedia\sdp.h"\
+ "..\..\..\pjmedia\include\pjmedia\sdp_neg.h"\
+ "..\..\..\pjmedia\include\pjmedia\session.h"\
+ "..\..\..\pjmedia\include\pjmedia\silencedet.h"\
+ "..\..\..\pjmedia\include\pjmedia\sound.h"\
+ "..\..\..\pjmedia\include\pjmedia\sound_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\splitcomb.h"\
+ "..\..\..\pjmedia\include\pjmedia\stream.h"\
+ "..\..\..\pjmedia\include\pjmedia\tonegen.h"\
+ "..\..\..\pjmedia\include\pjmedia\transport.h"\
+ "..\..\..\pjmedia\include\pjmedia\transport_ice.h"\
+ "..\..\..\pjmedia\include\pjmedia\transport_srtp.h"\
+ "..\..\..\pjmedia\include\pjmedia\transport_udp.h"\
+ "..\..\..\pjmedia\include\pjmedia\types.h"\
+ "..\..\..\pjmedia\include\pjmedia\wav_playlist.h"\
+ "..\..\..\pjmedia\include\pjmedia\wav_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\wave.h"\
+ "..\..\..\pjnath\include\pjnath.h"\
+ "..\..\..\pjnath\include\pjnath\config.h"\
+ "..\..\..\pjnath\include\pjnath\errno.h"\
+ "..\..\..\pjnath\include\pjnath\ice_session.h"\
+ "..\..\..\pjnath\include\pjnath\ice_strans.h"\
+ "..\..\..\pjnath\include\pjnath\nat_detect.h"\
+ "..\..\..\pjnath\include\pjnath\stun_auth.h"\
+ "..\..\..\pjnath\include\pjnath\stun_config.h"\
+ "..\..\..\pjnath\include\pjnath\stun_msg.h"\
+ "..\..\..\pjnath\include\pjnath\stun_session.h"\
+ "..\..\..\pjnath\include\pjnath\stun_transaction.h"\
+ "..\..\..\pjnath\include\pjnath\types.h"\
+ "..\..\..\pjsip\include\pjsip-simple\evsub.h"\
+ "..\..\..\pjsip\include\pjsip-simple\iscomposing.h"\
+ "..\..\..\pjsip\include\pjsip-simple\pidf.h"\
+ "..\..\..\pjsip\include\pjsip-simple\presence.h"\
+ "..\..\..\pjsip\include\pjsip-simple\publish.h"\
+ "..\..\..\pjsip\include\pjsip-simple\rpid.h"\
+ "..\..\..\pjsip\include\pjsip-simple\types.h"\
+ "..\..\..\pjsip\include\pjsip-simple\xpidf.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_100rel.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_inv.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_regc.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_replaces.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_xfer.h"\
+ "..\..\..\pjsip\include\pjsip.h"\
+ "..\..\..\pjsip\include\pjsip\sip_auth.h"\
+ "..\..\..\pjsip\include\pjsip\sip_auth_aka.h"\
+ "..\..\..\pjsip\include\pjsip\sip_auth_msg.h"\
+ "..\..\..\pjsip\include\pjsip\sip_autoconf.h"\
+ "..\..\..\pjsip\include\pjsip\sip_config.h"\
+ "..\..\..\pjsip\include\pjsip\sip_dialog.h"\
+ "..\..\..\pjsip\include\pjsip\sip_endpoint.h"\
+ "..\..\..\pjsip\include\pjsip\sip_errno.h"\
+ "..\..\..\pjsip\include\pjsip\sip_event.h"\
+ "..\..\..\pjsip\include\pjsip\sip_module.h"\
+ "..\..\..\pjsip\include\pjsip\sip_msg.h"\
+ "..\..\..\pjsip\include\pjsip\sip_parser.h"\
+ "..\..\..\pjsip\include\pjsip\sip_resolve.h"\
+ "..\..\..\pjsip\include\pjsip\sip_tel_uri.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transaction.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport_loop.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport_tcp.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport_tls.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport_udp.h"\
+ "..\..\..\pjsip\include\pjsip\sip_types.h"\
+ "..\..\..\pjsip\include\pjsip\sip_ua_layer.h"\
+ "..\..\..\pjsip\include\pjsip\sip_uri.h"\
+ "..\..\..\pjsip\include\pjsip\sip_util.h"\
+ "..\..\..\pjsip\include\pjsip_simple.h"\
+ "..\..\..\pjsip\include\pjsip_ua.h"\
+ "..\..\..\pjsip\include\pjsua-lib\pjsua.h"\
+ ".\PocketPJ.h"\
+ ".\PocketPJDlg.h"\
+ ".\SettingsDlg.h"\
+ ".\StdAfx.h"\
+
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\PocketPJ.rc
+
+!IF "$(CFG)" == "PocketPJ - Win32 (WCE emulator) Release"
+
+!ELSEIF "$(CFG)" == "PocketPJ - Win32 (WCE emulator) Debug"
+
+!ELSEIF "$(CFG)" == "PocketPJ - Win32 (WCE ARMV4) Release"
+
+!ELSEIF "$(CFG)" == "PocketPJ - Win32 (WCE ARMV4) Debug"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\PocketPJDlg.cpp
+
+!IF "$(CFG)" == "PocketPJ - Win32 (WCE emulator) Release"
+
+DEP_CPP_POCKET=\
+ ".\PocketPJ.h"\
+ ".\PocketPJDlg.h"\
+ ".\StdAfx.h"\
+
+
+!ELSEIF "$(CFG)" == "PocketPJ - Win32 (WCE emulator) Debug"
+
+DEP_CPP_POCKET=\
+ "..\..\..\pjlib-util\include\pjlib-util.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\base64.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\config.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\crc32.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\dns.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\errno.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\getopt.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\hmac_md5.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\hmac_sha1.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\md5.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\pcap.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\resolver.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\scanner.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\scanner_cis_bitwise.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\scanner_cis_uint.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\sha1.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\srv_resolver.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\stun_simple.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\types.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\xml.h"\
+ "..\..\..\pjlib\include\pj\addr_resolv.h"\
+ "..\..\..\pjlib\include\pj\array.h"\
+ "..\..\..\pjlib\include\pj\assert.h"\
+ "..\..\..\pjlib\include\pj\compat\assert.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_armcc.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_codew.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_gcce.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_mwcc.h"\
+ "..\..\..\pjlib\include\pj\compat\ctype.h"\
+ "..\..\..\pjlib\include\pj\compat\errno.h"\
+ "..\..\..\pjlib\include\pj\compat\high_precision.h"\
+ "..\..\..\pjlib\include\pj\compat\m_auto.h"\
+ "..\..\..\pjlib\include\pj\compat\os_auto.h"\
+ "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\
+ "..\..\..\pjlib\include\pj\compat\os_linux.h"\
+ "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\
+ "..\..\..\pjlib\include\pj\compat\os_palmos.h"\
+ "..\..\..\pjlib\include\pj\compat\os_rtems.h"\
+ "..\..\..\pjlib\include\pj\compat\os_sunos.h"\
+ "..\..\..\pjlib\include\pj\compat\os_symbian.h"\
+ "..\..\..\pjlib\include\pj\compat\os_win32.h"\
+ "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\
+ "..\..\..\pjlib\include\pj\compat\setjmp.h"\
+ "..\..\..\pjlib\include\pj\compat\size_t.h"\
+ "..\..\..\pjlib\include\pj\compat\stdarg.h"\
+ "..\..\..\pjlib\include\pj\compat\string.h"\
+ "..\..\..\pjlib\include\pj\config.h"\
+ "..\..\..\pjlib\include\pj\config_site.h"\
+ "..\..\..\pjlib\include\pj\config_site_sample.h"\
+ "..\..\..\pjlib\include\pj\ctype.h"\
+ "..\..\..\pjlib\include\pj\errno.h"\
+ "..\..\..\pjlib\include\pj\except.h"\
+ "..\..\..\pjlib\include\pj\fifobuf.h"\
+ "..\..\..\pjlib\include\pj\file_access.h"\
+ "..\..\..\pjlib\include\pj\file_io.h"\
+ "..\..\..\pjlib\include\pj\guid.h"\
+ "..\..\..\pjlib\include\pj\hash.h"\
+ "..\..\..\pjlib\include\pj\ioqueue.h"\
+ "..\..\..\pjlib\include\pj\ip_helper.h"\
+ "..\..\..\pjlib\include\pj\list.h"\
+ "..\..\..\pjlib\include\pj\list_i.h"\
+ "..\..\..\pjlib\include\pj\lock.h"\
+ "..\..\..\pjlib\include\pj\log.h"\
+ "..\..\..\pjlib\include\pj\os.h"\
+ "..\..\..\pjlib\include\pj\pool.h"\
+ "..\..\..\pjlib\include\pj\pool_alt.h"\
+ "..\..\..\pjlib\include\pj\pool_buf.h"\
+ "..\..\..\pjlib\include\pj\pool_i.h"\
+ "..\..\..\pjlib\include\pj\rand.h"\
+ "..\..\..\pjlib\include\pj\rbtree.h"\
+ "..\..\..\pjlib\include\pj\sock.h"\
+ "..\..\..\pjlib\include\pj\sock_select.h"\
+ "..\..\..\pjlib\include\pj\string.h"\
+ "..\..\..\pjlib\include\pj\string_i.h"\
+ "..\..\..\pjlib\include\pj\timer.h"\
+ "..\..\..\pjlib\include\pj\types.h"\
+ "..\..\..\pjlib\include\pj\unicode.h"\
+ "..\..\..\pjlib\include\pjlib.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\config.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\config_auto.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\gsm.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\ilbc.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\l16.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\speex.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\types.h"\
+ "..\..\..\pjmedia\include\pjmedia.h"\
+ "..\..\..\pjmedia\include\pjmedia\alaw_ulaw.h"\
+ "..\..\..\pjmedia\include\pjmedia\bidirectional.h"\
+ "..\..\..\pjmedia\include\pjmedia\clock.h"\
+ "..\..\..\pjmedia\include\pjmedia\codec.h"\
+ "..\..\..\pjmedia\include\pjmedia\conference.h"\
+ "..\..\..\pjmedia\include\pjmedia\config.h"\
+ "..\..\..\pjmedia\include\pjmedia\config_auto.h"\
+ "..\..\..\pjmedia\include\pjmedia\echo.h"\
+ "..\..\..\pjmedia\include\pjmedia\echo_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\endpoint.h"\
+ "..\..\..\pjmedia\include\pjmedia\errno.h"\
+ "..\..\..\pjmedia\include\pjmedia\g711.h"\
+ "..\..\..\pjmedia\include\pjmedia\jbuf.h"\
+ "..\..\..\pjmedia\include\pjmedia\master_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\mem_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\null_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\plc.h"\
+ "..\..\..\pjmedia\include\pjmedia\port.h"\
+ "..\..\..\pjmedia\include\pjmedia\resample.h"\
+ "..\..\..\pjmedia\include\pjmedia\rtcp.h"\
+ "..\..\..\pjmedia\include\pjmedia\rtp.h"\
+ "..\..\..\pjmedia\include\pjmedia\sdp.h"\
+ "..\..\..\pjmedia\include\pjmedia\sdp_neg.h"\
+ "..\..\..\pjmedia\include\pjmedia\session.h"\
+ "..\..\..\pjmedia\include\pjmedia\silencedet.h"\
+ "..\..\..\pjmedia\include\pjmedia\sound.h"\
+ "..\..\..\pjmedia\include\pjmedia\sound_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\splitcomb.h"\
+ "..\..\..\pjmedia\include\pjmedia\stream.h"\
+ "..\..\..\pjmedia\include\pjmedia\tonegen.h"\
+ "..\..\..\pjmedia\include\pjmedia\transport.h"\
+ "..\..\..\pjmedia\include\pjmedia\transport_ice.h"\
+ "..\..\..\pjmedia\include\pjmedia\transport_srtp.h"\
+ "..\..\..\pjmedia\include\pjmedia\transport_udp.h"\
+ "..\..\..\pjmedia\include\pjmedia\types.h"\
+ "..\..\..\pjmedia\include\pjmedia\wav_playlist.h"\
+ "..\..\..\pjmedia\include\pjmedia\wav_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\wave.h"\
+ "..\..\..\pjnath\include\pjnath.h"\
+ "..\..\..\pjnath\include\pjnath\config.h"\
+ "..\..\..\pjnath\include\pjnath\errno.h"\
+ "..\..\..\pjnath\include\pjnath\ice_session.h"\
+ "..\..\..\pjnath\include\pjnath\ice_strans.h"\
+ "..\..\..\pjnath\include\pjnath\nat_detect.h"\
+ "..\..\..\pjnath\include\pjnath\stun_auth.h"\
+ "..\..\..\pjnath\include\pjnath\stun_config.h"\
+ "..\..\..\pjnath\include\pjnath\stun_msg.h"\
+ "..\..\..\pjnath\include\pjnath\stun_session.h"\
+ "..\..\..\pjnath\include\pjnath\stun_transaction.h"\
+ "..\..\..\pjnath\include\pjnath\types.h"\
+ "..\..\..\pjsip\include\pjsip-simple\evsub.h"\
+ "..\..\..\pjsip\include\pjsip-simple\iscomposing.h"\
+ "..\..\..\pjsip\include\pjsip-simple\pidf.h"\
+ "..\..\..\pjsip\include\pjsip-simple\presence.h"\
+ "..\..\..\pjsip\include\pjsip-simple\publish.h"\
+ "..\..\..\pjsip\include\pjsip-simple\rpid.h"\
+ "..\..\..\pjsip\include\pjsip-simple\types.h"\
+ "..\..\..\pjsip\include\pjsip-simple\xpidf.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_100rel.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_inv.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_regc.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_replaces.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_xfer.h"\
+ "..\..\..\pjsip\include\pjsip.h"\
+ "..\..\..\pjsip\include\pjsip\sip_auth.h"\
+ "..\..\..\pjsip\include\pjsip\sip_auth_aka.h"\
+ "..\..\..\pjsip\include\pjsip\sip_auth_msg.h"\
+ "..\..\..\pjsip\include\pjsip\sip_autoconf.h"\
+ "..\..\..\pjsip\include\pjsip\sip_config.h"\
+ "..\..\..\pjsip\include\pjsip\sip_dialog.h"\
+ "..\..\..\pjsip\include\pjsip\sip_endpoint.h"\
+ "..\..\..\pjsip\include\pjsip\sip_errno.h"\
+ "..\..\..\pjsip\include\pjsip\sip_event.h"\
+ "..\..\..\pjsip\include\pjsip\sip_module.h"\
+ "..\..\..\pjsip\include\pjsip\sip_msg.h"\
+ "..\..\..\pjsip\include\pjsip\sip_parser.h"\
+ "..\..\..\pjsip\include\pjsip\sip_resolve.h"\
+ "..\..\..\pjsip\include\pjsip\sip_tel_uri.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transaction.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport_loop.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport_tcp.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport_tls.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport_udp.h"\
+ "..\..\..\pjsip\include\pjsip\sip_types.h"\
+ "..\..\..\pjsip\include\pjsip\sip_ua_layer.h"\
+ "..\..\..\pjsip\include\pjsip\sip_uri.h"\
+ "..\..\..\pjsip\include\pjsip\sip_util.h"\
+ "..\..\..\pjsip\include\pjsip_simple.h"\
+ "..\..\..\pjsip\include\pjsip_ua.h"\
+ "..\..\..\pjsip\include\pjsua-lib\pjsua.h"\
+ ".\PocketPJ.h"\
+ ".\PocketPJDlg.h"\
+ ".\PopUpWnd.h"\
+ ".\SettingsDlg.h"\
+ ".\StdAfx.h"\
+ {$(INCLUDE)}"ipexport.h"\
+ {$(INCLUDE)}"Iphlpapi.h"\
+ {$(INCLUDE)}"iptypes.h"\
+
+
+!ELSEIF "$(CFG)" == "PocketPJ - Win32 (WCE ARMV4) Release"
+
+DEP_CPP_POCKET=\
+ "..\..\..\pjlib-util\include\pjlib-util.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\base64.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\config.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\crc32.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\dns.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\errno.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\getopt.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\hmac_md5.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\hmac_sha1.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\md5.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\pcap.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\resolver.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\scanner.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\scanner_cis_bitwise.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\scanner_cis_uint.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\sha1.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\srv_resolver.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\stun_simple.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\types.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\xml.h"\
+ "..\..\..\pjlib\include\pj\addr_resolv.h"\
+ "..\..\..\pjlib\include\pj\array.h"\
+ "..\..\..\pjlib\include\pj\assert.h"\
+ "..\..\..\pjlib\include\pj\compat\assert.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_armcc.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_codew.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_gcce.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_mwcc.h"\
+ "..\..\..\pjlib\include\pj\compat\ctype.h"\
+ "..\..\..\pjlib\include\pj\compat\errno.h"\
+ "..\..\..\pjlib\include\pj\compat\high_precision.h"\
+ "..\..\..\pjlib\include\pj\compat\m_auto.h"\
+ "..\..\..\pjlib\include\pj\compat\os_auto.h"\
+ "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\
+ "..\..\..\pjlib\include\pj\compat\os_linux.h"\
+ "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\
+ "..\..\..\pjlib\include\pj\compat\os_palmos.h"\
+ "..\..\..\pjlib\include\pj\compat\os_rtems.h"\
+ "..\..\..\pjlib\include\pj\compat\os_sunos.h"\
+ "..\..\..\pjlib\include\pj\compat\os_symbian.h"\
+ "..\..\..\pjlib\include\pj\compat\os_win32.h"\
+ "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\
+ "..\..\..\pjlib\include\pj\compat\setjmp.h"\
+ "..\..\..\pjlib\include\pj\compat\size_t.h"\
+ "..\..\..\pjlib\include\pj\compat\stdarg.h"\
+ "..\..\..\pjlib\include\pj\compat\string.h"\
+ "..\..\..\pjlib\include\pj\config.h"\
+ "..\..\..\pjlib\include\pj\config_site.h"\
+ "..\..\..\pjlib\include\pj\config_site_sample.h"\
+ "..\..\..\pjlib\include\pj\ctype.h"\
+ "..\..\..\pjlib\include\pj\errno.h"\
+ "..\..\..\pjlib\include\pj\except.h"\
+ "..\..\..\pjlib\include\pj\fifobuf.h"\
+ "..\..\..\pjlib\include\pj\file_access.h"\
+ "..\..\..\pjlib\include\pj\file_io.h"\
+ "..\..\..\pjlib\include\pj\guid.h"\
+ "..\..\..\pjlib\include\pj\hash.h"\
+ "..\..\..\pjlib\include\pj\ioqueue.h"\
+ "..\..\..\pjlib\include\pj\ip_helper.h"\
+ "..\..\..\pjlib\include\pj\list.h"\
+ "..\..\..\pjlib\include\pj\list_i.h"\
+ "..\..\..\pjlib\include\pj\lock.h"\
+ "..\..\..\pjlib\include\pj\log.h"\
+ "..\..\..\pjlib\include\pj\os.h"\
+ "..\..\..\pjlib\include\pj\pool.h"\
+ "..\..\..\pjlib\include\pj\pool_alt.h"\
+ "..\..\..\pjlib\include\pj\pool_buf.h"\
+ "..\..\..\pjlib\include\pj\pool_i.h"\
+ "..\..\..\pjlib\include\pj\rand.h"\
+ "..\..\..\pjlib\include\pj\rbtree.h"\
+ "..\..\..\pjlib\include\pj\sock.h"\
+ "..\..\..\pjlib\include\pj\sock_select.h"\
+ "..\..\..\pjlib\include\pj\string.h"\
+ "..\..\..\pjlib\include\pj\string_i.h"\
+ "..\..\..\pjlib\include\pj\timer.h"\
+ "..\..\..\pjlib\include\pj\types.h"\
+ "..\..\..\pjlib\include\pj\unicode.h"\
+ "..\..\..\pjlib\include\pjlib.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\config.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\config_auto.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\gsm.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\ilbc.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\l16.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\speex.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\types.h"\
+ "..\..\..\pjmedia\include\pjmedia.h"\
+ "..\..\..\pjmedia\include\pjmedia\alaw_ulaw.h"\
+ "..\..\..\pjmedia\include\pjmedia\bidirectional.h"\
+ "..\..\..\pjmedia\include\pjmedia\clock.h"\
+ "..\..\..\pjmedia\include\pjmedia\codec.h"\
+ "..\..\..\pjmedia\include\pjmedia\conference.h"\
+ "..\..\..\pjmedia\include\pjmedia\config.h"\
+ "..\..\..\pjmedia\include\pjmedia\config_auto.h"\
+ "..\..\..\pjmedia\include\pjmedia\echo.h"\
+ "..\..\..\pjmedia\include\pjmedia\echo_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\endpoint.h"\
+ "..\..\..\pjmedia\include\pjmedia\errno.h"\
+ "..\..\..\pjmedia\include\pjmedia\g711.h"\
+ "..\..\..\pjmedia\include\pjmedia\jbuf.h"\
+ "..\..\..\pjmedia\include\pjmedia\master_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\mem_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\null_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\plc.h"\
+ "..\..\..\pjmedia\include\pjmedia\port.h"\
+ "..\..\..\pjmedia\include\pjmedia\resample.h"\
+ "..\..\..\pjmedia\include\pjmedia\rtcp.h"\
+ "..\..\..\pjmedia\include\pjmedia\rtp.h"\
+ "..\..\..\pjmedia\include\pjmedia\sdp.h"\
+ "..\..\..\pjmedia\include\pjmedia\sdp_neg.h"\
+ "..\..\..\pjmedia\include\pjmedia\session.h"\
+ "..\..\..\pjmedia\include\pjmedia\silencedet.h"\
+ "..\..\..\pjmedia\include\pjmedia\sound.h"\
+ "..\..\..\pjmedia\include\pjmedia\sound_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\splitcomb.h"\
+ "..\..\..\pjmedia\include\pjmedia\stream.h"\
+ "..\..\..\pjmedia\include\pjmedia\tonegen.h"\
+ "..\..\..\pjmedia\include\pjmedia\transport.h"\
+ "..\..\..\pjmedia\include\pjmedia\transport_ice.h"\
+ "..\..\..\pjmedia\include\pjmedia\transport_srtp.h"\
+ "..\..\..\pjmedia\include\pjmedia\transport_udp.h"\
+ "..\..\..\pjmedia\include\pjmedia\types.h"\
+ "..\..\..\pjmedia\include\pjmedia\wav_playlist.h"\
+ "..\..\..\pjmedia\include\pjmedia\wav_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\wave.h"\
+ "..\..\..\pjnath\include\pjnath.h"\
+ "..\..\..\pjnath\include\pjnath\config.h"\
+ "..\..\..\pjnath\include\pjnath\errno.h"\
+ "..\..\..\pjnath\include\pjnath\ice_session.h"\
+ "..\..\..\pjnath\include\pjnath\ice_strans.h"\
+ "..\..\..\pjnath\include\pjnath\nat_detect.h"\
+ "..\..\..\pjnath\include\pjnath\stun_auth.h"\
+ "..\..\..\pjnath\include\pjnath\stun_config.h"\
+ "..\..\..\pjnath\include\pjnath\stun_msg.h"\
+ "..\..\..\pjnath\include\pjnath\stun_session.h"\
+ "..\..\..\pjnath\include\pjnath\stun_transaction.h"\
+ "..\..\..\pjnath\include\pjnath\types.h"\
+ "..\..\..\pjsip\include\pjsip-simple\evsub.h"\
+ "..\..\..\pjsip\include\pjsip-simple\iscomposing.h"\
+ "..\..\..\pjsip\include\pjsip-simple\pidf.h"\
+ "..\..\..\pjsip\include\pjsip-simple\presence.h"\
+ "..\..\..\pjsip\include\pjsip-simple\publish.h"\
+ "..\..\..\pjsip\include\pjsip-simple\rpid.h"\
+ "..\..\..\pjsip\include\pjsip-simple\types.h"\
+ "..\..\..\pjsip\include\pjsip-simple\xpidf.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_100rel.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_inv.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_regc.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_replaces.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_xfer.h"\
+ "..\..\..\pjsip\include\pjsip.h"\
+ "..\..\..\pjsip\include\pjsip\sip_auth.h"\
+ "..\..\..\pjsip\include\pjsip\sip_auth_aka.h"\
+ "..\..\..\pjsip\include\pjsip\sip_auth_msg.h"\
+ "..\..\..\pjsip\include\pjsip\sip_autoconf.h"\
+ "..\..\..\pjsip\include\pjsip\sip_config.h"\
+ "..\..\..\pjsip\include\pjsip\sip_dialog.h"\
+ "..\..\..\pjsip\include\pjsip\sip_endpoint.h"\
+ "..\..\..\pjsip\include\pjsip\sip_errno.h"\
+ "..\..\..\pjsip\include\pjsip\sip_event.h"\
+ "..\..\..\pjsip\include\pjsip\sip_module.h"\
+ "..\..\..\pjsip\include\pjsip\sip_msg.h"\
+ "..\..\..\pjsip\include\pjsip\sip_parser.h"\
+ "..\..\..\pjsip\include\pjsip\sip_resolve.h"\
+ "..\..\..\pjsip\include\pjsip\sip_tel_uri.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transaction.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport_loop.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport_tcp.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport_tls.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport_udp.h"\
+ "..\..\..\pjsip\include\pjsip\sip_types.h"\
+ "..\..\..\pjsip\include\pjsip\sip_ua_layer.h"\
+ "..\..\..\pjsip\include\pjsip\sip_uri.h"\
+ "..\..\..\pjsip\include\pjsip\sip_util.h"\
+ "..\..\..\pjsip\include\pjsip_simple.h"\
+ "..\..\..\pjsip\include\pjsip_ua.h"\
+ "..\..\..\pjsip\include\pjsua-lib\pjsua.h"\
+ ".\PocketPJ.h"\
+ ".\PocketPJDlg.h"\
+ ".\PopUpWnd.h"\
+ ".\SettingsDlg.h"\
+ ".\StdAfx.h"\
+ {$(INCLUDE)}"ipexport.h"\
+ {$(INCLUDE)}"Iphlpapi.h"\
+ {$(INCLUDE)}"iptypes.h"\
+
+
+!ELSEIF "$(CFG)" == "PocketPJ - Win32 (WCE ARMV4) Debug"
+
+DEP_CPP_POCKET=\
+ "..\..\..\pjlib-util\include\pjlib-util.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\base64.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\config.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\crc32.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\dns.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\errno.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\getopt.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\hmac_md5.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\hmac_sha1.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\md5.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\pcap.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\resolver.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\scanner.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\scanner_cis_bitwise.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\scanner_cis_uint.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\sha1.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\srv_resolver.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\stun_simple.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\types.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\xml.h"\
+ "..\..\..\pjlib\include\pj\addr_resolv.h"\
+ "..\..\..\pjlib\include\pj\array.h"\
+ "..\..\..\pjlib\include\pj\assert.h"\
+ "..\..\..\pjlib\include\pj\compat\assert.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_armcc.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_codew.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_gcce.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_mwcc.h"\
+ "..\..\..\pjlib\include\pj\compat\ctype.h"\
+ "..\..\..\pjlib\include\pj\compat\errno.h"\
+ "..\..\..\pjlib\include\pj\compat\high_precision.h"\
+ "..\..\..\pjlib\include\pj\compat\m_auto.h"\
+ "..\..\..\pjlib\include\pj\compat\os_auto.h"\
+ "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\
+ "..\..\..\pjlib\include\pj\compat\os_linux.h"\
+ "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\
+ "..\..\..\pjlib\include\pj\compat\os_palmos.h"\
+ "..\..\..\pjlib\include\pj\compat\os_rtems.h"\
+ "..\..\..\pjlib\include\pj\compat\os_sunos.h"\
+ "..\..\..\pjlib\include\pj\compat\os_symbian.h"\
+ "..\..\..\pjlib\include\pj\compat\os_win32.h"\
+ "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\
+ "..\..\..\pjlib\include\pj\compat\setjmp.h"\
+ "..\..\..\pjlib\include\pj\compat\size_t.h"\
+ "..\..\..\pjlib\include\pj\compat\stdarg.h"\
+ "..\..\..\pjlib\include\pj\compat\string.h"\
+ "..\..\..\pjlib\include\pj\config.h"\
+ "..\..\..\pjlib\include\pj\config_site.h"\
+ "..\..\..\pjlib\include\pj\config_site_sample.h"\
+ "..\..\..\pjlib\include\pj\ctype.h"\
+ "..\..\..\pjlib\include\pj\errno.h"\
+ "..\..\..\pjlib\include\pj\except.h"\
+ "..\..\..\pjlib\include\pj\fifobuf.h"\
+ "..\..\..\pjlib\include\pj\file_access.h"\
+ "..\..\..\pjlib\include\pj\file_io.h"\
+ "..\..\..\pjlib\include\pj\guid.h"\
+ "..\..\..\pjlib\include\pj\hash.h"\
+ "..\..\..\pjlib\include\pj\ioqueue.h"\
+ "..\..\..\pjlib\include\pj\ip_helper.h"\
+ "..\..\..\pjlib\include\pj\list.h"\
+ "..\..\..\pjlib\include\pj\list_i.h"\
+ "..\..\..\pjlib\include\pj\lock.h"\
+ "..\..\..\pjlib\include\pj\log.h"\
+ "..\..\..\pjlib\include\pj\os.h"\
+ "..\..\..\pjlib\include\pj\pool.h"\
+ "..\..\..\pjlib\include\pj\pool_alt.h"\
+ "..\..\..\pjlib\include\pj\pool_buf.h"\
+ "..\..\..\pjlib\include\pj\pool_i.h"\
+ "..\..\..\pjlib\include\pj\rand.h"\
+ "..\..\..\pjlib\include\pj\rbtree.h"\
+ "..\..\..\pjlib\include\pj\sock.h"\
+ "..\..\..\pjlib\include\pj\sock_select.h"\
+ "..\..\..\pjlib\include\pj\string.h"\
+ "..\..\..\pjlib\include\pj\string_i.h"\
+ "..\..\..\pjlib\include\pj\timer.h"\
+ "..\..\..\pjlib\include\pj\types.h"\
+ "..\..\..\pjlib\include\pj\unicode.h"\
+ "..\..\..\pjlib\include\pjlib.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\config.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\config_auto.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\gsm.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\ilbc.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\l16.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\speex.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\types.h"\
+ "..\..\..\pjmedia\include\pjmedia.h"\
+ "..\..\..\pjmedia\include\pjmedia\alaw_ulaw.h"\
+ "..\..\..\pjmedia\include\pjmedia\bidirectional.h"\
+ "..\..\..\pjmedia\include\pjmedia\clock.h"\
+ "..\..\..\pjmedia\include\pjmedia\codec.h"\
+ "..\..\..\pjmedia\include\pjmedia\conference.h"\
+ "..\..\..\pjmedia\include\pjmedia\config.h"\
+ "..\..\..\pjmedia\include\pjmedia\config_auto.h"\
+ "..\..\..\pjmedia\include\pjmedia\echo.h"\
+ "..\..\..\pjmedia\include\pjmedia\echo_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\endpoint.h"\
+ "..\..\..\pjmedia\include\pjmedia\errno.h"\
+ "..\..\..\pjmedia\include\pjmedia\g711.h"\
+ "..\..\..\pjmedia\include\pjmedia\jbuf.h"\
+ "..\..\..\pjmedia\include\pjmedia\master_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\mem_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\null_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\plc.h"\
+ "..\..\..\pjmedia\include\pjmedia\port.h"\
+ "..\..\..\pjmedia\include\pjmedia\resample.h"\
+ "..\..\..\pjmedia\include\pjmedia\rtcp.h"\
+ "..\..\..\pjmedia\include\pjmedia\rtp.h"\
+ "..\..\..\pjmedia\include\pjmedia\sdp.h"\
+ "..\..\..\pjmedia\include\pjmedia\sdp_neg.h"\
+ "..\..\..\pjmedia\include\pjmedia\session.h"\
+ "..\..\..\pjmedia\include\pjmedia\silencedet.h"\
+ "..\..\..\pjmedia\include\pjmedia\sound.h"\
+ "..\..\..\pjmedia\include\pjmedia\sound_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\splitcomb.h"\
+ "..\..\..\pjmedia\include\pjmedia\stream.h"\
+ "..\..\..\pjmedia\include\pjmedia\tonegen.h"\
+ "..\..\..\pjmedia\include\pjmedia\transport.h"\
+ "..\..\..\pjmedia\include\pjmedia\transport_ice.h"\
+ "..\..\..\pjmedia\include\pjmedia\transport_srtp.h"\
+ "..\..\..\pjmedia\include\pjmedia\transport_udp.h"\
+ "..\..\..\pjmedia\include\pjmedia\types.h"\
+ "..\..\..\pjmedia\include\pjmedia\wav_playlist.h"\
+ "..\..\..\pjmedia\include\pjmedia\wav_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\wave.h"\
+ "..\..\..\pjnath\include\pjnath.h"\
+ "..\..\..\pjnath\include\pjnath\config.h"\
+ "..\..\..\pjnath\include\pjnath\errno.h"\
+ "..\..\..\pjnath\include\pjnath\ice_session.h"\
+ "..\..\..\pjnath\include\pjnath\ice_strans.h"\
+ "..\..\..\pjnath\include\pjnath\nat_detect.h"\
+ "..\..\..\pjnath\include\pjnath\stun_auth.h"\
+ "..\..\..\pjnath\include\pjnath\stun_config.h"\
+ "..\..\..\pjnath\include\pjnath\stun_msg.h"\
+ "..\..\..\pjnath\include\pjnath\stun_session.h"\
+ "..\..\..\pjnath\include\pjnath\stun_transaction.h"\
+ "..\..\..\pjnath\include\pjnath\types.h"\
+ "..\..\..\pjsip\include\pjsip-simple\evsub.h"\
+ "..\..\..\pjsip\include\pjsip-simple\iscomposing.h"\
+ "..\..\..\pjsip\include\pjsip-simple\pidf.h"\
+ "..\..\..\pjsip\include\pjsip-simple\presence.h"\
+ "..\..\..\pjsip\include\pjsip-simple\publish.h"\
+ "..\..\..\pjsip\include\pjsip-simple\rpid.h"\
+ "..\..\..\pjsip\include\pjsip-simple\types.h"\
+ "..\..\..\pjsip\include\pjsip-simple\xpidf.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_100rel.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_inv.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_regc.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_replaces.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_xfer.h"\
+ "..\..\..\pjsip\include\pjsip.h"\
+ "..\..\..\pjsip\include\pjsip\sip_auth.h"\
+ "..\..\..\pjsip\include\pjsip\sip_auth_aka.h"\
+ "..\..\..\pjsip\include\pjsip\sip_auth_msg.h"\
+ "..\..\..\pjsip\include\pjsip\sip_autoconf.h"\
+ "..\..\..\pjsip\include\pjsip\sip_config.h"\
+ "..\..\..\pjsip\include\pjsip\sip_dialog.h"\
+ "..\..\..\pjsip\include\pjsip\sip_endpoint.h"\
+ "..\..\..\pjsip\include\pjsip\sip_errno.h"\
+ "..\..\..\pjsip\include\pjsip\sip_event.h"\
+ "..\..\..\pjsip\include\pjsip\sip_module.h"\
+ "..\..\..\pjsip\include\pjsip\sip_msg.h"\
+ "..\..\..\pjsip\include\pjsip\sip_parser.h"\
+ "..\..\..\pjsip\include\pjsip\sip_resolve.h"\
+ "..\..\..\pjsip\include\pjsip\sip_tel_uri.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transaction.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport_loop.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport_tcp.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport_tls.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport_udp.h"\
+ "..\..\..\pjsip\include\pjsip\sip_types.h"\
+ "..\..\..\pjsip\include\pjsip\sip_ua_layer.h"\
+ "..\..\..\pjsip\include\pjsip\sip_uri.h"\
+ "..\..\..\pjsip\include\pjsip\sip_util.h"\
+ "..\..\..\pjsip\include\pjsip_simple.h"\
+ "..\..\..\pjsip\include\pjsip_ua.h"\
+ "..\..\..\pjsip\include\pjsua-lib\pjsua.h"\
+ ".\PocketPJ.h"\
+ ".\PocketPJDlg.h"\
+ ".\PopUpDlg.h"\
+ ".\SettingsDlg.h"\
+ ".\StdAfx.h"\
+
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\PopUpWnd.cpp
+
+!IF "$(CFG)" == "PocketPJ - Win32 (WCE emulator) Release"
+
+DEP_CPP_POPUP=\
+ ".\PopUpWnd.h"\
+ ".\StdAfx.h"\
+
+
+!ELSEIF "$(CFG)" == "PocketPJ - Win32 (WCE emulator) Debug"
+
+DEP_CPP_POPUP=\
+ "..\..\..\pjlib-util\include\pjlib-util.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\base64.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\config.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\crc32.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\dns.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\errno.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\getopt.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\hmac_md5.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\hmac_sha1.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\md5.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\pcap.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\resolver.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\scanner.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\scanner_cis_bitwise.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\scanner_cis_uint.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\sha1.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\srv_resolver.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\stun_simple.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\types.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\xml.h"\
+ "..\..\..\pjlib\include\pj\addr_resolv.h"\
+ "..\..\..\pjlib\include\pj\array.h"\
+ "..\..\..\pjlib\include\pj\assert.h"\
+ "..\..\..\pjlib\include\pj\compat\assert.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_armcc.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_codew.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_gcce.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_mwcc.h"\
+ "..\..\..\pjlib\include\pj\compat\ctype.h"\
+ "..\..\..\pjlib\include\pj\compat\errno.h"\
+ "..\..\..\pjlib\include\pj\compat\high_precision.h"\
+ "..\..\..\pjlib\include\pj\compat\m_auto.h"\
+ "..\..\..\pjlib\include\pj\compat\os_auto.h"\
+ "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\
+ "..\..\..\pjlib\include\pj\compat\os_linux.h"\
+ "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\
+ "..\..\..\pjlib\include\pj\compat\os_palmos.h"\
+ "..\..\..\pjlib\include\pj\compat\os_rtems.h"\
+ "..\..\..\pjlib\include\pj\compat\os_sunos.h"\
+ "..\..\..\pjlib\include\pj\compat\os_symbian.h"\
+ "..\..\..\pjlib\include\pj\compat\os_win32.h"\
+ "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\
+ "..\..\..\pjlib\include\pj\compat\setjmp.h"\
+ "..\..\..\pjlib\include\pj\compat\size_t.h"\
+ "..\..\..\pjlib\include\pj\compat\stdarg.h"\
+ "..\..\..\pjlib\include\pj\compat\string.h"\
+ "..\..\..\pjlib\include\pj\config.h"\
+ "..\..\..\pjlib\include\pj\config_site.h"\
+ "..\..\..\pjlib\include\pj\config_site_sample.h"\
+ "..\..\..\pjlib\include\pj\ctype.h"\
+ "..\..\..\pjlib\include\pj\errno.h"\
+ "..\..\..\pjlib\include\pj\except.h"\
+ "..\..\..\pjlib\include\pj\fifobuf.h"\
+ "..\..\..\pjlib\include\pj\file_access.h"\
+ "..\..\..\pjlib\include\pj\file_io.h"\
+ "..\..\..\pjlib\include\pj\guid.h"\
+ "..\..\..\pjlib\include\pj\hash.h"\
+ "..\..\..\pjlib\include\pj\ioqueue.h"\
+ "..\..\..\pjlib\include\pj\ip_helper.h"\
+ "..\..\..\pjlib\include\pj\list.h"\
+ "..\..\..\pjlib\include\pj\list_i.h"\
+ "..\..\..\pjlib\include\pj\lock.h"\
+ "..\..\..\pjlib\include\pj\log.h"\
+ "..\..\..\pjlib\include\pj\os.h"\
+ "..\..\..\pjlib\include\pj\pool.h"\
+ "..\..\..\pjlib\include\pj\pool_alt.h"\
+ "..\..\..\pjlib\include\pj\pool_buf.h"\
+ "..\..\..\pjlib\include\pj\pool_i.h"\
+ "..\..\..\pjlib\include\pj\rand.h"\
+ "..\..\..\pjlib\include\pj\rbtree.h"\
+ "..\..\..\pjlib\include\pj\sock.h"\
+ "..\..\..\pjlib\include\pj\sock_select.h"\
+ "..\..\..\pjlib\include\pj\string.h"\
+ "..\..\..\pjlib\include\pj\string_i.h"\
+ "..\..\..\pjlib\include\pj\timer.h"\
+ "..\..\..\pjlib\include\pj\types.h"\
+ "..\..\..\pjlib\include\pj\unicode.h"\
+ "..\..\..\pjlib\include\pjlib.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\config.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\config_auto.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\gsm.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\ilbc.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\l16.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\speex.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\types.h"\
+ "..\..\..\pjmedia\include\pjmedia.h"\
+ "..\..\..\pjmedia\include\pjmedia\alaw_ulaw.h"\
+ "..\..\..\pjmedia\include\pjmedia\bidirectional.h"\
+ "..\..\..\pjmedia\include\pjmedia\clock.h"\
+ "..\..\..\pjmedia\include\pjmedia\codec.h"\
+ "..\..\..\pjmedia\include\pjmedia\conference.h"\
+ "..\..\..\pjmedia\include\pjmedia\config.h"\
+ "..\..\..\pjmedia\include\pjmedia\config_auto.h"\
+ "..\..\..\pjmedia\include\pjmedia\echo.h"\
+ "..\..\..\pjmedia\include\pjmedia\echo_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\endpoint.h"\
+ "..\..\..\pjmedia\include\pjmedia\errno.h"\
+ "..\..\..\pjmedia\include\pjmedia\g711.h"\
+ "..\..\..\pjmedia\include\pjmedia\jbuf.h"\
+ "..\..\..\pjmedia\include\pjmedia\master_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\mem_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\null_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\plc.h"\
+ "..\..\..\pjmedia\include\pjmedia\port.h"\
+ "..\..\..\pjmedia\include\pjmedia\resample.h"\
+ "..\..\..\pjmedia\include\pjmedia\rtcp.h"\
+ "..\..\..\pjmedia\include\pjmedia\rtp.h"\
+ "..\..\..\pjmedia\include\pjmedia\sdp.h"\
+ "..\..\..\pjmedia\include\pjmedia\sdp_neg.h"\
+ "..\..\..\pjmedia\include\pjmedia\session.h"\
+ "..\..\..\pjmedia\include\pjmedia\silencedet.h"\
+ "..\..\..\pjmedia\include\pjmedia\sound.h"\
+ "..\..\..\pjmedia\include\pjmedia\sound_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\splitcomb.h"\
+ "..\..\..\pjmedia\include\pjmedia\stream.h"\
+ "..\..\..\pjmedia\include\pjmedia\tonegen.h"\
+ "..\..\..\pjmedia\include\pjmedia\transport.h"\
+ "..\..\..\pjmedia\include\pjmedia\transport_ice.h"\
+ "..\..\..\pjmedia\include\pjmedia\transport_srtp.h"\
+ "..\..\..\pjmedia\include\pjmedia\transport_udp.h"\
+ "..\..\..\pjmedia\include\pjmedia\types.h"\
+ "..\..\..\pjmedia\include\pjmedia\wav_playlist.h"\
+ "..\..\..\pjmedia\include\pjmedia\wav_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\wave.h"\
+ "..\..\..\pjnath\include\pjnath.h"\
+ "..\..\..\pjnath\include\pjnath\config.h"\
+ "..\..\..\pjnath\include\pjnath\errno.h"\
+ "..\..\..\pjnath\include\pjnath\ice_session.h"\
+ "..\..\..\pjnath\include\pjnath\ice_strans.h"\
+ "..\..\..\pjnath\include\pjnath\nat_detect.h"\
+ "..\..\..\pjnath\include\pjnath\stun_auth.h"\
+ "..\..\..\pjnath\include\pjnath\stun_config.h"\
+ "..\..\..\pjnath\include\pjnath\stun_msg.h"\
+ "..\..\..\pjnath\include\pjnath\stun_session.h"\
+ "..\..\..\pjnath\include\pjnath\stun_transaction.h"\
+ "..\..\..\pjnath\include\pjnath\types.h"\
+ "..\..\..\pjsip\include\pjsip-simple\evsub.h"\
+ "..\..\..\pjsip\include\pjsip-simple\iscomposing.h"\
+ "..\..\..\pjsip\include\pjsip-simple\pidf.h"\
+ "..\..\..\pjsip\include\pjsip-simple\presence.h"\
+ "..\..\..\pjsip\include\pjsip-simple\publish.h"\
+ "..\..\..\pjsip\include\pjsip-simple\rpid.h"\
+ "..\..\..\pjsip\include\pjsip-simple\types.h"\
+ "..\..\..\pjsip\include\pjsip-simple\xpidf.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_100rel.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_inv.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_regc.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_replaces.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_xfer.h"\
+ "..\..\..\pjsip\include\pjsip.h"\
+ "..\..\..\pjsip\include\pjsip\sip_auth.h"\
+ "..\..\..\pjsip\include\pjsip\sip_auth_aka.h"\
+ "..\..\..\pjsip\include\pjsip\sip_auth_msg.h"\
+ "..\..\..\pjsip\include\pjsip\sip_autoconf.h"\
+ "..\..\..\pjsip\include\pjsip\sip_config.h"\
+ "..\..\..\pjsip\include\pjsip\sip_dialog.h"\
+ "..\..\..\pjsip\include\pjsip\sip_endpoint.h"\
+ "..\..\..\pjsip\include\pjsip\sip_errno.h"\
+ "..\..\..\pjsip\include\pjsip\sip_event.h"\
+ "..\..\..\pjsip\include\pjsip\sip_module.h"\
+ "..\..\..\pjsip\include\pjsip\sip_msg.h"\
+ "..\..\..\pjsip\include\pjsip\sip_parser.h"\
+ "..\..\..\pjsip\include\pjsip\sip_resolve.h"\
+ "..\..\..\pjsip\include\pjsip\sip_tel_uri.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transaction.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport_loop.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport_tcp.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport_tls.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport_udp.h"\
+ "..\..\..\pjsip\include\pjsip\sip_types.h"\
+ "..\..\..\pjsip\include\pjsip\sip_ua_layer.h"\
+ "..\..\..\pjsip\include\pjsip\sip_uri.h"\
+ "..\..\..\pjsip\include\pjsip\sip_util.h"\
+ "..\..\..\pjsip\include\pjsip_simple.h"\
+ "..\..\..\pjsip\include\pjsip_ua.h"\
+ "..\..\..\pjsip\include\pjsua-lib\pjsua.h"\
+ ".\PocketPJDlg.h"\
+ ".\PopUpWnd.h"\
+ ".\SettingsDlg.h"\
+ ".\StdAfx.h"\
+
+
+!ELSEIF "$(CFG)" == "PocketPJ - Win32 (WCE ARMV4) Release"
+
+DEP_CPP_POPUP=\
+ "..\..\..\pjlib-util\include\pjlib-util.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\base64.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\config.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\crc32.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\dns.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\errno.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\getopt.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\hmac_md5.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\hmac_sha1.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\md5.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\pcap.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\resolver.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\scanner.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\scanner_cis_bitwise.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\scanner_cis_uint.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\sha1.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\srv_resolver.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\stun_simple.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\types.h"\
+ "..\..\..\pjlib-util\include\pjlib-util\xml.h"\
+ "..\..\..\pjlib\include\pj\addr_resolv.h"\
+ "..\..\..\pjlib\include\pj\array.h"\
+ "..\..\..\pjlib\include\pj\assert.h"\
+ "..\..\..\pjlib\include\pj\compat\assert.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_armcc.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_codew.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_gcce.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\
+ "..\..\..\pjlib\include\pj\compat\cc_mwcc.h"\
+ "..\..\..\pjlib\include\pj\compat\ctype.h"\
+ "..\..\..\pjlib\include\pj\compat\errno.h"\
+ "..\..\..\pjlib\include\pj\compat\high_precision.h"\
+ "..\..\..\pjlib\include\pj\compat\m_auto.h"\
+ "..\..\..\pjlib\include\pj\compat\os_auto.h"\
+ "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\
+ "..\..\..\pjlib\include\pj\compat\os_linux.h"\
+ "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\
+ "..\..\..\pjlib\include\pj\compat\os_palmos.h"\
+ "..\..\..\pjlib\include\pj\compat\os_rtems.h"\
+ "..\..\..\pjlib\include\pj\compat\os_sunos.h"\
+ "..\..\..\pjlib\include\pj\compat\os_symbian.h"\
+ "..\..\..\pjlib\include\pj\compat\os_win32.h"\
+ "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\
+ "..\..\..\pjlib\include\pj\compat\setjmp.h"\
+ "..\..\..\pjlib\include\pj\compat\size_t.h"\
+ "..\..\..\pjlib\include\pj\compat\stdarg.h"\
+ "..\..\..\pjlib\include\pj\compat\string.h"\
+ "..\..\..\pjlib\include\pj\config.h"\
+ "..\..\..\pjlib\include\pj\config_site.h"\
+ "..\..\..\pjlib\include\pj\config_site_sample.h"\
+ "..\..\..\pjlib\include\pj\ctype.h"\
+ "..\..\..\pjlib\include\pj\errno.h"\
+ "..\..\..\pjlib\include\pj\except.h"\
+ "..\..\..\pjlib\include\pj\fifobuf.h"\
+ "..\..\..\pjlib\include\pj\file_access.h"\
+ "..\..\..\pjlib\include\pj\file_io.h"\
+ "..\..\..\pjlib\include\pj\guid.h"\
+ "..\..\..\pjlib\include\pj\hash.h"\
+ "..\..\..\pjlib\include\pj\ioqueue.h"\
+ "..\..\..\pjlib\include\pj\ip_helper.h"\
+ "..\..\..\pjlib\include\pj\list.h"\
+ "..\..\..\pjlib\include\pj\list_i.h"\
+ "..\..\..\pjlib\include\pj\lock.h"\
+ "..\..\..\pjlib\include\pj\log.h"\
+ "..\..\..\pjlib\include\pj\os.h"\
+ "..\..\..\pjlib\include\pj\pool.h"\
+ "..\..\..\pjlib\include\pj\pool_alt.h"\
+ "..\..\..\pjlib\include\pj\pool_buf.h"\
+ "..\..\..\pjlib\include\pj\pool_i.h"\
+ "..\..\..\pjlib\include\pj\rand.h"\
+ "..\..\..\pjlib\include\pj\rbtree.h"\
+ "..\..\..\pjlib\include\pj\sock.h"\
+ "..\..\..\pjlib\include\pj\sock_select.h"\
+ "..\..\..\pjlib\include\pj\string.h"\
+ "..\..\..\pjlib\include\pj\string_i.h"\
+ "..\..\..\pjlib\include\pj\timer.h"\
+ "..\..\..\pjlib\include\pj\types.h"\
+ "..\..\..\pjlib\include\pj\unicode.h"\
+ "..\..\..\pjlib\include\pjlib.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\config.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\config_auto.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\gsm.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\ilbc.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\l16.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\speex.h"\
+ "..\..\..\pjmedia\include\pjmedia-codec\types.h"\
+ "..\..\..\pjmedia\include\pjmedia.h"\
+ "..\..\..\pjmedia\include\pjmedia\alaw_ulaw.h"\
+ "..\..\..\pjmedia\include\pjmedia\bidirectional.h"\
+ "..\..\..\pjmedia\include\pjmedia\clock.h"\
+ "..\..\..\pjmedia\include\pjmedia\codec.h"\
+ "..\..\..\pjmedia\include\pjmedia\conference.h"\
+ "..\..\..\pjmedia\include\pjmedia\config.h"\
+ "..\..\..\pjmedia\include\pjmedia\config_auto.h"\
+ "..\..\..\pjmedia\include\pjmedia\echo.h"\
+ "..\..\..\pjmedia\include\pjmedia\echo_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\endpoint.h"\
+ "..\..\..\pjmedia\include\pjmedia\errno.h"\
+ "..\..\..\pjmedia\include\pjmedia\g711.h"\
+ "..\..\..\pjmedia\include\pjmedia\jbuf.h"\
+ "..\..\..\pjmedia\include\pjmedia\master_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\mem_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\null_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\plc.h"\
+ "..\..\..\pjmedia\include\pjmedia\port.h"\
+ "..\..\..\pjmedia\include\pjmedia\resample.h"\
+ "..\..\..\pjmedia\include\pjmedia\rtcp.h"\
+ "..\..\..\pjmedia\include\pjmedia\rtp.h"\
+ "..\..\..\pjmedia\include\pjmedia\sdp.h"\
+ "..\..\..\pjmedia\include\pjmedia\sdp_neg.h"\
+ "..\..\..\pjmedia\include\pjmedia\session.h"\
+ "..\..\..\pjmedia\include\pjmedia\silencedet.h"\
+ "..\..\..\pjmedia\include\pjmedia\sound.h"\
+ "..\..\..\pjmedia\include\pjmedia\sound_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\splitcomb.h"\
+ "..\..\..\pjmedia\include\pjmedia\stream.h"\
+ "..\..\..\pjmedia\include\pjmedia\tonegen.h"\
+ "..\..\..\pjmedia\include\pjmedia\transport.h"\
+ "..\..\..\pjmedia\include\pjmedia\transport_ice.h"\
+ "..\..\..\pjmedia\include\pjmedia\transport_srtp.h"\
+ "..\..\..\pjmedia\include\pjmedia\transport_udp.h"\
+ "..\..\..\pjmedia\include\pjmedia\types.h"\
+ "..\..\..\pjmedia\include\pjmedia\wav_playlist.h"\
+ "..\..\..\pjmedia\include\pjmedia\wav_port.h"\
+ "..\..\..\pjmedia\include\pjmedia\wave.h"\
+ "..\..\..\pjnath\include\pjnath.h"\
+ "..\..\..\pjnath\include\pjnath\config.h"\
+ "..\..\..\pjnath\include\pjnath\errno.h"\
+ "..\..\..\pjnath\include\pjnath\ice_session.h"\
+ "..\..\..\pjnath\include\pjnath\ice_strans.h"\
+ "..\..\..\pjnath\include\pjnath\nat_detect.h"\
+ "..\..\..\pjnath\include\pjnath\stun_auth.h"\
+ "..\..\..\pjnath\include\pjnath\stun_config.h"\
+ "..\..\..\pjnath\include\pjnath\stun_msg.h"\
+ "..\..\..\pjnath\include\pjnath\stun_session.h"\
+ "..\..\..\pjnath\include\pjnath\stun_transaction.h"\
+ "..\..\..\pjnath\include\pjnath\types.h"\
+ "..\..\..\pjsip\include\pjsip-simple\evsub.h"\
+ "..\..\..\pjsip\include\pjsip-simple\iscomposing.h"\
+ "..\..\..\pjsip\include\pjsip-simple\pidf.h"\
+ "..\..\..\pjsip\include\pjsip-simple\presence.h"\
+ "..\..\..\pjsip\include\pjsip-simple\publish.h"\
+ "..\..\..\pjsip\include\pjsip-simple\rpid.h"\
+ "..\..\..\pjsip\include\pjsip-simple\types.h"\
+ "..\..\..\pjsip\include\pjsip-simple\xpidf.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_100rel.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_inv.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_regc.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_replaces.h"\
+ "..\..\..\pjsip\include\pjsip-ua\sip_xfer.h"\
+ "..\..\..\pjsip\include\pjsip.h"\
+ "..\..\..\pjsip\include\pjsip\sip_auth.h"\
+ "..\..\..\pjsip\include\pjsip\sip_auth_aka.h"\
+ "..\..\..\pjsip\include\pjsip\sip_auth_msg.h"\
+ "..\..\..\pjsip\include\pjsip\sip_autoconf.h"\
+ "..\..\..\pjsip\include\pjsip\sip_config.h"\
+ "..\..\..\pjsip\include\pjsip\sip_dialog.h"\
+ "..\..\..\pjsip\include\pjsip\sip_endpoint.h"\
+ "..\..\..\pjsip\include\pjsip\sip_errno.h"\
+ "..\..\..\pjsip\include\pjsip\sip_event.h"\
+ "..\..\..\pjsip\include\pjsip\sip_module.h"\
+ "..\..\..\pjsip\include\pjsip\sip_msg.h"\
+ "..\..\..\pjsip\include\pjsip\sip_parser.h"\
+ "..\..\..\pjsip\include\pjsip\sip_resolve.h"\
+ "..\..\..\pjsip\include\pjsip\sip_tel_uri.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transaction.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport_loop.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport_tcp.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport_tls.h"\
+ "..\..\..\pjsip\include\pjsip\sip_transport_udp.h"\
+ "..\..\..\pjsip\include\pjsip\sip_types.h"\
+ "..\..\..\pjsip\include\pjsip\sip_ua_layer.h"\
+ "..\..\..\pjsip\include\pjsip\sip_uri.h"\
+ "..\..\..\pjsip\include\pjsip\sip_util.h"\
+ "..\..\..\pjsip\include\pjsip_simple.h"\
+ "..\..\..\pjsip\include\pjsip_ua.h"\
+ "..\..\..\pjsip\include\pjsua-lib\pjsua.h"\
+ ".\PocketPJDlg.h"\
+ ".\PopUpWnd.h"\
+ ".\SettingsDlg.h"\
+ ".\StdAfx.h"\
+
+
+!ELSEIF "$(CFG)" == "PocketPJ - Win32 (WCE ARMV4) Debug"
+
+DEP_CPP_POPUP=\
+ ".\PopUpWnd.h"\
+ ".\StdAfx.h"\
+
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\SettingsDlg.cpp
+
+!IF "$(CFG)" == "PocketPJ - Win32 (WCE emulator) Release"
+
+DEP_CPP_SETTI=\
+ ".\PocketPJ.h"\
+ ".\SettingsDlg.h"\
+ ".\StdAfx.h"\
+
+
+!ELSEIF "$(CFG)" == "PocketPJ - Win32 (WCE emulator) Debug"
+
+DEP_CPP_SETTI=\
+ ".\PocketPJ.h"\
+ ".\SettingsDlg.h"\
+ ".\StdAfx.h"\
+
+
+!ELSEIF "$(CFG)" == "PocketPJ - Win32 (WCE ARMV4) Release"
+
+DEP_CPP_SETTI=\
+ ".\PocketPJ.h"\
+ ".\SettingsDlg.h"\
+ ".\StdAfx.h"\
+
+
+!ELSEIF "$(CFG)" == "PocketPJ - Win32 (WCE ARMV4) Debug"
+
+DEP_CPP_SETTI=\
+ ".\PocketPJ.h"\
+ ".\SettingsDlg.h"\
+ ".\StdAfx.h"\
+
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.cpp
+
+!IF "$(CFG)" == "PocketPJ - Win32 (WCE emulator) Release"
+
+DEP_CPP_STDAF=\
+ ".\StdAfx.h"\
+
+# ADD CPP /Yc"stdafx.h"
+
+!ELSEIF "$(CFG)" == "PocketPJ - Win32 (WCE emulator) Debug"
+
+DEP_CPP_STDAF=\
+ ".\StdAfx.h"\
+
+# ADD CPP /Yc"stdafx.h"
+
+!ELSEIF "$(CFG)" == "PocketPJ - Win32 (WCE ARMV4) Release"
+
+DEP_CPP_STDAF=\
+ ".\StdAfx.h"\
+
+# ADD CPP /Yc"stdafx.h"
+
+!ELSEIF "$(CFG)" == "PocketPJ - Win32 (WCE ARMV4) Debug"
+
+DEP_CPP_STDAF=\
+ ".\StdAfx.h"\
+
+# ADD CPP /Yc"stdafx.h"
+
+!ENDIF
+
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\newres.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\PocketPJ.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\PocketPJDlg.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\PopUpWnd.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Resource.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\SettingsDlg.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\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=.\res\action.bmp
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\blank.bmp
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\invisibl.bmp
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\invisibl.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\offline.bmp
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\offline.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\online.bmp
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\online.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\PocketPJ.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\PocketPJ.rc2
+# PROP Exclude_From_Scan -1
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\ReadMe.txt
+# End Source File
+# End Target
+# End Project
diff --git a/pjsip-apps/src/pocketpj/PocketPJ.vcproj b/pjsip-apps/src/pocketpj/PocketPJ.vcproj
new file mode 100644
index 0000000..b1d2039
--- /dev/null
+++ b/pjsip-apps/src/pocketpj/PocketPJ.vcproj
@@ -0,0 +1,5137 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="PocketPJ"
+ ProjectGUID="{48450961-D0DF-4B59-BD8D-39455AA02DF8}"
+ RootNamespace="PocketPJ"
+ Keyword="MFCProj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="Windows Mobile 6 Professional SDK (ARMV4I)"
+ />
+ <Platform
+ Name="Windows Mobile 6 Standard SDK (ARMV4I)"
+ />
+ <Platform
+ Name="Pocket PC 2003 (ARMV4)"
+ />
+ <Platform
+ Name="Smartphone 2003 (ARMV4)"
+ />
+ <Platform
+ Name="Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ />
+ <Platform
+ Name="Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-win32-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ ConfigurationType="1"
+ UseOfMFC="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="_CONSOLE;"
+ AdditionalIncludeDirectories="../../../pjlib/include,../../../pjlib-util/include,../../../pjnath/include,../../../pjmedia/include,../../../pjsip/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib secchk.lib ccrtrtti.lib"
+ OutputFile="..\..\bin\$(ProjectName)-$(TargetCPU)-$(PlatformName)-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Windows Mobile 6 Professional SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm6-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../../pjlib/include,../../../pjlib-util/include,../../../pjnath/include,../../../pjmedia/include,../../../pjsip/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\$(ProjectName)-$(TargetCPU)-wm6pro-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles="msvcr80.dll|$(BINDIR)\$(INSTRUCTIONSET)\|%CSIDL_PROGRAM_FILES%\$(ProjectName)|0;atl80.dll|$(BINDIR)\$(INSTRUCTIONSET)\|%CSIDL_PROGRAM_FILES%\$(ProjectName)|0;MFC80U.dll|$(BINDIR)\$(INSTRUCTIONSET)\|%CSIDL_PROGRAM_FILES%\$(ProjectName)|0;"
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Windows Mobile 6 Standard SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm6-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../../pjlib/include,../../../pjlib-util/include,../../../pjnath/include,../../../pjmedia/include,../../../pjsip/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\$(ProjectName)-$(TargetCPU)-wm6std-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Pocket PC 2003 (ARMV4)"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm2003-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../../pjlib/include,../../../pjlib-util/include,../../../pjnath/include,../../../pjmedia/include,../../../pjsip/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\$(ProjectName)-$(TargetCPU)-wm2003ppc-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Smartphone 2003 (ARMV4)"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm2003-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../../pjlib/include,../../../pjlib-util/include,../../../pjnath/include,../../../pjmedia/include,../../../pjsip/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\$(ProjectName)-$(TargetCPU)-wm2003sp-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm5-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../../pjlib/include,../../../pjlib-util/include,../../../pjnath/include,../../../pjmedia/include,../../../pjsip/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\$(ProjectName)-$(TargetCPU)-wm5ppc-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm5-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../../pjlib/include,../../../pjlib-util/include,../../../pjnath/include,../../../pjmedia/include,../../../pjsip/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\$(ProjectName)-$(TargetCPU)-wm5sp-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-win32-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ ConfigurationType="1"
+ UseOfMFC="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="_CONSOLE;"
+ AdditionalIncludeDirectories="../../../pjlib/include,../../../pjlib-util/include,../../../pjnath/include,../../../pjmedia/include,../../../pjsip/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib secchk.lib ccrtrtti.lib"
+ OutputFile="..\..\bin\$(ProjectName)-$(TargetCPU)-$(PlatformName)-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Windows Mobile 6 Professional SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm6-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../../pjlib/include,../../../pjlib-util/include,../../../pjnath/include,../../../pjmedia/include,../../../pjsip/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\$(ProjectName)-$(TargetCPU)-wm6pro-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles="msvcr80.dll|$(BINDIR)\$(INSTRUCTIONSET)\|%CSIDL_PROGRAM_FILES%\$(ProjectName)|0;atl80.dll|$(BINDIR)\$(INSTRUCTIONSET)\|%CSIDL_PROGRAM_FILES%\$(ProjectName)|0;msvcr80d.dll|$(BINDIR)\$(INSTRUCTIONSET)\|%CSIDL_PROGRAM_FILES%\$(ProjectName)|0;MFC80UD.dll|$(BINDIR)\$(INSTRUCTIONSET)\|%CSIDL_PROGRAM_FILES%\$(ProjectName)|0;"
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Windows Mobile 6 Standard SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm6-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../../pjlib/include,../../../pjlib-util/include,../../../pjnath/include,../../../pjmedia/include,../../../pjsip/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\$(ProjectName)-$(TargetCPU)-wm6std-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Pocket PC 2003 (ARMV4)"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm2003-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../../pjlib/include,../../../pjlib-util/include,../../../pjnath/include,../../../pjmedia/include,../../../pjsip/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\$(ProjectName)-$(TargetCPU)-wm2003ppc-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Smartphone 2003 (ARMV4)"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm2003-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../../pjlib/include,../../../pjlib-util/include,../../../pjnath/include,../../../pjmedia/include,../../../pjsip/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\$(ProjectName)-$(TargetCPU)-wm2003sp-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm5-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../../pjlib/include,../../../pjlib-util/include,../../../pjnath/include,../../../pjmedia/include,../../../pjsip/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\$(ProjectName)-$(TargetCPU)-wm5ppc-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm5-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../../pjlib/include,../../../pjlib-util/include,../../../pjnath/include,../../../pjmedia/include,../../../pjsip/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\$(ProjectName)-$(TargetCPU)-wm5sp-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Dynamic|Win32"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-debug-dynamic-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-win32-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ ConfigurationType="1"
+ UseOfMFC="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="_CONSOLE;"
+ AdditionalIncludeDirectories="../../../pjlib/include,../../../pjlib-util/include,../../../pjnath/include,../../../pjmedia/include,../../../pjsip/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib secchk.lib ccrtrtti.lib"
+ OutputFile="..\..\bin\$(ProjectName)-$(TargetCPU)-$(PlatformName)-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Dynamic|Windows Mobile 6 Professional SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-debug-dynamic-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm6-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../../pjlib/include,../../../pjlib-util/include,../../../pjnath/include,../../../pjmedia/include,../../../pjsip/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\$(ProjectName)-$(TargetCPU)-wm6pro-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Dynamic|Windows Mobile 6 Standard SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-debug-dynamic-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm6-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../../pjlib/include,../../../pjlib-util/include,../../../pjnath/include,../../../pjmedia/include,../../../pjsip/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\$(ProjectName)-$(TargetCPU)-wm6std-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Dynamic|Pocket PC 2003 (ARMV4)"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-debug-dynamic-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm2003-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../../pjlib/include,../../../pjlib-util/include,../../../pjnath/include,../../../pjmedia/include,../../../pjsip/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\$(ProjectName)-$(TargetCPU)-wm2003ppc-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Dynamic|Smartphone 2003 (ARMV4)"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-debug-dynamic-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm2003-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../../pjlib/include,../../../pjlib-util/include,../../../pjnath/include,../../../pjmedia/include,../../../pjsip/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\$(ProjectName)-$(TargetCPU)-wm2003sp-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Dynamic|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-debug-dynamic-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm5-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../../pjlib/include,../../../pjlib-util/include,../../../pjnath/include,../../../pjmedia/include,../../../pjsip/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\$(ProjectName)-$(TargetCPU)-wm5ppc-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Dynamic|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-debug-dynamic-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm5-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../../pjlib/include,../../../pjlib-util/include,../../../pjnath/include,../../../pjmedia/include,../../../pjsip/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\$(ProjectName)-$(TargetCPU)-wm5sp-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Static|Win32"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-win32-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ ConfigurationType="1"
+ UseOfMFC="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="_CONSOLE;"
+ AdditionalIncludeDirectories="../../../pjlib/include,../../../pjlib-util/include,../../../pjnath/include,../../../pjmedia/include,../../../pjsip/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib secchk.lib ccrtrtti.lib"
+ OutputFile="..\..\bin\$(ProjectName)-$(TargetCPU)-$(PlatformName)-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Static|Windows Mobile 6 Professional SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm6-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../../pjlib/include,../../../pjlib-util/include,../../../pjnath/include,../../../pjmedia/include,../../../pjsip/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\$(ProjectName)-$(TargetCPU)-wm6pro-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Static|Windows Mobile 6 Standard SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm6-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../../pjlib/include,../../../pjlib-util/include,../../../pjnath/include,../../../pjmedia/include,../../../pjsip/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\$(ProjectName)-$(TargetCPU)-wm6std-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Static|Pocket PC 2003 (ARMV4)"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm2003-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../../pjlib/include,../../../pjlib-util/include,../../../pjnath/include,../../../pjmedia/include,../../../pjsip/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\$(ProjectName)-$(TargetCPU)-wm2003ppc-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Static|Smartphone 2003 (ARMV4)"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm2003-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../../pjlib/include,../../../pjlib-util/include,../../../pjnath/include,../../../pjmedia/include,../../../pjsip/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\$(ProjectName)-$(TargetCPU)-wm2003sp-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Static|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm5-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../../pjlib/include,../../../pjlib-util/include,../../../pjnath/include,../../../pjmedia/include,../../../pjsip/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\$(ProjectName)-$(TargetCPU)-wm5ppc-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug-Static|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-debug-static-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm5-common-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../../pjlib/include,../../../pjlib-util/include,../../../pjnath/include,../../../pjmedia/include,../../../pjsip/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\$(ProjectName)-$(TargetCPU)-wm5sp-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Dynamic|Win32"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-win32-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ ConfigurationType="1"
+ UseOfMFC="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="_CONSOLE;"
+ AdditionalIncludeDirectories="../../../pjlib/include,../../../pjlib-util/include,../../../pjnath/include,../../../pjmedia/include,../../../pjsip/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib secchk.lib ccrtrtti.lib"
+ OutputFile="..\..\bin\$(ProjectName)-$(TargetCPU)-$(PlatformName)-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Dynamic|Windows Mobile 6 Professional SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm6-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../../pjlib/include,../../../pjlib-util/include,../../../pjnath/include,../../../pjmedia/include,../../../pjsip/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\$(ProjectName)-$(TargetCPU)-wm6pro-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Dynamic|Windows Mobile 6 Standard SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm6-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../../pjlib/include,../../../pjlib-util/include,../../../pjnath/include,../../../pjmedia/include,../../../pjsip/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\$(ProjectName)-$(TargetCPU)-wm6std-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Dynamic|Pocket PC 2003 (ARMV4)"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm2003-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../../pjlib/include,../../../pjlib-util/include,../../../pjnath/include,../../../pjmedia/include,../../../pjsip/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\$(ProjectName)-$(TargetCPU)-wm2003ppc-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Dynamic|Smartphone 2003 (ARMV4)"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm2003-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../../pjlib/include,../../../pjlib-util/include,../../../pjnath/include,../../../pjmedia/include,../../../pjsip/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\$(ProjectName)-$(TargetCPU)-wm2003sp-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Dynamic|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm5-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../../pjlib/include,../../../pjlib-util/include,../../../pjnath/include,../../../pjmedia/include,../../../pjsip/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\$(ProjectName)-$(TargetCPU)-wm5ppc-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Dynamic|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-release-dynamic-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm5-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../../pjlib/include,../../../pjlib-util/include,../../../pjnath/include,../../../pjmedia/include,../../../pjsip/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\$(ProjectName)-$(TargetCPU)-wm5sp-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Static|Win32"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-release-static-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-win32-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ ConfigurationType="1"
+ UseOfMFC="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="_CONSOLE;"
+ AdditionalIncludeDirectories="../../../pjlib/include,../../../pjlib-util/include,../../../pjnath/include,../../../pjmedia/include,../../../pjsip/include"
+ PrecompiledHeaderFile=""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib secchk.lib ccrtrtti.lib"
+ OutputFile="..\..\bin\$(ProjectName)-$(TargetCPU)-$(PlatformName)-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Static|Windows Mobile 6 Professional SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-release-static-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm6-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../../pjlib/include,../../../pjlib-util/include,../../../pjnath/include,../../../pjmedia/include,../../../pjsip/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\$(ProjectName)-$(TargetCPU)-wm6pro-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Static|Windows Mobile 6 Standard SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-release-static-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm6-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../../pjlib/include,../../../pjlib-util/include,../../../pjnath/include,../../../pjmedia/include,../../../pjsip/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\$(ProjectName)-$(TargetCPU)-wm6std-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Static|Pocket PC 2003 (ARMV4)"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-release-static-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm2003-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../../pjlib/include,../../../pjlib-util/include,../../../pjnath/include,../../../pjmedia/include,../../../pjsip/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\$(ProjectName)-$(TargetCPU)-wm2003ppc-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Static|Smartphone 2003 (ARMV4)"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-release-static-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm2003-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../../pjlib/include,../../../pjlib-util/include,../../../pjnath/include,../../../pjmedia/include,../../../pjsip/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\$(ProjectName)-$(TargetCPU)-wm2003sp-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Static|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-release-static-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm5-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../../pjlib/include,../../../pjlib-util/include,../../../pjnath/include,../../../pjmedia/include,../../../pjsip/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\$(ProjectName)-$(TargetCPU)-wm5ppc-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ <Configuration
+ Name="Release-Static|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ InheritedPropertySheets="..\..\..\build\vs\pjproject-vs8-release-static-defaults.vsprops;..\..\..\build\vs\pjproject-vs8-wm5-release-defaults.vsprops"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ ConfigurationType="1"
+ UseOfMFC="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ ExecutionBucket="7"
+ AdditionalIncludeDirectories="../../../pjlib/include,../../../pjlib-util/include,../../../pjnath/include,../../../pjmedia/include,../../../pjsip/include"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="commctrl.lib coredll.lib winsock.lib ws2.lib iphlpapi.lib"
+ OutputFile="..\..\bin\$(ProjectName)-$(TargetCPU)-wm5sp-vs$(VSVer)-$(ConfigurationName).exe"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCCodeSignTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ <DeploymentTool
+ ForceDirty="-1"
+ RemoteDirectory=""
+ RegisterOutput="0"
+ AdditionalFiles=""
+ />
+ <DebuggerTool
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath="PocketPJ.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="PocketPJ.rc"
+ >
+ </File>
+ <File
+ RelativePath="PocketPJDlg.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="PopUpWnd.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="SettingsDlg.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="StdAfx.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 6 Professional SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 6 Standard SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Pocket PC 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Smartphone 2003 (ARMV4)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath="newres.h"
+ >
+ </File>
+ <File
+ RelativePath="PocketPJ.h"
+ >
+ </File>
+ <File
+ RelativePath="PocketPJDlg.h"
+ >
+ </File>
+ <File
+ RelativePath="PopUpWnd.h"
+ >
+ </File>
+ <File
+ RelativePath="Resource.h"
+ >
+ </File>
+ <File
+ RelativePath="SettingsDlg.h"
+ >
+ </File>
+ <File
+ RelativePath="StdAfx.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+ >
+ <File
+ RelativePath="res\action.bmp"
+ >
+ </File>
+ <File
+ RelativePath="res\blank.bmp"
+ >
+ </File>
+ <File
+ RelativePath="res\invisibl.bmp"
+ >
+ </File>
+ <File
+ RelativePath="res\invisibl.ico"
+ >
+ </File>
+ <File
+ RelativePath="res\offline.bmp"
+ >
+ </File>
+ <File
+ RelativePath="res\offline.ico"
+ >
+ </File>
+ <File
+ RelativePath="res\online.bmp"
+ >
+ </File>
+ <File
+ RelativePath="res\online.ico"
+ >
+ </File>
+ <File
+ RelativePath="res\PocketPJ.ico"
+ >
+ </File>
+ <File
+ RelativePath="res\PocketPJ.rc2"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 6 Professional SDK (ARMV4I)"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 6 Standard SDK (ARMV4I)"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Pocket PC 2003 (ARMV4)"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Smartphone 2003 (ARMV4)"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 6 Professional SDK (ARMV4I)"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 6 Standard SDK (ARMV4I)"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Pocket PC 2003 (ARMV4)"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Smartphone 2003 (ARMV4)"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 6 Professional SDK (ARMV4I)"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 6 Standard SDK (ARMV4I)"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Pocket PC 2003 (ARMV4)"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Smartphone 2003 (ARMV4)"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Dynamic|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 6 Professional SDK (ARMV4I)"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 6 Standard SDK (ARMV4I)"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Pocket PC 2003 (ARMV4)"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Smartphone 2003 (ARMV4)"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug-Static|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 6 Professional SDK (ARMV4I)"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 6 Standard SDK (ARMV4I)"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Pocket PC 2003 (ARMV4)"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Smartphone 2003 (ARMV4)"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Dynamic|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 6 Professional SDK (ARMV4I)"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 6 Standard SDK (ARMV4I)"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Pocket PC 2003 (ARMV4)"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Smartphone 2003 (ARMV4)"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release-Static|Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <File
+ RelativePath="ReadMe.txt"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/pjsip-apps/src/pocketpj/PocketPJ.vcw b/pjsip-apps/src/pocketpj/PocketPJ.vcw
new file mode 100644
index 0000000..01521ae
--- /dev/null
+++ b/pjsip-apps/src/pocketpj/PocketPJ.vcw
@@ -0,0 +1,269 @@
+Microsoft eMbedded Visual Tools Workspace File, Format Version 4.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "PocketPJ"=".\PocketPJ.vcp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name libgsmcodec
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libportaudio
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libresample
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libsrtp
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name pjlib_util_wince
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name pjlib_wince
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name pjmedia_codec_wince
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name pjmedia_wince
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name pjnath_wince
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name pjsip_core_wince
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name pjsip_simple_wince
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name pjsip_ua_wince
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name pjsua_lib_wince
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libilbccodec
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libspeex
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name pjmedia_auddev_wince
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "libgsmcodec"="..\..\..\third_party\build\gsm\libgsmcodec.vcp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "libilbccodec"="..\..\..\third_party\build\ilbc\libilbccodec.vcp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "libportaudio"="..\..\..\third_party\build\portaudio\libportaudio.vcp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "libresample"="..\..\..\third_party\build\resample\libresample.vcp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "libspeex"="..\..\..\third_party\build\speex\libspeex.vcp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "libsrtp"="..\..\..\third_party\build\srtp\libsrtp.vcp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "pjlib_util_wince"="..\..\..\pjlib-util\build\wince-evc4\pjlib_util_wince.vcp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "pjlib_wince"="..\..\..\pjlib\build\wince-evc4\pjlib_wince.vcp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "pjmedia_auddev_wince"="..\..\..\pjmedia\build\wince-evc4\pjmedia_auddev_wince.vcp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "pjmedia_codec_wince"="..\..\..\pjmedia\build\wince-evc4\pjmedia_codec_wince.vcp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "pjmedia_wince"="..\..\..\pjmedia\build\wince-evc4\pjmedia_wince.vcp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "pjnath_wince"="..\..\..\pjnath\build\wince-evc4\pjnath_wince.vcp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "pjsip_core_wince"="..\..\..\pjsip\build\wince-evc4\pjsip_core_wince.vcp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "pjsip_simple_wince"="..\..\..\pjsip\build\wince-evc4\pjsip_simple_wince.vcp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "pjsip_ua_wince"="..\..\..\pjsip\build\wince-evc4\pjsip_ua_wince.vcp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "pjsua_lib_wince"="..\..\..\pjsip\build\wince-evc4\pjsua_lib_wince.vcp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/pjsip-apps/src/pocketpj/PocketPJDlg.cpp b/pjsip-apps/src/pocketpj/PocketPJDlg.cpp
new file mode 100644
index 0000000..87caf19
--- /dev/null
+++ b/pjsip-apps/src/pocketpj/PocketPJDlg.cpp
@@ -0,0 +1,792 @@
+// PocketPJDlg.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "PocketPJ.h"
+#include "PocketPJDlg.h"
+#include <iphlpapi.h>
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+#define TIMER_ID 101
+static CPocketPJDlg *theDlg;
+
+/////////////////////////////////////////////////////////////////////////////
+// CPocketPJDlg dialog
+
+CPocketPJDlg::CPocketPJDlg(CWnd* pParent /*=NULL*/)
+ : CDialog(CPocketPJDlg::IDD, pParent), m_PopUp(NULL)
+{
+ //{{AFX_DATA_INIT(CPocketPJDlg)
+ // NOTE: the ClassWizard will add member initialization here
+ //}}AFX_DATA_INIT
+ // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
+ m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
+
+ theDlg = this;
+
+ m_PopUp = new CPopUpWnd(this);
+ m_PopUp->Hide();
+
+ unsigned i;
+ m_PopUpCount = 0;
+ for (i=0; i<POPUP_MAX_TYPE; ++i) {
+ m_PopUpState[i] = FALSE;
+ }
+}
+
+void CPocketPJDlg::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CPocketPJDlg)
+ DDX_Control(pDX, IDC_URL, m_Url);
+ DDX_Control(pDX, IDC_BUDDY_LIST, m_BuddyList);
+ DDX_Control(pDX, IDC_BTN_ACTION, m_BtnUrlAction);
+ DDX_Control(pDX, IDC_BTN_ACC, m_BtnAcc);
+ DDX_Control(pDX, IDC_ACC_ID, m_AccId);
+ //}}AFX_DATA_MAP
+}
+
+BEGIN_MESSAGE_MAP(CPocketPJDlg, CDialog)
+ //{{AFX_MSG_MAP(CPocketPJDlg)
+ ON_BN_CLICKED(IDC_BTN_ACC, OnBtnAcc)
+ ON_BN_CLICKED(IDC_BTN_ACTION, OnBtnAction)
+ ON_COMMAND(IDC_ACC_SETTINGS, OnSettings)
+ ON_COMMAND(IDC_URI_CALL, OnUriCall)
+ ON_WM_TIMER()
+ ON_COMMAND(IDC_URI_ADD_BUDDY, OnUriAddBuddy)
+ ON_COMMAND(IDC_URI_DEL_BUDDY, OnUriDelBuddy)
+ ON_COMMAND(IDC_ACC_ONLINE, OnAccOnline)
+ ON_COMMAND(IDC_ACC_INVISIBLE, OnAccInvisible)
+ ON_NOTIFY(NM_CLICK, IDC_BUDDY_LIST, OnClickBuddyList)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+
+void CPocketPJDlg::Error(const CString &title, pj_status_t rc)
+{
+ char errmsg[PJ_ERR_MSG_SIZE];
+ wchar_t werrmsg[PJ_ERR_MSG_SIZE];
+
+ pj_strerror(rc, errmsg, sizeof(errmsg));
+ pj_ansi_to_unicode(errmsg, strlen(errmsg), werrmsg, PJ_ARRAY_SIZE(werrmsg));
+
+ AfxMessageBox(title + _T(": ") + werrmsg);
+}
+
+BOOL CPocketPJDlg::Restart()
+{
+ unsigned i;
+ pj_status_t status;
+
+ char ver[80];
+ sprintf(ver, "PocketPJ/%s", pj_get_version());
+
+ ShowWindow(SW_SHOW);
+ PopUp_Show(POPUP_REGISTRATION, ver,
+ "Starting up....", "", "", "", 0);
+
+ KillTimer(TIMER_ID);
+
+ // Destroy first.
+ PopUp_Modify(POPUP_REGISTRATION, POPUP_EL_TITLE3, "Cleaning up..");
+ pjsua_destroy();
+
+ m_BtnAcc.SetBitmap(::LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_OFFLINE)) );
+ UpdateWindow();
+
+
+ // Create
+ PopUp_Show(POPUP_REGISTRATION, ver,
+ "Starting up....", "Creating stack..", "", "", 0);
+
+ status = pjsua_create();
+ if (status != PJ_SUCCESS) {
+ Error(_T("Error in creating library"), status);
+ PopUp_Hide(POPUP_REGISTRATION);
+ return FALSE;
+ }
+
+ pjsua_config cfg;
+ pjsua_logging_config log_cfg;
+ pjsua_media_config media_cfg;
+
+ pjsua_config_default(&cfg);
+ cfg.max_calls = 1;
+ cfg.thread_cnt = 0;
+ cfg.user_agent = pj_str(ver);
+
+ cfg.cb.on_call_state = &on_call_state;
+ cfg.cb.on_call_media_state = &on_call_media_state;
+ cfg.cb.on_incoming_call = &on_incoming_call;
+ cfg.cb.on_reg_state = &on_reg_state;
+ cfg.cb.on_buddy_state = &on_buddy_state;
+ cfg.cb.on_pager = &on_pager;
+
+ /* Configure nameserver */
+ char nameserver[60];
+ {
+ FIXED_INFO fi;
+ PIP_ADDR_STRING pDNS = NULL;
+ ULONG len = sizeof(fi);
+ CString err;
+
+ PopUp_Modify(POPUP_REGISTRATION, POPUP_EL_TITLE3, "Retrieving network parameters..");
+ if (GetNetworkParams(&fi, &len) != ERROR_SUCCESS) {
+ err = _T("Info: Error querying network parameters. You must configure DNS server.");
+ } else if (fi.CurrentDnsServer) {
+ pDNS = fi.CurrentDnsServer;
+ } else if (fi.DnsServerList.IpAddress.String[0] != 0) {
+ pDNS = &fi.DnsServerList;
+ } else {
+ err = _T("Info: DNS server not configured. You must configure DNS server.");
+ }
+
+ if (err.GetLength()) {
+ if (m_Cfg.m_DNS.GetLength()) {
+ pj_unicode_to_ansi((LPCTSTR)m_Cfg.m_DNS, m_Cfg.m_DNS.GetLength(),
+ nameserver, sizeof(nameserver));
+ cfg.nameserver_count = 1;
+ cfg.nameserver[0] = pj_str(nameserver);
+ } else {
+ AfxMessageBox(err);
+ pjsua_destroy();
+ PopUp_Hide(POPUP_REGISTRATION);
+ return FALSE;
+ }
+ } else {
+ strcpy(nameserver, pDNS->IpAddress.String);
+ cfg.nameserver_count = 1;
+ cfg.nameserver[0] = pj_str(nameserver);
+ }
+ }
+
+ char tmp_stun[80];
+ if (m_Cfg.m_UseStun) {
+ pj_unicode_to_ansi((LPCTSTR)m_Cfg.m_StunSrv, m_Cfg.m_StunSrv.GetLength(),
+ tmp_stun, sizeof(tmp_stun));
+ cfg.stun_host = pj_str(tmp_stun);
+ }
+
+ pjsua_logging_config_default(&log_cfg);
+ log_cfg.msg_logging = PJ_TRUE;
+ log_cfg.log_filename = pj_str("\\PocketPJ.TXT");
+
+ pjsua_media_config_default(&media_cfg);
+ media_cfg.clock_rate = 8000;
+ media_cfg.audio_frame_ptime = 40;
+ media_cfg.ec_tail_len = 0;
+ media_cfg.ilbc_mode = 30;
+ media_cfg.max_media_ports = 8;
+ // use default quality setting
+ //media_cfg.quality = 5;
+ media_cfg.thread_cnt = 1;
+ media_cfg.enable_ice = m_Cfg.m_UseIce;
+ media_cfg.no_vad = !m_Cfg.m_VAD;
+
+ if (m_Cfg.m_EchoSuppress) {
+ media_cfg.ec_options = PJMEDIA_ECHO_SIMPLE;
+ media_cfg.ec_tail_len = m_Cfg.m_EcTail;
+ }
+
+ // Init
+ PopUp_Modify(POPUP_REGISTRATION, POPUP_EL_TITLE3, "Initializing..");
+ status = pjsua_init(&cfg, &log_cfg, &media_cfg);
+ if (status != PJ_SUCCESS) {
+ Error(_T("Error initializing library"), status);
+ pjsua_destroy();
+ PopUp_Hide(POPUP_REGISTRATION);
+ return FALSE;
+ }
+
+ // Create one UDP transport
+ PopUp_Modify(POPUP_REGISTRATION, POPUP_EL_TITLE3, "Adding UDP transport..");
+ pjsua_transport_id transport_id;
+ pjsua_transport_config udp_cfg;
+
+ pjsua_transport_config_default(&udp_cfg);
+ udp_cfg.port = 0;
+ status = pjsua_transport_create(PJSIP_TRANSPORT_UDP,
+ &udp_cfg, &transport_id);
+ if (status != PJ_SUCCESS) {
+ Error(_T("Error creating UDP transport"), status);
+ pjsua_destroy();
+ PopUp_Hide(POPUP_REGISTRATION);
+ return FALSE;
+ }
+
+ // Always instantiate TCP to support auto-switching to TCP when
+ // packet is larger than 1300 bytes. If TCP is disabled when
+ // no auto-switching will occur
+ if (1) {
+ // Create one TCP transport
+ PopUp_Modify(POPUP_REGISTRATION, POPUP_EL_TITLE3, "Adding TCP transport..");
+ pjsua_transport_id transport_id;
+ pjsua_transport_config tcp_cfg;
+
+ pjsua_transport_config_default(&tcp_cfg);
+ tcp_cfg.port = 0;
+ status = pjsua_transport_create(PJSIP_TRANSPORT_TCP,
+ &tcp_cfg, &transport_id);
+ if (status != PJ_SUCCESS) {
+ Error(_T("Error creating TCP transport"), status);
+ pjsua_destroy();
+ PopUp_Hide(POPUP_REGISTRATION);
+ return FALSE;
+ }
+ }
+
+ // Adjust codecs priority
+ pj_str_t tmp;
+ pjsua_codec_set_priority(pj_cstr(&tmp, "*"), 0);
+ for (i=0; i<(unsigned)m_Cfg.m_Codecs.GetSize(); ++i) {
+ CString codec = m_Cfg.m_Codecs.GetAt(i);
+ char tmp_nam[80];
+
+ pj_unicode_to_ansi((LPCTSTR)codec, codec.GetLength(),
+ tmp_nam, sizeof(tmp_nam));
+ pjsua_codec_set_priority(pj_cstr(&tmp, tmp_nam), (pj_uint8_t)(200-i));
+ }
+
+ // Start!
+ PopUp_Modify(POPUP_REGISTRATION, POPUP_EL_TITLE3, "Starting..");
+ status = pjsua_start();
+ if (status != PJ_SUCCESS) {
+ Error(_T("Error starting library"), status);
+ pjsua_destroy();
+ PopUp_Hide(POPUP_REGISTRATION);
+ return FALSE;
+ }
+
+ // Add account
+ PopUp_Modify(POPUP_REGISTRATION, POPUP_EL_TITLE3, "Adding account..");
+ char domain[80], username[80], passwd[80];
+ char id[80], reg_uri[80];
+ pjsua_acc_config acc_cfg;
+
+ pj_unicode_to_ansi((LPCTSTR)m_Cfg.m_Domain, m_Cfg.m_Domain.GetLength(),
+ domain, sizeof(domain));
+ pj_unicode_to_ansi((LPCTSTR)m_Cfg.m_User, m_Cfg.m_User.GetLength(),
+ username, sizeof(username));
+ pj_unicode_to_ansi((LPCTSTR)m_Cfg.m_Password, m_Cfg.m_Password.GetLength(),
+ passwd, sizeof(passwd));
+
+ snprintf(id, sizeof(id), "<sip:%s@%s>", username, domain);
+ snprintf(reg_uri, sizeof(reg_uri), "sip:%s", domain);
+
+ pjsua_acc_config_default(&acc_cfg);
+ acc_cfg.id = pj_str(id);
+ acc_cfg.reg_uri = pj_str(reg_uri);
+ acc_cfg.cred_count = 1;
+ acc_cfg.cred_info[0].scheme = pj_str("Digest");
+ acc_cfg.cred_info[0].realm = pj_str("*");
+ acc_cfg.cred_info[0].username = pj_str(username);
+ acc_cfg.cred_info[0].data_type = 0;
+ acc_cfg.cred_info[0].data = pj_str(passwd);
+
+#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
+ acc_cfg.use_srtp = (m_Cfg.m_UseSrtp ? PJMEDIA_SRTP_OPTIONAL : PJMEDIA_SRTP_DISABLED);
+ acc_cfg.srtp_secure_signaling = 0;
+#endif
+
+ acc_cfg.publish_enabled = m_Cfg.m_UsePublish;
+
+ char route[80];
+ if (m_Cfg.m_TCP) {
+ snprintf(route, sizeof(route), "<sip:%s;lr;transport=tcp>", domain);
+ acc_cfg.proxy[acc_cfg.proxy_cnt++] = pj_str(route);
+ } else {
+ snprintf(route, sizeof(route), "<sip:%s;lr>", domain);
+ acc_cfg.proxy[acc_cfg.proxy_cnt++] = pj_str(route);
+ }
+
+ status = pjsua_acc_add(&acc_cfg, PJ_TRUE, &m_PjsuaAccId);
+ if (status != PJ_SUCCESS) {
+ Error(_T("Invalid account settings"), status);
+ pjsua_destroy();
+ PopUp_Hide(POPUP_REGISTRATION);
+ return FALSE;
+ }
+
+ CString acc_text = m_Cfg.m_User + _T("@") + m_Cfg.m_Domain;
+ m_AccId.SetWindowText(acc_text);
+
+ PopUp_Modify(POPUP_REGISTRATION, POPUP_EL_TITLE1, acc_text);
+ PopUp_Modify(POPUP_REGISTRATION, POPUP_EL_TITLE2, "Registering..");
+ PopUp_Modify(POPUP_REGISTRATION, POPUP_EL_TITLE3, "");
+
+ SetTimer(TIMER_ID, 100, NULL);
+ return TRUE;
+}
+
+
+void CPocketPJDlg::PopUp_Show( PopUpType type,
+ const CString& title1,
+ const CString& title2,
+ const CString& title3,
+ const CString& btn1,
+ const CString& btn2,
+ unsigned userData)
+{
+ PJ_UNUSED_ARG(userData);
+
+ if (!m_PopUpState[type])
+ ++m_PopUpCount;
+
+ m_PopUpState[type] = TRUE;
+
+ m_PopUpContent[type].m_Title1 = title1;
+ m_PopUpContent[type].m_Title2 = title2;
+ m_PopUpContent[type].m_Title3 = title3;
+ m_PopUpContent[type].m_Btn1 = btn1;
+ m_PopUpContent[type].m_Btn2 = btn2;
+
+ m_PopUp->SetContent(m_PopUpContent[type]);
+ m_PopUp->Show();
+}
+
+void CPocketPJDlg::PopUp_Modify(PopUpType type,
+ PopUpElement el,
+ const CString& text)
+{
+ switch (el) {
+ case POPUP_EL_TITLE1:
+ m_PopUpContent[type].m_Title1 = text;
+ break;
+ case POPUP_EL_TITLE2:
+ m_PopUpContent[type].m_Title2 = text;
+ break;
+ case POPUP_EL_TITLE3:
+ m_PopUpContent[type].m_Title3 = text;
+ break;
+ case POPUP_EL_BUTTON1:
+ m_PopUpContent[type].m_Btn1 = text;
+ break;
+ case POPUP_EL_BUTTON2:
+ m_PopUpContent[type].m_Btn1 = text;
+ break;
+ }
+
+ m_PopUp->SetContent(m_PopUpContent[type]);
+}
+
+void CPocketPJDlg::PopUp_Hide(PopUpType type)
+{
+ if (m_PopUpState[type])
+ --m_PopUpCount;
+
+ m_PopUpState[type] = FALSE;
+
+ if (m_PopUpCount == 0) {
+ m_PopUp->Hide();
+ UpdateWindow();
+ } else {
+ for (int i=POPUP_MAX_TYPE-1; i>=0; --i) {
+ if (m_PopUpState[i]) {
+ m_PopUp->SetContent(m_PopUpContent[i]);
+ break;
+ }
+ }
+ }
+}
+
+void CPocketPJDlg::OnIncomingCall()
+{
+ pjsua_call_info ci;
+
+ pjsua_call_get_info(0, &ci);
+
+ PopUp_Show(POPUP_CALL, "Incoming call..", ci.remote_info.ptr, "",
+ "Answer", "Hangup", 0);
+ pjsua_call_answer(0, 180, NULL, NULL);
+ if (m_Cfg.m_AutoAnswer)
+ OnPopUpButton(1);
+}
+
+void CPocketPJDlg::OnCallState()
+{
+ pjsua_call_info ci;
+
+ pjsua_call_get_info(0, &ci);
+
+ switch (ci.state) {
+ case PJSIP_INV_STATE_NULL: /**< Before INVITE is sent or received */
+ break;
+ case PJSIP_INV_STATE_CALLING: /**< After INVITE is sent */
+ PopUp_Show(POPUP_CALL, "Calling..", ci.remote_info.ptr, "",
+ "", "Hangup", 0);
+ break;
+ case PJSIP_INV_STATE_INCOMING: /**< After INVITE is received. */
+ OnIncomingCall();
+ break;
+ case PJSIP_INV_STATE_EARLY: /**< After response with To tag. */
+ case PJSIP_INV_STATE_CONNECTING:/**< After 2xx is sent/received. */
+ case PJSIP_INV_STATE_CONFIRMED: /**< After ACK is sent/received. */
+ {
+ CString stateText = ci.state_text.ptr;
+ PopUp_Modify(POPUP_CALL, POPUP_EL_TITLE3, stateText);
+ }
+ break;
+ case PJSIP_INV_STATE_DISCONNECTED:/**< Session is terminated. */
+ PopUp_Modify(POPUP_CALL, POPUP_EL_TITLE3, "Disconnected");
+ PopUp_Hide(POPUP_CALL);
+ break;
+ }
+}
+
+void CPocketPJDlg::on_call_state(pjsua_call_id call_id, pjsip_event *e)
+{
+ PJ_UNUSED_ARG(e);
+ PJ_UNUSED_ARG(call_id);
+
+ theDlg->OnCallState();
+}
+
+void CPocketPJDlg::on_call_media_state(pjsua_call_id call_id)
+{
+ pjsua_call_info call_info;
+
+ pjsua_call_get_info(call_id, &call_info);
+ if (call_info.media_status == PJSUA_CALL_MEDIA_ACTIVE) {
+ pjsua_conf_connect(call_info.conf_slot, 0);
+ pjsua_conf_connect(0, call_info.conf_slot);
+ }
+}
+
+void CPocketPJDlg::on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id,
+ pjsip_rx_data *rdata)
+{
+ PJ_UNUSED_ARG(acc_id);
+ PJ_UNUSED_ARG(call_id);
+ PJ_UNUSED_ARG(rdata);
+
+ theDlg->OnIncomingCall();
+}
+
+void CPocketPJDlg::OnRegState()
+{
+ pjsua_acc_info ai;
+ pjsua_acc_get_info(m_PjsuaAccId, &ai);
+
+ CString acc_text = m_Cfg.m_User + _T("@") + m_Cfg.m_Domain;
+
+ if (ai.expires>0 && ai.status/100==2) {
+ /* Registration success */
+ HBITMAP old = m_BtnAcc.SetBitmap(::LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_ONLINE)) );
+ PJ_UNUSED_ARG(old);
+ acc_text += " (OK)";
+ m_AccId.SetWindowText(acc_text);
+ } else if (ai.status/100 != 2) {
+ acc_text += " (err)";
+ Error(_T("SIP registration error"), PJSIP_ERRNO_FROM_SIP_STATUS(ai.status));
+ m_AccId.SetWindowText(acc_text);
+ }
+ PopUp_Hide(POPUP_REGISTRATION);
+}
+
+void CPocketPJDlg::on_reg_state(pjsua_acc_id acc_id)
+{
+ PJ_UNUSED_ARG(acc_id);
+
+ theDlg->OnRegState();
+}
+
+void CPocketPJDlg::on_buddy_state(pjsua_buddy_id buddy_id)
+{
+ PJ_UNUSED_ARG(buddy_id);
+
+ theDlg->RedrawBuddyList();
+}
+
+void CPocketPJDlg::on_pager(pjsua_call_id call_id, const pj_str_t *from,
+ const pj_str_t *to, const pj_str_t *contact,
+ const pj_str_t *mime_type, const pj_str_t *text)
+{
+ PJ_UNUSED_ARG(call_id);
+ PJ_UNUSED_ARG(from);
+ PJ_UNUSED_ARG(to);
+ PJ_UNUSED_ARG(contact);
+ PJ_UNUSED_ARG(mime_type);
+ PJ_UNUSED_ARG(text);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CPocketPJDlg message handlers
+
+BOOL CPocketPJDlg::OnInitDialog()
+{
+ CDialog::OnInitDialog();
+
+ // Set the icon for this dialog. The framework does this automatically
+ // when the application's main window is not a dialog
+ SetIcon(m_hIcon, TRUE); // Set big icon
+ SetIcon(m_hIcon, FALSE); // Set small icon
+
+ CenterWindow(GetDesktopWindow()); // center to the hpc screen
+
+ // TODO: Add extra initialization here
+
+ m_Cfg.LoadRegistry();
+ //ShowWindow(SW_SHOW);
+ m_AccId.SetWindowText(m_Cfg.m_User);
+
+ CImageList *il = new CImageList;
+ VERIFY(il->Create(16, 16, ILC_COLOR|ILC_MASK, 2, 4));
+
+ CBitmap *bmp = new CBitmap;
+ bmp->LoadBitmap(MAKEINTRESOURCE(IDB_BLANK));
+ il->Add(bmp, RGB(255,255,255));
+ bmp = new CBitmap;
+ bmp->LoadBitmap(MAKEINTRESOURCE(IDB_ONLINE));
+ il->Add(bmp, RGB(255,255,255));
+
+ m_BuddyList.SetImageList(il, LVSIL_SMALL);
+
+ if (m_Cfg.m_Domain.GetLength()==0 || Restart() == FALSE) {
+ for (;;) {
+ CSettingsDlg dlg(m_Cfg);
+ if (dlg.DoModal() != IDOK) {
+ EndDialog(IDOK);
+ return TRUE;
+ }
+
+ m_Cfg.SaveRegistry();
+
+ if (Restart())
+ break;
+ }
+ }
+
+ RedrawBuddyList();
+ return TRUE; // return TRUE unless you set the focus to a control
+}
+
+
+
+void CPocketPJDlg::OnBtnAcc()
+{
+ CMenu menu;
+ VERIFY(menu.LoadMenu(IDR_ACC_MENU));
+ CMenu* pPopup = menu.GetSubMenu(0);
+ ASSERT(pPopup != NULL);
+
+ RECT r;
+ m_BtnAcc.GetWindowRect(&r);
+ pPopup->TrackPopupMenu(TPM_LEFTALIGN, r.left+4, r.top+4, this);
+}
+
+void CPocketPJDlg::OnBtnAction()
+{
+ CMenu menu;
+ VERIFY(menu.LoadMenu(IDR_URI_MENU));
+ CMenu* pPopup = menu.GetSubMenu(0);
+ ASSERT(pPopup != NULL);
+
+ RECT r;
+ this->m_BtnUrlAction.GetWindowRect(&r);
+ pPopup->TrackPopupMenu(TPM_LEFTALIGN, r.left+4, r.top+4, this);
+}
+
+void CPocketPJDlg::OnSettings()
+{
+ for (;;) {
+ CSettingsDlg dlg(m_Cfg);
+ if (dlg.DoModal() != IDOK) {
+ return;
+ }
+
+ m_Cfg.SaveRegistry();
+
+ if (Restart())
+ break;
+ }
+}
+
+void CPocketPJDlg::OnOK()
+{
+ if (AfxMessageBox(_T("Quit PocketPJ?"), MB_YESNO)==IDYES) {
+ KillTimer(TIMER_ID);
+ PopUp_Show(POPUP_REGISTRATION, "", "Shutting down..", "", "", "", 0);
+ pjsua_destroy();
+ CDialog::OnOK();
+ PopUp_Hide(POPUP_REGISTRATION);
+ m_Cfg.SaveRegistry();
+ return;
+ }
+}
+
+void CPocketPJDlg::OnTimer(UINT nIDEvent)
+{
+ pjsua_handle_events(10);
+ CDialog::OnTimer(nIDEvent);
+}
+
+int CPocketPJDlg::FindBuddyInPjsua(const CString &Uri)
+{
+ char uri[80];
+ pjsua_buddy_id id[128];
+ unsigned i, count = PJ_ARRAY_SIZE(id);
+
+ if (pjsua_enum_buddies(id, &count) != PJ_SUCCESS)
+ return PJSUA_INVALID_ID;
+ if (count==0)
+ return PJSUA_INVALID_ID;
+
+ pj_unicode_to_ansi((LPCTSTR)Uri, Uri.GetLength(), uri, sizeof(uri));
+
+ for (i=0; i<count; ++i) {
+ pjsua_buddy_info bi;
+ pjsua_buddy_get_info(id[i], &bi);
+ if (pj_strcmp2(&bi.uri, uri)==0)
+ return i;
+ }
+
+ return PJSUA_INVALID_ID;
+}
+
+int CPocketPJDlg::FindBuddyInCfg(const CString &uri)
+{
+ int i;
+ for (i=0; i<m_Cfg.m_BuddyList.GetSize(); ++i) {
+ if (m_Cfg.m_BuddyList.GetAt(0) == uri) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+void CPocketPJDlg::RedrawBuddyList()
+{
+ int i;
+
+ m_BuddyList.DeleteAllItems();
+
+ for (i=0; i<m_Cfg.m_BuddyList.GetSize(); ++i) {
+ int isOnline;
+ int id;
+
+ id = FindBuddyInPjsua(m_Cfg.m_BuddyList.GetAt(i));
+ if (id != PJSUA_INVALID_ID) {
+ pjsua_buddy_info bi;
+ pjsua_buddy_get_info(id, &bi);
+ isOnline = (bi.status == PJSUA_BUDDY_STATUS_ONLINE);
+ } else {
+ isOnline = 0;
+ }
+
+ LVITEM lvi;
+ memset(&lvi, 0, sizeof(lvi));
+ lvi.mask = LVIF_TEXT | LVIF_IMAGE;
+ lvi.iItem = i;
+ lvi.iImage = isOnline;
+ lvi.pszText = (LPTSTR)(LPCTSTR)m_Cfg.m_BuddyList.GetAt(i);
+
+ m_BuddyList.InsertItem(&lvi);
+ }
+}
+
+void CPocketPJDlg::OnUriCall()
+{
+ char tmp[120];
+ CString uri;
+ pj_status_t status;
+
+ m_Url.GetWindowText(uri);
+ pj_unicode_to_ansi((LPCTSTR)uri, uri.GetLength(), tmp, sizeof(tmp));
+ if ((status=pjsua_verify_sip_url(tmp)) != PJ_SUCCESS) {
+ Error("The URL is not valid SIP URL", status);
+ return;
+ }
+
+ pj_str_t dest_uri = pj_str(tmp);
+ pjsua_call_id call_id;
+
+ status = pjsua_call_make_call(m_PjsuaAccId, &dest_uri, 0, NULL, NULL, &call_id);
+
+ if (status != PJ_SUCCESS)
+ Error("Unable to make call", status);
+}
+
+void CPocketPJDlg::OnUriAddBuddy()
+{
+ int i;
+ char tmp[120];
+ CString uri;
+ pj_status_t status;
+
+ m_Url.GetWindowText(uri);
+ pj_unicode_to_ansi((LPCTSTR)uri, uri.GetLength(), tmp, sizeof(tmp));
+ if ((status=pjsua_verify_sip_url(tmp)) != PJ_SUCCESS) {
+ Error("The URL is not valid SIP URL", status);
+ return;
+ }
+
+ for (i=0; i<m_Cfg.m_BuddyList.GetSize(); ++i) {
+ if (m_Cfg.m_BuddyList.GetAt(0) == uri) {
+ AfxMessageBox(_T("The URI is already in the buddy list"));
+ return;
+ }
+ }
+
+ m_Cfg.m_BuddyList.Add(uri);
+ RedrawBuddyList();
+}
+
+void CPocketPJDlg::OnUriDelBuddy()
+{
+ CString uri;
+
+ m_Url.GetWindowText(uri);
+ int i = FindBuddyInCfg(uri);
+ if (i<0) {
+ /* Buddy not found */
+ return;
+ }
+
+ m_Cfg.m_BuddyList.RemoveAt(i);
+ RedrawBuddyList();
+ AfxMessageBox(_T("Buddy " + uri + " deleted"));
+}
+
+void CPocketPJDlg::OnAccOnline()
+{
+ pjsua_acc_set_online_status(m_PjsuaAccId, PJ_TRUE);
+ m_BtnAcc.SetBitmap(::LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_ONLINE)) );
+}
+
+void CPocketPJDlg::OnAccInvisible()
+{
+ pjsua_acc_set_online_status(m_PjsuaAccId, PJ_FALSE);
+ m_BtnAcc.SetBitmap(::LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_INVISIBLE)) );
+}
+
+void CPocketPJDlg::OnPopUpButton(int btnNo)
+{
+ if (btnNo == 1) {
+ pjsua_call_answer(0, 200, NULL, 0);
+ PopUp_Modify(POPUP_CALL, POPUP_EL_BUTTON1, "");
+ } else if (btnNo == 2) {
+ // Hangup button
+ PopUp_Modify(POPUP_CALL, POPUP_EL_TITLE2, "Hang up..");
+ PopUp_Modify(POPUP_CALL, POPUP_EL_TITLE3, "");
+ pjsua_call_hangup(0, PJSIP_SC_DECLINE, 0, 0);
+ }
+}
+
+void CPocketPJDlg::OnClickBuddyList(NMHDR* pNMHDR, LRESULT* pResult)
+{
+ POSITION pos = m_BuddyList.GetFirstSelectedItemPosition();
+
+ PJ_UNUSED_ARG(pNMHDR);
+
+ if (pos != NULL) {
+ int iItem = m_BuddyList.GetNextSelectedItem(pos);
+ CString uri = m_BuddyList.GetItemText(iItem, 0);
+ m_Url.SetWindowText(uri);
+ }
+ *pResult = 0;
+}
diff --git a/pjsip-apps/src/pocketpj/PocketPJDlg.h b/pjsip-apps/src/pocketpj/PocketPJDlg.h
new file mode 100644
index 0000000..2b3eb97
--- /dev/null
+++ b/pjsip-apps/src/pocketpj/PocketPJDlg.h
@@ -0,0 +1,129 @@
+// PocketPJDlg.h : header file
+//
+
+#if !defined(AFX_POCKETPJDLG_H__DF5F90C9_E72B_4557_9126_AFE75A3ADE9D__INCLUDED_)
+#define AFX_POCKETPJDLG_H__DF5F90C9_E72B_4557_9126_AFE75A3ADE9D__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+#include "SettingsDlg.h"
+#include "PopUpWnd.h"
+#include <pjsua-lib/pjsua.h>
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CPocketPJDlg dialog
+
+class CPocketPJDlg : public CDialog
+{
+// Construction
+public:
+ CPocketPJDlg(CWnd* pParent = NULL); // standard constructor
+
+ void OnPopUpButton(int btnNo);
+ void OnIncomingCall();
+
+// Dialog Data
+ //{{AFX_DATA(CPocketPJDlg)
+ enum { IDD = IDD_POCKETPJ_DIALOG };
+ CEdit m_Url;
+ CListCtrl m_BuddyList;
+ CStatic m_BtnUrlAction;
+ CStatic m_BtnAcc;
+ CStatic m_AccId;
+ //}}AFX_DATA
+
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CPocketPJDlg)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+
+// Implementation
+protected:
+ HICON m_hIcon;
+
+ // Generated message map functions
+ //{{AFX_MSG(CPocketPJDlg)
+ virtual BOOL OnInitDialog();
+ afx_msg void OnBtnAcc();
+ afx_msg void OnBtnAction();
+ afx_msg void OnSettings();
+ afx_msg void OnUriCall();
+ afx_msg void OnTimer(UINT nIDEvent);
+ afx_msg void OnUriAddBuddy();
+ afx_msg void OnUriDelBuddy();
+ afx_msg void OnAccOnline();
+ afx_msg void OnAccInvisible();
+ afx_msg void OnClickBuddyList(NMHDR* pNMHDR, LRESULT* pResult);
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+
+private:
+ enum PopUpType
+ {
+ POPUP_REGISTRATION,
+ POPUP_CALL,
+
+ POPUP_MAX_TYPE
+ };
+ enum PopUpElement
+ {
+ POPUP_EL_TITLE1,
+ POPUP_EL_TITLE2,
+ POPUP_EL_TITLE3,
+ POPUP_EL_BUTTON1,
+ POPUP_EL_BUTTON2,
+ };
+ CPopUpWnd *m_PopUp;
+ int m_PopUpCount;
+ BOOL m_PopUpState[POPUP_MAX_TYPE];
+ CPopUpContent m_PopUpContent[POPUP_MAX_TYPE];
+
+ void PopUp_Show(PopUpType type,
+ const CString& title1,
+ const CString& title2,
+ const CString& title3,
+ const CString& btn1,
+ const CString& btn2,
+ unsigned userData);
+ void PopUp_Modify(PopUpType type,
+ PopUpElement el,
+ const CString& text);
+ void PopUp_Hide(PopUpType type);
+
+private:
+ CPocketPJSettings m_Cfg;
+
+ void Error(const CString &title, pj_status_t rc);
+ BOOL Restart();
+ void OnOK();
+ int FindBuddyInCfg(const CString &uri);
+ int FindBuddyInPjsua(const CString &uri);
+ void RedrawBuddyList();
+
+private:
+ pjsua_acc_id m_PjsuaAccId;
+
+ void OnRegState();
+ void OnCallState();
+
+ // pjsua callbacks
+ static void on_call_state(pjsua_call_id call_id, pjsip_event *e);
+ static void on_call_media_state(pjsua_call_id call_id);
+ static void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id,
+ pjsip_rx_data *rdata);
+ static void on_reg_state(pjsua_acc_id acc_id);
+ static void on_buddy_state(pjsua_buddy_id buddy_id);
+ static void on_pager(pjsua_call_id call_id, const pj_str_t *from,
+ const pj_str_t *to, const pj_str_t *contact,
+ const pj_str_t *mime_type, const pj_str_t *text);
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft eMbedded Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_POCKETPJDLG_H__DF5F90C9_E72B_4557_9126_AFE75A3ADE9D__INCLUDED_)
diff --git a/pjsip-apps/src/pocketpj/PopUpWnd.cpp b/pjsip-apps/src/pocketpj/PopUpWnd.cpp
new file mode 100644
index 0000000..1f1654f
--- /dev/null
+++ b/pjsip-apps/src/pocketpj/PopUpWnd.cpp
@@ -0,0 +1,235 @@
+#include "stdafx.h"
+#include "PopUpWnd.h"
+#include "resource.h"
+#include "PocketPJDlg.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+#define IDC_BTN1 10
+#define IDC_BTN2 11
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CPopUpWnd
+
+CPopUpWnd::CPopUpWnd(CPocketPJDlg* pParent)
+{
+ Create(pParent);
+}
+
+CPopUpWnd::~CPopUpWnd()
+{
+ DestroyWindow();
+}
+
+BOOL CPopUpWnd::Create(CPocketPJDlg* pParent)
+{
+ BOOL bSuccess;
+
+ m_ParentWnd = pParent;
+
+ // Register window class
+ CString csClassName = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW,
+ 0,
+ CBrush(::GetSysColor(COLOR_BTNFACE)));
+
+ // Create popup window
+ bSuccess = CreateEx(WS_EX_DLGMODALFRAME|WS_EX_TOPMOST, // Extended style
+ csClassName, // Classname
+ _T("PocketPJ"), // Title
+ WS_POPUP|WS_BORDER|WS_CAPTION, // style
+ 0,0, // position - updated soon.
+ 1,1, // Size - updated soon
+ pParent->GetSafeHwnd(), // handle to parent
+ 0, // No menu
+ NULL);
+ if (!bSuccess)
+ return FALSE;
+
+ ShowWindow(SW_HIDE);
+
+ // Now create the controls
+ CRect TempRect(0,0,10,10);
+
+ /* |SS_LEFTNOWORDWRAP */
+ bSuccess = m_Title1.Create(_T("Title1"), WS_CHILD|WS_VISIBLE|SS_NOPREFIX,
+ TempRect, this, IDC_TITLE1);
+ if (!bSuccess)
+ return FALSE;
+
+ bSuccess = m_Title2.Create(_T("Title2"), WS_CHILD|WS_VISIBLE|SS_NOPREFIX,
+ TempRect, this, IDC_TITLE2);
+ if (!bSuccess)
+ return FALSE;
+
+ bSuccess = m_Title3.Create(_T("Title3"), WS_CHILD|WS_VISIBLE|SS_NOPREFIX,
+ TempRect, this, IDC_TITLE3);
+ if (!bSuccess)
+ return FALSE;
+
+ bSuccess = m_Btn1.Create(_T("Button1"),
+ WS_CHILD|WS_VISIBLE|WS_TABSTOP| BS_PUSHBUTTON,
+ TempRect, this, IDC_BTN1);
+ if (!bSuccess)
+ return FALSE;
+
+ bSuccess = m_Btn2.Create(_T("Button2"),
+ WS_CHILD|WS_VISIBLE|WS_TABSTOP| BS_PUSHBUTTON,
+ TempRect, this, IDC_BTN2);
+ if (!bSuccess)
+ return FALSE;
+
+ CFont *ft1 = new CFont,
+ *ft2 = new CFont,
+ *ft3 = new CFont;
+
+
+ LOGFONT lf;
+ memset(&lf, 0, sizeof(LOGFONT));
+ lf.lfHeight = 12;
+ lstrcpy(lf.lfFaceName, _T("Arial"));
+ VERIFY(ft1->CreateFontIndirect(&lf));
+ VERIFY(ft3->CreateFontIndirect(&lf));
+
+ lf.lfHeight = 20;
+ VERIFY(ft2->CreateFontIndirect(&lf));
+
+ m_Title1.SetFont(ft1, TRUE);
+ m_Title2.SetFont(ft2, TRUE);
+ m_Title3.SetFont(ft3, TRUE);
+
+
+ SetWindowSize();
+
+ // Center and show window
+ CenterWindow();
+
+ Show();
+
+ return TRUE;
+}
+
+void CPopUpWnd::SetContent(const CPopUpContent &content)
+{
+ m_Title1.SetWindowText(content.m_Title1);
+ m_Title2.SetWindowText(content.m_Title2);
+ m_Title3.SetWindowText(content.m_Title3);
+
+ if (content.m_Btn1 != "") {
+ m_Btn1.SetWindowText(content.m_Btn1);
+ m_Btn1.ShowWindow(SW_SHOW);
+ } else {
+ m_Btn1.ShowWindow(SW_HIDE);
+ }
+
+ if (content.m_Btn2 != "") {
+ m_Btn2.SetWindowText(content.m_Btn2);
+ m_Btn2.ShowWindow(SW_SHOW);
+ } else {
+ m_Btn2.ShowWindow(SW_HIDE);
+ }
+
+ UpdateWindow();
+ ShowWindow(SW_SHOW);
+}
+
+void CPopUpWnd::SetWindowSize(int width, int height)
+{
+ enum { H1 = 16, H2 = 40, H3 = 16, S = 5, G = 10, BW=60, BH=20, BG=40};
+
+ CRect rootRect(0, 0, 320, 240);
+ int Y;
+
+ MoveWindow((rootRect.Width() - width)/2, (rootRect.Height() - height)/2,
+ width, height);
+
+ m_Title1.MoveWindow(10, Y=S, width-20, H1);
+ m_Title2.MoveWindow(10, Y+=H1+G, width-20, H2);
+ m_Title3.MoveWindow(10, Y+=H2+G, width-20, H3);
+
+ m_Btn1.MoveWindow((width-2*BW-BG)/2, Y+=H3+G, BW, BH);
+ m_Btn2.MoveWindow((width-2*BW-BG)/2+BW+BG, Y, BW, BH);
+}
+
+void CPopUpWnd::Hide()
+{
+ if (!::IsWindow(GetSafeHwnd()))
+ return;
+
+ if (IsWindowVisible())
+ {
+ ShowWindow(SW_HIDE);
+ ModifyStyle(WS_VISIBLE, 0);
+ }
+}
+
+void CPopUpWnd::Show()
+{
+ if (!::IsWindow(GetSafeHwnd()))
+ return;
+
+ ModifyStyle(0, WS_VISIBLE);
+ ShowWindow(SW_SHOWNA);
+ RedrawWindow(NULL,NULL,RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
+}
+
+BEGIN_MESSAGE_MAP(CPopUpWnd, CWnd)
+ //{{AFX_MSG_MAP(CPopUpWnd)
+ ON_WM_ERASEBKGND()
+ //}}AFX_MSG_MAP
+ ON_BN_CLICKED(IDC_BTN1, OnCancel1)
+ ON_BN_CLICKED(IDC_BTN2, OnCancel2)
+END_MESSAGE_MAP()
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CPopUpWnd message handlers
+
+BOOL CPopUpWnd::OnEraseBkgnd(CDC* pDC)
+{
+ CBrush backBrush;
+ backBrush.CreateSolidBrush(RGB(255,255,255));
+ CBrush* pOldBrush = pDC->SelectObject(&backBrush);
+
+ CRect rect;
+ pDC->GetClipBox(&rect); // Erase the area needed
+ pDC->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATCOPY);
+ pDC->SelectObject(pOldBrush);
+
+ return TRUE;
+}
+
+void CPopUpWnd::OnCancel1()
+{
+ m_ParentWnd->OnPopUpButton(1);
+}
+
+
+void CPopUpWnd::OnCancel2()
+{
+ m_ParentWnd->OnPopUpButton(2);
+}
+
+
+BOOL CPopUpWnd::DestroyWindow()
+{
+ return CWnd::DestroyWindow();
+}
+
+void CPopUpWnd::PeekAndPump()
+{
+ MSG msg;
+ while (::PeekMessage(&msg, NULL,0,0,PM_NOREMOVE))
+ {
+ if (!AfxGetApp()->PumpMessage())
+ {
+ ::PostQuitMessage(0);
+ return;
+ }
+ }
+}
+
diff --git a/pjsip-apps/src/pocketpj/PopUpWnd.h b/pjsip-apps/src/pocketpj/PopUpWnd.h
new file mode 100644
index 0000000..55c4a24
--- /dev/null
+++ b/pjsip-apps/src/pocketpj/PopUpWnd.h
@@ -0,0 +1,67 @@
+#ifndef __POPUP_WND_H__
+#define __POPUP_WND_H__
+
+
+class CPocketPJDlg;
+
+/////////////////////////////////////////////////////////////////////////////
+struct CPopUpContent
+{
+ CString m_Title1;
+ CString m_Title2;
+ CString m_Title3;
+ CString m_Btn1;
+ CString m_Btn2;
+};
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CPopUpWnd window
+
+class CPopUpWnd : public CWnd
+{
+public:
+ CPopUpWnd(CPocketPJDlg* pParent);
+ virtual ~CPopUpWnd();
+
+ void SetContent(const CPopUpContent &content);
+ void Hide();
+ void Show();
+
+ void SetWindowSize(int nWindowWidth = 200, int nWindowHeight = 180);
+
+ void PeekAndPump();
+
+// Implementation
+protected:
+ CPocketPJDlg * m_ParentWnd;
+
+ CStatic m_Title1;
+ CStatic m_Title2;
+ CStatic m_Title3;
+ CButton m_Btn1;
+ CButton m_Btn2;
+
+ BOOL Create(CPocketPJDlg* pParent);
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CPopUpWnd)
+ public:
+ virtual BOOL DestroyWindow();
+ //}}AFX_VIRTUAL
+
+// Generated message map functions
+protected:
+ //{{AFX_MSG(CPopUpWnd)
+ afx_msg BOOL OnEraseBkgnd(CDC* pDC);
+ //}}AFX_MSG
+ afx_msg void OnCancel1();
+ afx_msg void OnCancel2();
+ DECLARE_MESSAGE_MAP()
+};
+
+
+#endif
+/////////////////////////////////////////////////////////////////////////////
+
diff --git a/pjsip-apps/src/pocketpj/ReadMe.txt b/pjsip-apps/src/pocketpj/ReadMe.txt
new file mode 100644
index 0000000..a52cd9d
--- /dev/null
+++ b/pjsip-apps/src/pocketpj/ReadMe.txt
@@ -0,0 +1,81 @@
+========================================================================
+ Microsoft Foundation Class Library for Windows CE: PocketPJ
+========================================================================
+
+
+AppWizard has created this PocketPJ application for you. This application
+not only demonstrates the basics of using the Microsoft Foundation classes
+but is also a starting point for writing your application.
+
+This file contains a summary of what you will find in each of the files that
+make up your PocketPJ application.
+
+PocketPJ.h
+ This is the main header file for the application. It includes other
+ project specific headers (including Resource.h) and declares the
+ CPocketPJApp application class.
+
+PocketPJ.cpp
+ This is the main application source file that contains the application
+ class CPocketPJApp.
+
+PocketPJ.rc
+ This is a listing of all of the Microsoft Windows CE resources that the
+ program uses. It includes the icons, bitmaps, and cursors that are stored
+ in the RES subdirectory. This file can be directly edited in Microsoft
+ eMbedded Visual C++.
+
+res\PocketPJ.ico
+ This is an icon file, which is used as the application's icon. This
+ icon is included by the main resource file PocketPJ.rc.
+
+res\PocketPJ.rc2
+ This file contains resources that are not edited by Microsoft
+ eMbedded Visual C++. You should place all resources not
+ editable by the resource editor in this file.
+
+PocketPJ.vcc
+ This file contains information used by ClassWizard to edit existing
+ classes or add new classes. ClassWizard also uses this file to store
+ information needed to create and edit message maps and dialog data
+ maps and to create prototype member functions.
+
+/////////////////////////////////////////////////////////////////////////////
+
+AppWizard creates one dialog class:
+
+PocketPJDlg.h, PocketPJDlg.cpp - the dialog
+ These files contain your CPocketPJDlg class. This class defines
+ the behavior of your application's main dialog. The dialog's
+ template is in PocketPJ.rc, which can be edited in Microsoft
+ Developer Studio.
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+Other standard files:
+
+StdAfx.h, StdAfx.cpp
+ These files are used to build a precompiled header (PCH) file
+ named PocketPJ.pch and a precompiled types file named StdAfx.obj.
+
+Resource.h
+ This is the standard header file, which defines new resource IDs.
+ Microsoft eMbedded Visual C++ reads and updates this file.
+
+/////////////////////////////////////////////////////////////////////////////
+Other notes:
+
+AppWizard uses "TODO:" to indicate parts of the source code you
+should add to or customize.
+
+If your application uses MFC in a shared DLL, and your application is
+in a language other than the operating system's current language, you
+will need to copy the corresponding localized resources MFCWCXXX.DLL from
+the Microsoft eMbedded Visual C++ CD-ROM onto the system or system32 directory,
+and rename it to be MFCLOC.DLL. ("XXX" stands for the language abbreviation.
+For example, MFCWCDEU.DLL contains resources translated to German.) If you
+don't do this, some of the UI elements of your application will remain in the
+language of the operating system.
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/pjsip-apps/src/pocketpj/SettingsDlg.cpp b/pjsip-apps/src/pocketpj/SettingsDlg.cpp
new file mode 100644
index 0000000..1357044
--- /dev/null
+++ b/pjsip-apps/src/pocketpj/SettingsDlg.cpp
@@ -0,0 +1,376 @@
+// SettingsDlg.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "PocketPJ.h"
+#include "SettingsDlg.h"
+#include <pjsua-lib/pjsua.h>
+#include <atlbase.h>
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+#define REG_PATH _T("pjsip.org\\PocketPC")
+#define REG_DOMAIN _T("Domain")
+#define REG_USER _T("User")
+#define REG_PASSWD _T("Data")
+#define REG_USE_STUN _T("UseSTUN")
+#define REG_STUN_SRV _T("STUNSrv")
+#define REG_DNS _T("DNS")
+#define REG_USE_ICE _T("UseICE")
+#define REG_USE_SRTP _T("UseSRTP")
+#define REG_USE_PUBLISH _T("UsePUBLISH")
+#define REG_BUDDY_CNT _T("BuddyCnt")
+#define REG_BUDDY_X _T("Buddy%u")
+#define REG_ENABLE_EC _T("EnableEC")
+#define REG_EC_TAIL _T("ECTail")
+#define REG_ENABLE_VAD _T("EnableVAD")
+#define REG_ENABLE_TCP _T("EnableTCP")
+#define REG_CODEC_CNT _T("CodecCnt")
+#define REG_CODEC_X _T("Codec%u")
+#define REG_AUTO_ANSWER _T("AutoAnswer")
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Settings
+CPocketPJSettings::CPocketPJSettings()
+: m_UseStun(FALSE), m_UseIce(FALSE), m_UseSrtp(FALSE), m_UsePublish(FALSE),
+ m_EchoSuppress(TRUE), m_EcTail(200), m_TCP(FALSE), m_VAD(FALSE),
+ m_AutoAnswer(FALSE)
+{
+ /* Init codec list */
+#if defined(PJMEDIA_HAS_GSM_CODEC) && PJMEDIA_HAS_GSM_CODEC
+ m_Codecs.Add(_T("GSM"));
+#endif
+#if defined(PJMEDIA_HAS_G711_CODEC) && PJMEDIA_HAS_G711_CODEC
+ m_Codecs.Add(_T("PCMU"));
+ m_Codecs.Add(_T("PCMA"));
+#endif
+#if defined(PJMEDIA_HAS_SPEEX_CODEC) && PJMEDIA_HAS_SPEEX_CODEC
+ m_Codecs.Add(_T("Speex"));
+#endif
+}
+
+// Load from registry
+void CPocketPJSettings::LoadRegistry()
+{
+ CRegKey key;
+ wchar_t textVal[256];
+ DWORD dwordVal;
+ DWORD cbData;
+
+
+ if (key.Open(HKEY_CURRENT_USER, REG_PATH) != ERROR_SUCCESS)
+ return;
+
+ cbData = sizeof(textVal);
+ if (key.QueryValue(textVal, REG_DOMAIN, &cbData) == ERROR_SUCCESS) {
+ m_Domain = textVal;
+ }
+
+ cbData = sizeof(textVal);
+ if (key.QueryValue(textVal, REG_USER, &cbData) == ERROR_SUCCESS) {
+ m_User = textVal;
+ }
+
+ cbData = sizeof(textVal);
+ if (key.QueryValue(textVal, REG_PASSWD, &cbData) == ERROR_SUCCESS) {
+ m_Password = textVal;
+ }
+
+ cbData = sizeof(textVal);
+ if (key.QueryValue(textVal, REG_STUN_SRV, &cbData) == ERROR_SUCCESS) {
+ m_StunSrv = textVal;
+ }
+
+ cbData = sizeof(textVal);
+ if (key.QueryValue(textVal, REG_DNS, &cbData) == ERROR_SUCCESS) {
+ m_DNS = textVal;
+ }
+
+ dwordVal = 0;
+ if (key.QueryValue(dwordVal, REG_USE_STUN) == ERROR_SUCCESS) {
+ m_UseStun = dwordVal != 0;
+ }
+
+ if (key.QueryValue(dwordVal, REG_USE_ICE) == ERROR_SUCCESS) {
+ m_UseIce = dwordVal != 0;
+ }
+
+
+ if (key.QueryValue(dwordVal, REG_USE_SRTP) == ERROR_SUCCESS) {
+ m_UseSrtp = dwordVal != 0;
+ }
+
+
+ cbData = sizeof(dwordVal);
+ if (key.QueryValue(dwordVal, REG_USE_PUBLISH) == ERROR_SUCCESS) {
+ m_UsePublish = dwordVal != 0;
+ }
+
+ cbData = sizeof(dwordVal);
+ if (key.QueryValue(dwordVal, REG_ENABLE_EC) == ERROR_SUCCESS) {
+ m_EchoSuppress = dwordVal != 0;
+ }
+
+ cbData = sizeof(dwordVal);
+ if (key.QueryValue(dwordVal, REG_EC_TAIL) == ERROR_SUCCESS) {
+ m_EcTail = dwordVal;
+ }
+
+ cbData = sizeof(dwordVal);
+ if (key.QueryValue(dwordVal, REG_ENABLE_TCP) == ERROR_SUCCESS) {
+ m_TCP = dwordVal != 0;
+ }
+
+ cbData = sizeof(dwordVal);
+ if (key.QueryValue(dwordVal, REG_ENABLE_VAD) == ERROR_SUCCESS) {
+ m_VAD = dwordVal != 0;
+ }
+
+ cbData = sizeof(dwordVal);
+ if (key.QueryValue(dwordVal, REG_AUTO_ANSWER) == ERROR_SUCCESS) {
+ m_AutoAnswer = dwordVal != 0;
+ }
+
+ m_BuddyList.RemoveAll();
+
+ DWORD buddyCount = 0;
+ cbData = sizeof(dwordVal);
+ if (key.QueryValue(dwordVal, REG_BUDDY_CNT) == ERROR_SUCCESS) {
+ buddyCount = dwordVal;
+ }
+
+ unsigned i;
+ for (i=0; i<buddyCount; ++i) {
+ CString entry;
+ entry.Format(REG_BUDDY_X, i);
+
+ cbData = sizeof(textVal);
+ if (key.QueryValue(textVal, entry, &cbData) == ERROR_SUCCESS) {
+ m_BuddyList.Add(textVal);
+ }
+ }
+
+ DWORD codecCount = 0;
+ cbData = sizeof(dwordVal);
+ if (key.QueryValue(codecCount, REG_CODEC_CNT) == ERROR_SUCCESS) {
+
+ m_Codecs.RemoveAll();
+
+ for (i=0; i<codecCount; ++i) {
+ CString entry;
+ entry.Format(REG_CODEC_X, i);
+
+ cbData = sizeof(textVal);
+ if (key.QueryValue(textVal, entry, &cbData) == ERROR_SUCCESS) {
+ m_Codecs.Add(textVal);
+ }
+ }
+ }
+
+ key.Close();
+}
+
+// Save to registry
+void CPocketPJSettings::SaveRegistry()
+{
+ CRegKey key;
+
+ if (key.Create(HKEY_CURRENT_USER, REG_PATH) != ERROR_SUCCESS)
+ return;
+
+ key.SetValue(m_Domain, REG_DOMAIN);
+ key.SetValue(m_User, REG_USER);
+ key.SetValue(m_Password, REG_PASSWD);
+ key.SetValue(m_StunSrv, REG_STUN_SRV);
+ key.SetValue(m_DNS, REG_DNS);
+
+ key.SetValue(m_UseStun, REG_USE_STUN);
+ key.SetValue(m_UseIce, REG_USE_ICE);
+ key.SetValue(m_UseSrtp, REG_USE_SRTP);
+ key.SetValue(m_UsePublish, REG_USE_PUBLISH);
+
+ key.SetValue(m_EchoSuppress, REG_ENABLE_EC);
+ key.SetValue(m_EcTail, REG_EC_TAIL);
+
+ key.SetValue(m_TCP, REG_ENABLE_TCP);
+ key.SetValue(m_VAD, REG_ENABLE_VAD);
+ key.SetValue(m_AutoAnswer, REG_AUTO_ANSWER);
+
+ key.SetValue(m_BuddyList.GetSize(), REG_BUDDY_CNT);
+
+ int i;
+ for (i=0; i<m_BuddyList.GetSize(); ++i) {
+ CString entry;
+ entry.Format(REG_BUDDY_X, i);
+ key.SetValue(m_BuddyList.GetAt(i), entry);
+ }
+
+ DWORD N = m_Codecs.GetSize();
+ key.SetValue(N, REG_CODEC_CNT);
+ for (i=0; i<m_Codecs.GetSize(); ++i) {
+ CString entry;
+ entry.Format(REG_CODEC_X, i);
+ key.SetValue(m_Codecs.GetAt(i), entry);
+ }
+
+ key.Close();
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CSettingsDlg dialog
+
+
+CSettingsDlg::CSettingsDlg(CPocketPJSettings &cfg, CWnd* pParent)
+ : CDialog(CSettingsDlg::IDD, pParent), m_Cfg(cfg)
+{
+ //{{AFX_DATA_INIT(CSettingsDlg)
+ m_Domain = _T("");
+ m_ICE = FALSE;
+ m_Passwd = _T("");
+ m_PUBLISH = FALSE;
+ m_SRTP = FALSE;
+ m_STUN = FALSE;
+ m_StunSrv = _T("");
+ m_User = _T("");
+ m_Dns = _T("");
+ m_EchoSuppress = FALSE;
+ m_EcTail = _T("");
+ m_TCP = FALSE;
+ m_VAD = FALSE;
+ m_AutoAnswer = FALSE;
+ //}}AFX_DATA_INIT
+
+ m_Domain = m_Cfg.m_Domain;
+ m_ICE = m_Cfg.m_UseIce;
+ m_Passwd = m_Cfg.m_Password;
+ m_PUBLISH = m_Cfg.m_UsePublish;
+ m_SRTP = m_Cfg.m_UseSrtp;
+ m_STUN = m_Cfg.m_UseStun;
+ m_StunSrv = m_Cfg.m_StunSrv;
+ m_User = m_Cfg.m_User;
+ m_Dns = m_Cfg.m_DNS;
+ m_EchoSuppress = m_Cfg.m_EchoSuppress;
+ m_TCP = m_Cfg.m_TCP;
+ m_VAD = m_Cfg.m_VAD;
+ m_AutoAnswer= m_Cfg.m_AutoAnswer;
+
+ CString s;
+ s.Format(_T("%d"), m_Cfg.m_EcTail);
+ m_EcTail = s;
+
+}
+
+
+void CSettingsDlg::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CSettingsDlg)
+ DDX_Control(pDX, IDC_CODECS, m_Codecs);
+ DDX_Text(pDX, IDC_DOMAIN, m_Domain);
+ DDX_Check(pDX, IDC_ICE, m_ICE);
+ DDX_Text(pDX, IDC_PASSWD, m_Passwd);
+ DDX_Check(pDX, IDC_PUBLISH, m_PUBLISH);
+ DDX_Check(pDX, IDC_SRTP, m_SRTP);
+ DDX_Check(pDX, IDC_STUN, m_STUN);
+ DDX_Text(pDX, IDC_STUN_SRV, m_StunSrv);
+ DDX_Text(pDX, IDC_USER, m_User);
+ DDX_Text(pDX, IDC_DNS, m_Dns);
+ DDX_Check(pDX, IDC_ECHO_SUPPRESS, m_EchoSuppress);
+ DDX_Text(pDX, IDC_EC_TAIL, m_EcTail);
+ DDX_Check(pDX, IDC_TCP, m_TCP);
+ DDX_Check(pDX, IDC_VAD, m_VAD);
+ DDX_Check(pDX, IDC_AA, m_AutoAnswer);
+ //}}AFX_DATA_MAP
+
+
+ if (m_Codecs.GetCount() == 0) {
+ int i;
+ for (i=0; i<m_Cfg.m_Codecs.GetSize(); ++i) {
+ m_Codecs.AddString(m_Cfg.m_Codecs.GetAt(i));
+ }
+ m_Codecs.SetCurSel(0);
+ }
+}
+
+
+BEGIN_MESSAGE_MAP(CSettingsDlg, CDialog)
+ //{{AFX_MSG_MAP(CSettingsDlg)
+ ON_BN_CLICKED(IDC_STUN, OnStun)
+ ON_BN_CLICKED(IDC_ECHO_SUPPRESS, OnEchoSuppress)
+ ON_CBN_SELCHANGE(IDC_CODECS, OnSelchangeCodecs)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CSettingsDlg message handlers
+
+int CSettingsDlg::DoModal()
+{
+ int rc = CDialog::DoModal();
+
+ return rc;
+}
+
+void CSettingsDlg::OnStun()
+{
+}
+
+void CSettingsDlg::OnEchoSuppress()
+{
+}
+
+void CSettingsDlg::OnSelchangeCodecs()
+{
+ int cur = m_Codecs.GetCurSel();
+ if (cur < 1)
+ return;
+
+ CString codec;
+ DWORD N;
+
+ m_Codecs.GetLBText(cur, codec);
+ N = m_Codecs.GetCount();
+ m_Codecs.DeleteString(cur);
+ N = m_Codecs.GetCount();
+ m_Codecs.InsertString(0, codec);
+ N = m_Codecs.GetCount();
+ m_Codecs.SetCurSel(0);
+}
+
+
+void CSettingsDlg::OnOK()
+{
+ UpdateData(TRUE);
+
+ m_Cfg.m_Domain = m_Domain;
+ m_Cfg.m_UseIce = m_ICE != 0;
+ m_Cfg.m_Password = m_Passwd;
+ m_Cfg.m_UsePublish = m_PUBLISH != 0;
+ m_Cfg.m_UseSrtp = m_SRTP != 0;
+ m_Cfg.m_UseStun = m_STUN != 0;
+ m_Cfg.m_StunSrv = m_StunSrv;
+ m_Cfg.m_User = m_User;
+ m_Cfg.m_DNS = m_Dns;
+ m_Cfg.m_EchoSuppress= m_EchoSuppress != 0;
+ m_Cfg.m_EcTail = _ttoi(m_EcTail);
+ m_Cfg.m_TCP = m_TCP != 0;
+ m_Cfg.m_VAD = m_VAD != 0;
+ m_Cfg.m_AutoAnswer = m_AutoAnswer != 0;
+
+ unsigned i;
+ m_Cfg.m_Codecs.RemoveAll();
+ DWORD N = m_Codecs.GetCount();
+ for (i=0; i<N; ++i) {
+ CString codec;
+ m_Codecs.GetLBText(i, codec);
+ m_Cfg.m_Codecs.Add(codec);
+ }
+
+ CDialog::OnOK();
+}
diff --git a/pjsip-apps/src/pocketpj/SettingsDlg.h b/pjsip-apps/src/pocketpj/SettingsDlg.h
new file mode 100644
index 0000000..816ede9
--- /dev/null
+++ b/pjsip-apps/src/pocketpj/SettingsDlg.h
@@ -0,0 +1,99 @@
+#if !defined(AFX_SETTINGSDLG_H__46F18E6E_F411_4D9E_BEE9_619D80BC81DC__INCLUDED_)
+#define AFX_SETTINGSDLG_H__46F18E6E_F411_4D9E_BEE9_619D80BC81DC__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// SettingsDlg.h : header file
+//
+#include <Afxtempl.h>
+
+/////////////////////////////////////////////////////////////////////////////
+// Settings
+struct CPocketPJSettings
+{
+ CString m_Domain;
+ CString m_User;
+ CString m_Password;
+ bool m_UseStun;
+ CString m_StunSrv;
+ bool m_UseIce;
+ bool m_UseSrtp;
+ bool m_UsePublish;
+ CString m_DNS;
+ bool m_EchoSuppress;
+ DWORD m_EcTail;
+ bool m_TCP;
+ bool m_VAD;
+ bool m_AutoAnswer;
+
+ CArray<CString,CString> m_Codecs;
+ CArray<CString,CString> m_BuddyList;
+
+ CPocketPJSettings();
+
+ // Load from registry
+ void LoadRegistry();
+
+ // Save to registry
+ void SaveRegistry();
+};
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CSettingsDlg dialog
+
+class CSettingsDlg : public CDialog
+{
+// Construction
+public:
+ CSettingsDlg(CPocketPJSettings & cfg, CWnd* pParent = NULL);
+
+// Dialog Data
+ //{{AFX_DATA(CSettingsDlg)
+ enum { IDD = IDD_SETTING };
+ CComboBox m_Codecs;
+ CString m_Domain;
+ BOOL m_ICE;
+ CString m_Passwd;
+ BOOL m_PUBLISH;
+ BOOL m_SRTP;
+ BOOL m_STUN;
+ CString m_StunSrv;
+ CString m_User;
+ CString m_Dns;
+ BOOL m_EchoSuppress;
+ CString m_EcTail;
+ BOOL m_TCP;
+ BOOL m_VAD;
+ BOOL m_AutoAnswer;
+ //}}AFX_DATA
+
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CSettingsDlg)
+ public:
+ virtual int DoModal();
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+ CPocketPJSettings & m_Cfg;
+
+ // Generated message map functions
+ //{{AFX_MSG(CSettingsDlg)
+ afx_msg void OnStun();
+ afx_msg void OnEchoSuppress();
+ afx_msg void OnSelchangeCodecs();
+ virtual void OnOK();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_SETTINGSDLG_H__46F18E6E_F411_4D9E_BEE9_619D80BC81DC__INCLUDED_)
diff --git a/pjsip-apps/src/pocketpj/StdAfx.cpp b/pjsip-apps/src/pocketpj/StdAfx.cpp
new file mode 100644
index 0000000..78794a3
--- /dev/null
+++ b/pjsip-apps/src/pocketpj/StdAfx.cpp
@@ -0,0 +1,6 @@
+// stdafx.cpp : source file that includes just the standard includes
+// PocketPJ.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
diff --git a/pjsip-apps/src/pocketpj/StdAfx.h b/pjsip-apps/src/pocketpj/StdAfx.h
new file mode 100644
index 0000000..4142afe
--- /dev/null
+++ b/pjsip-apps/src/pocketpj/StdAfx.h
@@ -0,0 +1,32 @@
+// 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__20B05C7D_B63E_4E5C_B3BB_E76C6C9E70B7__INCLUDED_)
+#define AFX_STDAFX_H__20B05C7D_B63E_4E5C_B3BB_E76C6C9E70B7__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+#pragma warning(disable:4496)
+
+
+#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
+
+#include <afxwin.h> // MFC core and standard components
+#include <afxext.h> // MFC extensions
+
+#if defined(_AFXDLL)
+#include <afxdtctl.h> // MFC support for Internet Explorer 4 Common Controls
+#endif
+
+#ifndef _AFX_NO_AFXCMN_SUPPORT
+#include <afxcmn.h> // MFC support for Windows Common Controls
+#endif // _AFX_NO_AFXCMN_SUPPORT
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft eMbedded Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_STDAFX_H__20B05C7D_B63E_4E5C_B3BB_E76C6C9E70B7__INCLUDED_)
diff --git a/pjsip-apps/src/pocketpj/newres.h b/pjsip-apps/src/pocketpj/newres.h
new file mode 100644
index 0000000..31c3a43
--- /dev/null
+++ b/pjsip-apps/src/pocketpj/newres.h
@@ -0,0 +1,28 @@
+#ifndef __NEWRES_H__
+#define __NEWRES_H__
+
+#define SHMENUBAR RCDATA
+#if !(defined(_WIN32_WCE_PSPC) && (_WIN32_WCE >= 300))
+ #undef HDS_HORZ
+ #undef HDS_BUTTONS
+ #undef HDS_HIDDEN
+
+ #include <commctrl.h>
+ // for MenuBar
+ #define I_IMAGENONE (-2)
+ #define NOMENU 0xFFFF
+ #define IDS_SHNEW 1
+ #define IDM_SHAREDNEW 10
+ #define IDM_SHAREDNEWDEFAULT 11
+
+ // for Tab Control
+ #define TCS_SCROLLOPPOSITE 0x0001 // assumes multiline tab
+ #define TCS_BOTTOM 0x0002
+ #define TCS_RIGHT 0x0002
+ #define TCS_VERTICAL 0x0080
+ #define TCS_MULTISELECT 0x0004 // allow multi-select in button mode
+ #define TCS_FLATBUTTONS 0x0008
+#endif //_WIN32_WCE_PSPC
+
+
+#endif //__NEWRES_H__
diff --git a/pjsip-apps/src/pocketpj/output/.keep b/pjsip-apps/src/pocketpj/output/.keep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/pjsip-apps/src/pocketpj/output/.keep
diff --git a/pjsip-apps/src/pocketpj/res/PocketPJ.ico b/pjsip-apps/src/pocketpj/res/PocketPJ.ico
new file mode 100644
index 0000000..51a182e
--- /dev/null
+++ b/pjsip-apps/src/pocketpj/res/PocketPJ.ico
Binary files differ
diff --git a/pjsip-apps/src/pocketpj/res/PocketPJ.rc2 b/pjsip-apps/src/pocketpj/res/PocketPJ.rc2
new file mode 100644
index 0000000..50048ba
--- /dev/null
+++ b/pjsip-apps/src/pocketpj/res/PocketPJ.rc2
@@ -0,0 +1,13 @@
+//
+// POCKETPJ.RC2 - resources Microsoft eMbedded Visual C++ does not edit directly
+//
+
+#ifdef APSTUDIO_INVOKED
+ #error this file is not editable by Microsoft eMbedded Visual C++
+#endif //APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Add manually edited resources here...
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/pjsip-apps/src/pocketpj/res/action.bmp b/pjsip-apps/src/pocketpj/res/action.bmp
new file mode 100644
index 0000000..dac70fe
--- /dev/null
+++ b/pjsip-apps/src/pocketpj/res/action.bmp
Binary files differ
diff --git a/pjsip-apps/src/pocketpj/res/blank.bmp b/pjsip-apps/src/pocketpj/res/blank.bmp
new file mode 100644
index 0000000..d9521c4
--- /dev/null
+++ b/pjsip-apps/src/pocketpj/res/blank.bmp
Binary files differ
diff --git a/pjsip-apps/src/pocketpj/res/invisibl.bmp b/pjsip-apps/src/pocketpj/res/invisibl.bmp
new file mode 100644
index 0000000..8819406
--- /dev/null
+++ b/pjsip-apps/src/pocketpj/res/invisibl.bmp
Binary files differ
diff --git a/pjsip-apps/src/pocketpj/res/invisibl.ico b/pjsip-apps/src/pocketpj/res/invisibl.ico
new file mode 100644
index 0000000..7404261
--- /dev/null
+++ b/pjsip-apps/src/pocketpj/res/invisibl.ico
Binary files differ
diff --git a/pjsip-apps/src/pocketpj/res/offline.bmp b/pjsip-apps/src/pocketpj/res/offline.bmp
new file mode 100644
index 0000000..cf18162
--- /dev/null
+++ b/pjsip-apps/src/pocketpj/res/offline.bmp
Binary files differ
diff --git a/pjsip-apps/src/pocketpj/res/offline.ico b/pjsip-apps/src/pocketpj/res/offline.ico
new file mode 100644
index 0000000..207c666
--- /dev/null
+++ b/pjsip-apps/src/pocketpj/res/offline.ico
Binary files differ
diff --git a/pjsip-apps/src/pocketpj/res/online.bmp b/pjsip-apps/src/pocketpj/res/online.bmp
new file mode 100644
index 0000000..7d87554
--- /dev/null
+++ b/pjsip-apps/src/pocketpj/res/online.bmp
Binary files differ
diff --git a/pjsip-apps/src/pocketpj/res/online.ico b/pjsip-apps/src/pocketpj/res/online.ico
new file mode 100644
index 0000000..c999c2b
--- /dev/null
+++ b/pjsip-apps/src/pocketpj/res/online.ico
Binary files differ
diff --git a/pjsip-apps/src/pocketpj/resource.h b/pjsip-apps/src/pocketpj/resource.h
new file mode 100644
index 0000000..85eefa2
--- /dev/null
+++ b/pjsip-apps/src/pocketpj/resource.h
@@ -0,0 +1,71 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft eMbedded Visual C++ generated include file.
+// Used by PocketPJ.rc
+//
+#define IDD_POCKETPJ_DIALOG 102
+#define IDR_MAINFRAME 128
+#define IDI_ONLINE 131
+#define IDI_OFFLINE 132
+#define IDI_INVISIBLE 133
+#define IDB_ONLINE 135
+#define IDB_OFFLINE 136
+#define IDB_INVISIBLE 137
+#define IDB_ACTION 138
+#define IDR_ACC_MENU 139
+#define IDR_URI_MENU 140
+#define IDD_SETTING 141
+#define IDD_POPUP 143
+#define IDB_BLANK 144
+#define IDC_BTN_ACC 1006
+#define IDC_BTN_ACTION 1007
+#define IDC_ACC_ID 1008
+#define IDC_BUDDY_LIST 1009
+#define IDC_URL 1010
+#define IDC_DOMAIN 1011
+#define IDC_USER 1012
+#define IDC_PASSWD 1013
+#define IDC_STUN 1014
+#define IDC_STUN_SRV 1015
+#define IDC_ICE 1016
+#define IDC_SRTP 1017
+#define IDC_TITLE1 1017
+#define IDC_PUBLISH 1018
+#define IDC_TITLE2 1018
+#define IDC_DNS 1019
+#define IDC_TITLE3 1020
+#define IDC_ECHO_SUPPRESS 1020
+#define IDC_BUTTON1 1021
+#define IDC_EC_TAIL 1021
+#define IDC_BUTTON2 1022
+#define IDC_VAD 1022
+#define IDC_TCP 1023
+#define IDC_CODECS 1024
+#define IDC_AA 1025
+#define IDS_CAP_ONLINE 32772
+#define IDS_CAP_OFFLINE 32774
+#define IDS_CAP_INVISIBLE 32776
+#define IDC_ONLINE 32777
+#define IDC_ACC_ONLINE 32777
+#define IDS_CAP_MENUITEM32783 32784
+#define IDC_MENU1 32785
+#define IDS_CAP_MENUITEM32786 32787
+#define IDC_SETTINGS 32788
+#define IDC_ACC_SETTINGS 32788
+#define IDC_MENU2 32789
+#define IDS_CAP_MENUITEM32790 32791
+#define IDC_URI_CALL 32792
+#define IDC_URI_ADD_BUDDY 32793
+#define ID_URI_DEL_BUDDY 32794
+#define IDC_URI_DEL_BUDDY 32794
+#define IDC_ACC_INVISIBLE 32795
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 145
+#define _APS_NEXT_COMMAND_VALUE 32796
+#define _APS_NEXT_CONTROL_VALUE 1025
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/pjsip-apps/src/py_pjsua/DEPRECATED.txt b/pjsip-apps/src/py_pjsua/DEPRECATED.txt
new file mode 100644
index 0000000..c5e8587
--- /dev/null
+++ b/pjsip-apps/src/py_pjsua/DEPRECATED.txt
@@ -0,0 +1,2 @@
+This Python module is now deprecated. Please use the new implementation under
+pjsip-apps/python directory.
diff --git a/pjsip-apps/src/py_pjsua/Makefile b/pjsip-apps/src/py_pjsua/Makefile
new file mode 100644
index 0000000..10ed2fb
--- /dev/null
+++ b/pjsip-apps/src/py_pjsua/Makefile
@@ -0,0 +1,6 @@
+all:
+ python setup.py install
+
+clean:
+ python setup.py clean
+ rm -rf ./build
diff --git a/pjsip-apps/src/py_pjsua/helper.mak b/pjsip-apps/src/py_pjsua/helper.mak
new file mode 100644
index 0000000..b4acce6
--- /dev/null
+++ b/pjsip-apps/src/py_pjsua/helper.mak
@@ -0,0 +1,17 @@
+include ../../../build.mak
+
+lib_dir:
+ @for token in `echo $(APP_LDFLAGS)`; do \
+ echo $$token | grep L | sed 's/-L//'; \
+ done
+
+inc_dir:
+ @for token in `echo $(APP_CFLAGS)`; do \
+ echo $$token | grep I | sed 's/-I//'; \
+ done
+
+libs:
+ @for token in `echo $(APP_LDLIBS)`; do \
+ echo $$token | grep \\-l | sed 's/-l//'; \
+ done
+
diff --git a/pjsip-apps/src/py_pjsua/pjsua.py b/pjsip-apps/src/py_pjsua/pjsua.py
new file mode 100644
index 0000000..f769ba5
--- /dev/null
+++ b/pjsip-apps/src/py_pjsua/pjsua.py
@@ -0,0 +1,264 @@
+import py_pjsua
+
+status = py_pjsua.create()
+print "py status " + `status`
+
+
+#
+# Create configuration objects
+#
+ua_cfg = py_pjsua.config_default()
+log_cfg = py_pjsua.logging_config_default()
+media_cfg = py_pjsua.media_config_default()
+
+#
+# Logging callback.
+#
+def logging_cb1(level, str, len):
+ print str,
+
+
+#
+# Configure logging
+#
+log_cfg.cb = logging_cb1
+log_cfg.console_level = 4
+
+#
+# Initialize pjsua!
+#
+status = py_pjsua.init(ua_cfg, log_cfg, media_cfg);
+print "py status after initialization :" + `status`
+
+
+#
+# Start pjsua!
+#
+status = py_pjsua.start()
+if status != 0:
+ exit(1)
+
+
+message = py_pjsua.msg_data_init()
+
+print "identitas object message data :" + `message`
+
+sipaddr = 'sip:167.205.34.99'
+print "checking sip address [%s] : %d" % (sipaddr, py_pjsua.verify_sip_url(sipaddr))
+
+sipaddr = '167.205.34.99'
+print "checking invalid sip address [%s] : %d" % (sipaddr, py_pjsua.verify_sip_url(sipaddr))
+
+object = py_pjsua.get_pjsip_endpt()
+print "identitas Endpoint :" + `object` + ""
+
+mediaend = py_pjsua.get_pjmedia_endpt()
+print "identitas Media Endpoint :" + `mediaend` + ""
+
+pool = py_pjsua.get_pool_factory()
+print "identitas pool factory :" + `pool` + ""
+
+status = py_pjsua.handle_events(3000)
+print "py status after 3 second of blocking wait :" + `status`
+
+
+
+# end of new testrun
+
+#
+
+# lib transport
+stunc = py_pjsua.stun_config_default();
+
+
+tc = py_pjsua.transport_config_default();
+
+
+py_pjsua.normalize_stun_config(stunc);
+
+
+status, id = py_pjsua.transport_create(1, tc);
+print "py transport create status " + `status`
+
+ti = py_pjsua.Transport_Info();
+ti = py_pjsua.transport_get_info(id)
+print "py transport get info status " + `status`
+
+status = py_pjsua.transport_set_enable(id,1)
+print "py transport set enable status " + `status`
+if status != 0 :
+ py_pjsua.perror("py_pjsua","set enable",status)
+
+
+status = py_pjsua.transport_close(id,1)
+print "py transport close status " + `status`
+if status != 0 :
+ py_pjsua.perror("py_pjsua","close",status)
+
+# end of lib transport
+
+# lib account
+
+accfg = py_pjsua.acc_config_default()
+status, accid = py_pjsua.acc_add(accfg, 1)
+print "py acc add status " + `status`
+if status != 0 :
+ py_pjsua.perror("py_pjsua","add acc",status)
+count = py_pjsua.acc_get_count()
+print "acc count " + `count`
+
+accid = py_pjsua.acc_get_default()
+
+print "acc id default " + `accid`
+
+# end of lib account
+
+#lib buddy
+
+bcfg = py_pjsua.Buddy_Config()
+status, id = py_pjsua.buddy_add(bcfg)
+acc_id = id
+print "py buddy add status " + `status` + " id " + `id`
+bool = py_pjsua.buddy_is_valid(id)
+print "py buddy is valid " + `bool`
+count = py_pjsua.get_buddy_count()
+print "buddy count " + `count`
+binfo = py_pjsua.buddy_get_info(id)
+ids = py_pjsua.enum_buddies()
+status = py_pjsua.buddy_del(id)
+print "py buddy del status " + `status`
+status = py_pjsua.buddy_subscribe_pres(id, 1)
+print "py buddy subscribe pres status " + `status`
+py_pjsua.pres_dump(1)
+status = py_pjsua.im_send(accid, "fahris@divusi.com", "", "hallo", message, 0)
+print "py im send status " + `status`
+status = py_pjsua.im_typing(accid, "fahris@divusi.com", 1, message)
+print "py im typing status " + `status`
+#print "binfo " + `binfo`
+
+#end of lib buddy
+
+#lib media
+count = py_pjsua.conf_get_max_ports()
+print "py media conf get max ports " + `count`
+count = py_pjsua.conf_get_active_ports()
+print "py media conf get active ports " + `count`
+ids = py_pjsua.enum_conf_ports()
+for id in ids:
+ print "py media conf ports " + `id`
+ cp_info = py_pjsua.conf_get_port_info(id)
+ print "port info name " + cp_info.name
+pool = py_pjsua.PJ_Pool()
+port = py_pjsua.PJMedia_Port()
+status, id = py_pjsua.conf_add_port(pool,port)
+print "py media conf add port status " + `status` + " id " + `id`
+if status != 0 :
+ py_pjsua.perror("py_pjsua","add port",status)
+status = py_pjsua.conf_remove_port(id)
+print "py media conf remove port status " + `status`
+if status != 0 :
+ py_pjsua.perror("py_pjsua","remove port",status)
+status = py_pjsua.conf_connect(id, id)
+print "py media conf connect status " + `status`
+if status != 0 :
+ py_pjsua.perror("py_pjsua","connect",status)
+status = py_pjsua.conf_disconnect(id, id)
+print "py media conf disconnect status " + `status`
+if status != 0 :
+ py_pjsua.perror("py_pjsua","disconnect",status)
+status, id = py_pjsua.player_create("test.wav", 0)
+print "py media player create status " + `status` + " id " + `id`
+if status != 0 :
+ py_pjsua.perror("py_pjsua","player create",status)
+c_id = py_pjsua.player_get_conf_port(id)
+print "py media player get conf port id " + `c_id`
+status = py_pjsua.player_set_pos(id, 10)
+if status != 0 :
+ py_pjsua.perror("py_pjsua","player set pos",status)
+status = py_pjsua.player_destroy(id)
+if status != 0 :
+ py_pjsua.perror("py_pjsua","player destroy",status)
+status, id = py_pjsua.recorder_create("rec.wav", 0, "None", 1000, 0)
+print "py media recorder create status " + `status` + " id " + `id`
+if status != 0 :
+ py_pjsua.perror("py_pjsua","recorder create",status)
+status = py_pjsua.recorder_get_conf_port(id)
+print "py media recorder get conf port status " + `status`
+if status != 0 :
+ py_pjsua.perror("py_pjsua","recorder get conf port",status)
+status = py_pjsua.recorder_destroy(id)
+print "py media recorder destroy status " + `status`
+if status != 0 :
+ py_pjsua.perror("py_pjsua","recorder destroy",status)
+#cdev, pdev = py_pjsua.get_snd_dev()
+#print "py media get snd dev capture dev " + `cdev` + " playback dev " + `pdev`
+status = py_pjsua.set_snd_dev(0,1)
+print "py media set snd dev status " + `status`
+if status != 0 :
+ py_pjsua.perror("py_pjsua","set snd dev",status)
+status = py_pjsua.set_null_snd_dev()
+print "py media set null snd dev status " + `status`
+if status != 0 :
+ py_pjsua.perror("py_pjsua","set null snd dev",status)
+port = py_pjsua.set_no_snd_dev()
+status = py_pjsua.set_ec(0,0)
+print "py media set ec status " + `status`
+if status != 0 :
+ py_pjsua.perror("py_pjsua","set ec",status)
+tail = py_pjsua.get_ec_tail()
+print "py media get ec tail " + `tail`
+infos = py_pjsua.enum_codecs()
+for info in infos:
+ print "py media enum codecs " + `info`
+status = py_pjsua.codec_set_priority("coba", 0)
+print "py media codec set priority " + `status`
+if status != 0 :
+ py_pjsua.perror("py_pjsua","codec set priority",status)
+c_param = py_pjsua.codec_get_param("coba")
+status = py_pjsua.codec_set_param("coba", c_param)
+print "py media codec set param " + `status`
+if status != 0 :
+ py_pjsua.perror("py_pjsua","codec set param",status)
+
+#end of lib media
+
+#lib call
+
+count = py_pjsua.call_get_max_count()
+print "py call get max count " + `count`
+count = py_pjsua.call_get_count()
+print "py call get count " + `count`
+ids = py_pjsua.enum_calls()
+for id in ids:
+ print "py enum calls id " + `id`
+msg_data = py_pjsua.Msg_Data()
+status, id = py_pjsua.call_make_call(-1, "sip:bulukucing1@iptel.org", 0, 0, msg_data)
+print "py call make call " + `status` + " id " + `id`
+if status != 0 :
+ py_pjsua.perror("py_pjsua","call make call",status)
+bool = py_pjsua.call_is_active(id)
+print "py call is active " + `bool`
+bool = py_pjsua.call_has_media(id)
+print "py call has media " + `bool`
+cp_id = py_pjsua.call_get_conf_port(id)
+print "py call get conf port " + `cp_id`
+info = py_pjsua.call_get_info(id)
+if info != None :
+ print "py info id " + `info.id`
+status = py_pjsua.call_set_user_data(id, 0)
+print "py call set user data status " + `status`
+if status != 0 :
+ py_pjsua.perror("py_pjsua","set user data",status)
+user_data = py_pjsua.call_get_user_data(id)
+print "py call get user data " + `user_data`
+
+
+
+#end of lib call
+
+py_pjsua.perror("saya","hallo",70006)
+
+status = py_pjsua.destroy()
+print "py status " + `status`
+
+
diff --git a/pjsip-apps/src/py_pjsua/pjsua_app.py b/pjsip-apps/src/py_pjsua/pjsua_app.py
new file mode 100644
index 0000000..a0fd56c
--- /dev/null
+++ b/pjsip-apps/src/py_pjsua/pjsua_app.py
@@ -0,0 +1,780 @@
+# $Id: pjsua_app.py 1438 2007-09-17 15:44:47Z bennylp $
+#
+# Sample and simple Python script to make and receive calls, and do
+# presence and instant messaging/IM using PJSUA-API binding for Python.
+#
+# Copyright (C) 2003-2007 Benny Prijono <benny@prijono.org>
+#
+import py_pjsua
+import sys
+import thread
+
+#
+# Configurations
+#
+THIS_FILE = "pjsua_app.py"
+C_QUIT = 0
+C_LOG_LEVEL = 4
+
+# STUN config.
+# Set C_STUN_HOST to the address:port of the STUN server to enable STUN
+#
+C_STUN_HOST = ""
+#C_STUN_HOST = "192.168.0.2"
+#C_STUN_HOST = "stun.iptel.org:3478"
+
+# SIP port
+C_SIP_PORT = 5060
+
+
+# Globals
+#
+g_ua_cfg = None
+g_acc_id = py_pjsua.PJSUA_INVALID_ID
+g_current_call = py_pjsua.PJSUA_INVALID_ID
+g_wav_files = []
+g_wav_id = 0
+g_wav_port = 0
+g_rec_file = ""
+g_rec_id = 0
+g_rec_port = 0
+
+# Utility: display PJ error and exit
+#
+def err_exit(title, rc):
+ py_pjsua.perror(THIS_FILE, title, rc)
+ py_pjsua.destroy()
+ exit(1)
+
+
+# Logging function (also callback, called by pjsua-lib)
+#
+def log_cb(level, str, len):
+ if level <= C_LOG_LEVEL:
+ print str,
+
+def write_log(level, str):
+ log_cb(level, str + "\n", 0)
+
+
+# Utility to get call info
+#
+def call_name(call_id):
+ ci = py_pjsua.call_get_info(call_id)
+ return "[Call " + `call_id` + " " + ci.remote_info + "]"
+
+# Callback when call state has changed.
+#
+def on_call_state(call_id, e):
+ global g_current_call
+ ci = py_pjsua.call_get_info(call_id)
+ write_log(3, call_name(call_id) + " state = " + `ci.state_text`)
+ if ci.state == py_pjsua.PJSIP_INV_STATE_DISCONNECTED:
+ g_current_call = py_pjsua.PJSUA_INVALID_ID
+
+# Callback for incoming call
+#
+def on_incoming_call(acc_id, call_id, rdata):
+ global g_current_call
+
+ if g_current_call != py_pjsua.PJSUA_INVALID_ID:
+ # There's call in progress - answer Busy
+ py_pjsua.call_answer(call_id, 486, None, None)
+ return
+
+ g_current_call = call_id
+ ci = py_pjsua.call_get_info(call_id)
+ write_log(3, "*** Incoming call: " + call_name(call_id) + "***")
+ write_log(3, "*** Press a to answer or h to hangup ***")
+
+
+
+# Callback when media state has changed (e.g. established or terminated)
+#
+def on_call_media_state(call_id):
+ ci = py_pjsua.call_get_info(call_id)
+ if ci.media_status == py_pjsua.PJSUA_CALL_MEDIA_ACTIVE:
+ py_pjsua.conf_connect(ci.conf_slot, 0)
+ py_pjsua.conf_connect(0, ci.conf_slot)
+ write_log(3, call_name(call_id) + ": media is active")
+ else:
+ write_log(3, call_name(call_id) + ": media is inactive")
+
+
+# Callback when account registration state has changed
+#
+def on_reg_state(acc_id):
+ acc_info = py_pjsua.acc_get_info(acc_id)
+ if acc_info.has_registration != 0:
+ cmd = "registration"
+ else:
+ cmd = "unregistration"
+ if acc_info.status != 0 and acc_info.status != 200:
+ write_log(3, "Account " + cmd + " failed: rc=" + `acc_info.status` + " " + acc_info.status_text)
+ else:
+ write_log(3, "Account " + cmd + " success")
+
+
+# Callback when buddy's presence state has changed
+#
+def on_buddy_state(buddy_id):
+ write_log(3, "On Buddy state called")
+ buddy_info = py_pjsua.buddy_get_info(buddy_id)
+ if buddy_info.status != 0 and buddy_info.status != 200:
+ write_log(3, "Status of " + `buddy_info.uri` + " is " + `buddy_info.status_text`)
+ else:
+ write_log(3, "Status : " + `buddy_info.status`)
+
+# Callback on incoming pager (MESSAGE)
+#
+def on_pager(call_id, strfrom, strto, contact, mime_type, text):
+ write_log(3, "MESSAGE from " + `strfrom` + " : " + `text`)
+
+
+# Callback on the delivery status of outgoing pager (MESSAGE)
+#
+def on_pager_status(call_id, strto, body, user_data, status, reason):
+ write_log(3, "MESSAGE to " + `strto` + " status " + `status` + " reason " + `reason`)
+
+
+# Received typing indication
+#
+def on_typing(call_id, strfrom, to, contact, is_typing):
+ str_t = ""
+ if is_typing:
+ str_t = "is typing.."
+ else:
+ str_t = "has stopped typing"
+ write_log(3, "IM indication: " + strfrom + " " + str_t)
+
+# Received the status of previous call transfer request
+#
+def on_call_transfer_status(call_id,status_code,status_text,final,p_cont):
+ strfinal = ""
+ if final == 1:
+ strfinal = "[final]"
+
+ write_log(3, "Call " + `call_id` + ": transfer status= " + `status_code` + " " + status_text+ " " + strfinal)
+
+ if status_code/100 == 2:
+ write_log(3, "Call " + `call_id` + " : call transfered successfully, disconnecting call")
+ status = py_pjsua.call_hangup(call_id, 410, None, None)
+ p_cont = 0
+
+# Callback on incoming call transfer request
+#
+def on_call_transfer_request(call_id, dst, code):
+ write_log(3, "Call transfer request from " + `call_id` + " to " + dst + " with code " + `code`)
+
+#
+# Initialize pjsua.
+#
+def app_init():
+ global g_acc_id, g_ua_cfg
+
+ # Create pjsua before anything else
+ status = py_pjsua.create()
+ if status != 0:
+ err_exit("pjsua create() error", status)
+
+ # Create and initialize logging config
+ log_cfg = py_pjsua.logging_config_default()
+ log_cfg.level = C_LOG_LEVEL
+ log_cfg.cb = log_cb
+
+ # Create and initialize pjsua config
+ # Note: for this Python module, thread_cnt must be 0 since Python
+ # doesn't like to be called from alien thread (pjsua's thread
+ # in this case)
+ ua_cfg = py_pjsua.config_default()
+ ua_cfg.thread_cnt = 0
+ ua_cfg.user_agent = "PJSUA/Python 0.1"
+ ua_cfg.cb.on_incoming_call = on_incoming_call
+ ua_cfg.cb.on_call_media_state = on_call_media_state
+ ua_cfg.cb.on_reg_state = on_reg_state
+ ua_cfg.cb.on_call_state = on_call_state
+ ua_cfg.cb.on_buddy_state = on_buddy_state
+ ua_cfg.cb.on_pager = on_pager
+ ua_cfg.cb.on_pager_status = on_pager_status
+ ua_cfg.cb.on_typing = on_typing
+ ua_cfg.cb.on_call_transfer_status = on_call_transfer_status
+ ua_cfg.cb.on_call_transfer_request = on_call_transfer_request
+
+ # Configure STUN setting
+ if C_STUN_HOST != "":
+ ua_cfg.stun_host = C_STUN_HOST;
+
+ # Create and initialize media config
+ med_cfg = py_pjsua.media_config_default()
+ med_cfg.ec_tail_len = 0
+
+ #
+ # Initialize pjsua!!
+ #
+ status = py_pjsua.init(ua_cfg, log_cfg, med_cfg)
+ if status != 0:
+ err_exit("pjsua init() error", status)
+
+ # Configure UDP transport config
+ transport_cfg = py_pjsua.transport_config_default()
+ transport_cfg.port = C_SIP_PORT
+
+ # Create UDP transport
+ status, transport_id = \
+ py_pjsua.transport_create(py_pjsua.PJSIP_TRANSPORT_UDP, transport_cfg)
+ if status != 0:
+ err_exit("Error creating UDP transport", status)
+
+
+ # Create initial default account
+ status, acc_id = py_pjsua.acc_add_local(transport_id, 1)
+ if status != 0:
+ err_exit("Error creating account", status)
+
+ g_acc_id = acc_id
+ g_ua_cfg = ua_cfg
+
+# Add SIP account interractively
+#
+def add_account():
+ global g_acc_id
+
+ acc_domain = ""
+ acc_username = ""
+ acc_passwd =""
+ confirm = ""
+
+ # Input account configs
+ print "Your SIP domain (e.g. myprovider.com): ",
+ acc_domain = sys.stdin.readline()
+ if acc_domain == "\n":
+ return
+ acc_domain = acc_domain.replace("\n", "")
+
+ print "Your username (e.g. alice): ",
+ acc_username = sys.stdin.readline()
+ if acc_username == "\n":
+ return
+ acc_username = acc_username.replace("\n", "")
+
+ print "Your password (e.g. secret): ",
+ acc_passwd = sys.stdin.readline()
+ if acc_passwd == "\n":
+ return
+ acc_passwd = acc_passwd.replace("\n", "")
+
+ # Configure account configuration
+ acc_cfg = py_pjsua.acc_config_default()
+ acc_cfg.id = "sip:" + acc_username + "@" + acc_domain
+ acc_cfg.reg_uri = "sip:" + acc_domain
+
+ cred_info = py_pjsua.Pjsip_Cred_Info()
+ cred_info.realm = "*"
+ cred_info.scheme = "digest"
+ cred_info.username = acc_username
+ cred_info.data_type = 0
+ cred_info.data = acc_passwd
+
+ acc_cfg.cred_info.append(1)
+ acc_cfg.cred_info[0] = cred_info
+
+ # Add new SIP account
+ status, acc_id = py_pjsua.acc_add(acc_cfg, 1)
+ if status != 0:
+ py_pjsua.perror(THIS_FILE, "Error adding SIP account", status)
+ else:
+ g_acc_id = acc_id
+ write_log(3, "Account " + acc_cfg.id + " added")
+
+def add_player():
+ global g_wav_files
+ global g_wav_id
+ global g_wav_port
+
+ file_name = ""
+ status = -1
+ wav_id = 0
+
+ print "Enter the path of the file player(e.g. /tmp/audio.wav): ",
+ file_name = sys.stdin.readline()
+ if file_name == "\n":
+ return
+ file_name = file_name.replace("\n", "")
+ status, wav_id = py_pjsua.player_create(file_name, 0)
+ if status != 0:
+ py_pjsua.perror(THIS_FILE, "Error adding file player ", status)
+ else:
+ g_wav_files.append(file_name)
+ if g_wav_id == 0:
+ g_wav_id = wav_id
+ g_wav_port = py_pjsua.player_get_conf_port(wav_id)
+ write_log(3, "File player " + file_name + " added")
+
+def add_recorder():
+ global g_rec_file
+ global g_rec_id
+ global g_rec_port
+
+ file_name = ""
+ status = -1
+ rec_id = 0
+
+ print "Enter the path of the file recorder(e.g. /tmp/audio.wav): ",
+ file_name = sys.stdin.readline()
+ if file_name == "\n":
+ return
+ file_name = file_name.replace("\n", "")
+ status, rec_id = py_pjsua.recorder_create(file_name, 0, None, 0, 0)
+ if status != 0:
+ py_pjsua.perror(THIS_FILE, "Error adding file recorder ", status)
+ else:
+ g_rec_file = file_name
+ g_rec_id = rec_id
+ g_rec_port = py_pjsua.recorder_get_conf_port(rec_id)
+ write_log(3, "File recorder " + file_name + " added")
+
+def conf_list():
+ ports = None
+ print "Conference ports : "
+ ports = py_pjsua.enum_conf_ports()
+
+ for port in ports:
+ info = None
+ info = py_pjsua.conf_get_port_info(port)
+ txlist = ""
+ for listener in info.listeners:
+ txlist = txlist + "#" + `listener` + " "
+
+ print "Port #" + `info.slot_id` + "[" + `(info.clock_rate/1000)` + "KHz/" + `(info.samples_per_frame * 1000 / info.clock_rate)` + "ms] " + info.name + " transmitting to: " + txlist
+
+def connect_port():
+ src_port = 0
+ dst_port = 0
+
+ print "Connect src port # (empty to cancel): "
+ src_port = sys.stdin.readline()
+ if src_port == "\n":
+ return
+ src_port = src_port.replace("\n", "")
+ src_port = int(src_port)
+ print "To dst port # (empty to cancel): "
+ dst_port = sys.stdin.readline()
+ if dst_port == "\n":
+ return
+ dst_port = dst_port.replace("\n", "")
+ dst_port = int(dst_port)
+ status = py_pjsua.conf_connect(src_port, dst_port)
+ if status != 0:
+ py_pjsua.perror(THIS_FILE, "Error connecting port ", status)
+ else:
+ write_log(3, "Port connected from " + `src_port` + " to " + `dst_port`)
+
+def disconnect_port():
+ src_port = 0
+ dst_port = 0
+
+ print "Disconnect src port # (empty to cancel): "
+ src_port = sys.stdin.readline()
+ if src_port == "\n":
+ return
+ src_port = src_port.replace("\n", "")
+ src_port = int(src_port)
+ print "From dst port # (empty to cancel): "
+ dst_port = sys.stdin.readline()
+ if dst_port == "\n":
+ return
+ dst_port = dst_port.replace("\n", "")
+ dst_port = int(dst_port)
+ status = py_pjsua.conf_disconnect(src_port, dst_port)
+ if status != 0:
+ py_pjsua.perror(THIS_FILE, "Error disconnecting port ", status)
+ else:
+ write_log(3, "Port disconnected " + `src_port` + " from " + `dst_port`)
+
+def dump_call_quality():
+ global g_current_call
+
+ buf = ""
+ if g_current_call != -1:
+ buf = py_pjsua.call_dump(g_current_call, 1, 1024, " ")
+ write_log(3, "\n" + buf)
+ else:
+ write_log(3, "No current call")
+
+def xfer_call():
+ global g_current_call
+
+ if g_current_call == -1:
+
+ write_log(3, "No current call")
+
+ else:
+ call = g_current_call
+ ci = py_pjsua.call_get_info(g_current_call)
+ print "Transfering current call ["+ `g_current_call` + "] " + ci.remote_info
+ print "Enter sip url : "
+ url = sys.stdin.readline()
+ if url == "\n":
+ return
+ url = url.replace("\n", "")
+ if call != g_current_call:
+ print "Call has been disconnected"
+ return
+ msg_data = py_pjsua.msg_data_init()
+ status = py_pjsua.call_xfer(g_current_call, url, msg_data);
+ if status != 0:
+ py_pjsua.perror(THIS_FILE, "Error transfering call ", status)
+ else:
+ write_log(3, "Call transfered to " + url)
+
+def xfer_call_replaces():
+ if g_current_call == -1:
+ write_log(3, "No current call")
+ else:
+ call = g_current_call
+
+ ids = py_pjsua.enum_calls()
+ if len(ids) <= 1:
+ print "There are no other calls"
+ return
+
+ ci = py_pjsua.call_get_info(g_current_call)
+ print "Transfer call [" + `g_current_call` + "] " + ci.remote_info + " to one of the following:"
+ for i in range(0, len(ids)):
+ if ids[i] == call:
+ continue
+ call_info = py_pjsua.call_get_info(ids[i])
+ print `ids[i]` + " " + call_info.remote_info + " [" + call_info.state_text + "]"
+
+ print "Enter call number to be replaced : "
+ buf = sys.stdin.readline()
+ buf = buf.replace("\n","")
+ if buf == "":
+ return
+ dst_call = int(buf)
+
+ if call != g_current_call:
+ print "Call has been disconnected"
+ return
+
+ if dst_call == call:
+ print "Destination call number must not be the same as the call being transfered"
+ return
+
+ if dst_call >= py_pjsua.PJSUA_MAX_CALLS:
+ print "Invalid destination call number"
+ return
+
+ if py_pjsua.call_is_active(dst_call) == 0:
+ print "Invalid destination call number"
+ return
+
+ py_pjsua.call_xfer_replaces(call, dst_call, 0, None)
+
+#
+# Worker thread function.
+# Python doesn't like it when it's called from an alien thread
+# (pjsua's worker thread, in this case), so for Python we must
+# disable worker thread in pjsua and poll pjsua from Python instead.
+#
+def worker_thread_main(arg):
+ global C_QUIT
+ thread_desc = 0;
+ status = py_pjsua.thread_register("python worker", thread_desc)
+ if status != 0:
+ py_pjsua.perror(THIS_FILE, "Error registering thread", status)
+ else:
+ while C_QUIT == 0:
+ py_pjsua.handle_events(50)
+ print "Worker thread quitting.."
+ C_QUIT = 2
+
+
+# Start pjsua
+#
+def app_start():
+ # Done with initialization, start pjsua!!
+ #
+ status = py_pjsua.start()
+ if status != 0:
+ err_exit("Error starting pjsua!", status)
+
+ # Start worker thread
+ thr = thread.start_new(worker_thread_main, (0,))
+
+ print "PJSUA Started!!"
+
+
+# Print account and buddy list
+def print_acc_buddy_list():
+ global g_acc_id
+
+ acc_ids = py_pjsua.enum_accs()
+ print "Account list:"
+ for acc_id in acc_ids:
+ acc_info = py_pjsua.acc_get_info(acc_id)
+ if acc_info.has_registration == 0:
+ acc_status = acc_info.status_text
+ else:
+ acc_status = `acc_info.status` + "/" + acc_info.status_text + " (expires=" + `acc_info.expires` + ")"
+
+ if acc_id == g_acc_id:
+ print " *",
+ else:
+ print " ",
+
+ print "[" + `acc_id` + "] " + acc_info.acc_uri + ": " + acc_status
+ print " Presence status: ",
+ if acc_info.online_status != 0:
+ print "Online"
+ else:
+ print "Invisible"
+
+ if py_pjsua.get_buddy_count() > 0:
+ print ""
+ print "Buddy list:"
+ buddy_ids = py_pjsua.enum_buddies()
+ for buddy_id in buddy_ids:
+ bi = py_pjsua.buddy_get_info(buddy_id)
+ print " [" + `buddy_id` + "] " + bi.status_text + " " + bi.uri
+
+
+# Print application menu
+#
+def print_menu():
+ print ""
+ print ">>>"
+ print_acc_buddy_list()
+ print """
++============================================================================+
+| Call Commands : | Buddy, IM & Presence: | Account: |
+| | | |
+| m Make call | +b Add buddy | +a Add account |
+| a Answer current call | -b Delete buddy | -a Delete accnt |
+| h Hangup current call | | |
+| H Hold call | i Send instant message | rr register |
+| v re-inVite (release Hold) | s Subscribe presence | ru Unregister |
+| # Send DTMF string | u Unsubscribe presence | |
+| dq Dump curr. call quality | t ToGgle Online status | |
+| +--------------------------+------------------+
+| x Xfer call | Media Commands: | Status: |
+| X Xfer with Replaces | | |
+| | cl List ports | d Dump status |
+| | cc Connect port | dd Dump detail |
+| | cd Disconnect port | |
+| | +p Add file player | |
+|------------------------------+ +r Add file recorder | |
+| q Quit application | | |
++============================================================================+"""
+ print "You have " + `py_pjsua.call_get_count()` + " active call(s)"
+ print ">>>",
+
+# Menu
+#
+def app_menu():
+ global g_acc_id
+ global g_current_call
+
+ quit = 0
+ while quit == 0:
+ print_menu()
+ choice = sys.stdin.readline()
+
+ if choice[0] == "q":
+ quit = 1
+
+ elif choice[0] == "i":
+ # Sending IM
+ print "Send IM to SIP URL: ",
+ url = sys.stdin.readline()
+ if url == "\n":
+ continue
+
+ # Send typing indication
+ py_pjsua.im_typing(g_acc_id, url, 1, None)
+
+ print "The content: ",
+ message = sys.stdin.readline()
+ if message == "\n":
+ py_pjsua.im_typing(g_acc_id, url, 0, None)
+ continue
+
+ # Send the IM!
+ py_pjsua.im_send(g_acc_id, url, None, message, None, 0)
+
+ elif choice[0] == "m":
+ # Make call
+ print "Using account ", g_acc_id
+ print "Make call to SIP URL: ",
+ url = sys.stdin.readline()
+ url = url.replace("\n", "")
+ if url == "":
+ continue
+
+ # Initiate the call!
+ status, call_id = py_pjsua.call_make_call(g_acc_id, url, 0, 0, None)
+
+ if status != 0:
+ py_pjsua.perror(THIS_FILE, "Error making call", status)
+ else:
+ g_current_call = call_id
+
+ elif choice[0] == "+" and choice[1] == "b":
+ # Add new buddy
+ bc = py_pjsua.Buddy_Config()
+ print "Buddy URL: ",
+ bc.uri = sys.stdin.readline()
+ if bc.uri == "\n":
+ continue
+
+ bc.uri = bc.uri.replace("\n", "")
+ bc.subscribe = 1
+ status, buddy_id = py_pjsua.buddy_add(bc)
+ if status != 0:
+ py_pjsua.perror(THIS_FILE, "Error adding buddy", status)
+ elif choice[0] == "-" and choice[1] == "b":
+ print "Enter buddy ID to delete : "
+ buf = sys.stdin.readline()
+ buf = buf.replace("\n","")
+ if buf == "":
+ continue
+ i = int(buf)
+ if py_pjsua.buddy_is_valid(i) == 0:
+ print "Invalid buddy id " + `i`
+ else:
+ py_pjsua.buddy_del(i)
+ print "Buddy " + `i` + " deleted"
+ elif choice[0] == "+" and choice[1] == "a":
+ # Add account
+ add_account()
+ elif choice[0] == "-" and choice[1] == "a":
+ print "Enter account ID to delete : "
+ buf = sys.stdin.readline()
+ buf = buf.replace("\n","")
+ if buf == "":
+ continue
+ i = int(buf)
+
+ if py_pjsua.acc_is_valid(i) == 0:
+ print "Invalid account id " + `i`
+ else:
+ py_pjsua.acc_del(i)
+ print "Account " + `i` + " deleted"
+
+ elif choice[0] == "+" and choice[1] == "p":
+ add_player()
+ elif choice[0] == "+" and choice[1] == "r":
+ add_recorder()
+ elif choice[0] == "c" and choice[1] == "l":
+ conf_list()
+ elif choice[0] == "c" and choice[1] == "c":
+ connect_port()
+ elif choice[0] == "c" and choice[1] == "d":
+ disconnect_port()
+ elif choice[0] == "d" and choice[1] == "q":
+ dump_call_quality()
+ elif choice[0] == "x":
+ xfer_call()
+ elif choice[0] == "X":
+ xfer_call_replaces()
+ elif choice[0] == "h":
+ if g_current_call != py_pjsua.PJSUA_INVALID_ID:
+ py_pjsua.call_hangup(g_current_call, 603, None, None)
+ else:
+ print "No current call"
+ elif choice[0] == "H":
+ if g_current_call != py_pjsua.PJSUA_INVALID_ID:
+ py_pjsua.call_set_hold(g_current_call, None)
+
+ else:
+ print "No current call"
+ elif choice[0] == "v":
+ if g_current_call != py_pjsua.PJSUA_INVALID_ID:
+
+ py_pjsua.call_reinvite(g_current_call, 1, None);
+
+ else:
+ print "No current call"
+ elif choice[0] == "#":
+ if g_current_call == py_pjsua.PJSUA_INVALID_ID:
+ print "No current call"
+ elif py_pjsua.call_has_media(g_current_call) == 0:
+ print "Media is not established yet!"
+ else:
+ call = g_current_call
+ print "DTMF strings to send (0-9*#A-B)"
+ buf = sys.stdin.readline()
+ buf = buf.replace("\n", "")
+ if buf == "":
+ continue
+ if call != g_current_call:
+ print "Call has been disconnected"
+ continue
+ status = py_pjsua.call_dial_dtmf(g_current_call, buf)
+ if status != 0:
+ py_pjsua.perror(THIS_FILE, "Unable to send DTMF", status);
+ else:
+ print "DTMF digits enqueued for transmission"
+ elif choice[0] == "s":
+ print "Subscribe presence of (buddy id) : "
+ buf = sys.stdin.readline()
+ buf = buf.replace("\n","")
+ if buf == "":
+ continue
+ i = int(buf)
+ py_pjsua.buddy_subscribe_pres(i, 1)
+ elif choice[0] == "u":
+ print "Unsubscribe presence of (buddy id) : "
+ buf = sys.stdin.readline()
+ buf = buf.replace("\n","")
+ if buf == "":
+ continue
+ i = int(buf)
+ py_pjsua.buddy_subscribe_pres(i, 0)
+ elif choice[0] == "t":
+ acc_info = py_pjsua.acc_get_info(g_acc_id)
+ if acc_info.online_status == 0:
+ acc_info.online_status = 1
+ else:
+ acc_info.online_status = 0
+ py_pjsua.acc_set_online_status(g_acc_id, acc_info.online_status)
+ st = ""
+ if acc_info.online_status == 0:
+ st = "offline"
+ else:
+ st = "online"
+ print "Setting " + acc_info.acc_uri + " online status to " + st
+ elif choice[0] == "r":
+ if choice[1] == "r":
+ py_pjsua.acc_set_registration(g_acc_id, 1)
+ elif choice[1] == "u":
+ py_pjsua.acc_set_registration(g_acc_id, 0)
+ elif choice[0] == "d":
+ py_pjsua.dump(choice[1] == "d")
+ elif choice[0] == "a":
+ if g_current_call != py_pjsua.PJSUA_INVALID_ID:
+
+ py_pjsua.call_answer(g_current_call, 200, None, None)
+ else:
+ print "No current call"
+
+
+#
+# main
+#
+app_init()
+app_start()
+app_menu()
+
+#
+# Done, quitting..
+#
+print "PJSUA shutting down.."
+C_QUIT = 1
+# Give the worker thread chance to quit itself
+while C_QUIT != 2:
+ py_pjsua.handle_events(50)
+
+print "PJSUA destroying.."
+py_pjsua.destroy()
+
diff --git a/pjsip-apps/src/py_pjsua/py_pjsua.c b/pjsip-apps/src/py_pjsua/py_pjsua.c
new file mode 100644
index 0000000..9d22133
--- /dev/null
+++ b/pjsip-apps/src/py_pjsua/py_pjsua.c
@@ -0,0 +1,5872 @@
+/* $Id: py_pjsua.c 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include "py_pjsua.h"
+
+#define THIS_FILE "main.c"
+#define POOL_SIZE 4000
+#define SND_DEV_NUM 64
+#define SND_NAME_LEN 64
+
+/* LIB BASE */
+
+static PyObject* obj_log_cb;
+static long thread_id;
+
+#define ENTER_PYTHON() PyGILState_STATE state = PyGILState_Ensure()
+#define LEAVE_PYTHON() PyGILState_Release(state)
+
+/*
+ * cb_log_cb
+ * declares method for reconfiguring logging process for callback struct
+ */
+static void cb_log_cb(int level, const char *data, int len)
+{
+
+ /* Ignore if this callback is called from alien thread context,
+ * or otherwise it will crash Python.
+ */
+ if (pj_thread_local_get(thread_id) == 0)
+ return;
+
+ if (PyCallable_Check(obj_log_cb))
+ {
+ ENTER_PYTHON();
+
+ PyObject_CallFunctionObjArgs(
+ obj_log_cb, Py_BuildValue("i",level),
+ PyString_FromString(data), Py_BuildValue("i",len), NULL
+ );
+
+ LEAVE_PYTHON();
+ }
+}
+
+
+
+/*
+ * The global callback object.
+ */
+static PyObj_pjsua_callback * g_obj_callback;
+
+
+/*
+ * cb_on_call_state
+ * declares method on_call_state for callback struct
+ */
+static void cb_on_call_state(pjsua_call_id call_id, pjsip_event *e)
+{
+ if (PyCallable_Check(g_obj_callback->on_call_state))
+ {
+ PyObj_pjsip_event * obj;
+
+ ENTER_PYTHON();
+
+ obj = (PyObj_pjsip_event *)PyType_GenericNew(&PyTyp_pjsip_event,
+ NULL, NULL);
+
+ obj->event = e;
+
+ PyObject_CallFunctionObjArgs(
+ g_obj_callback->on_call_state,
+ Py_BuildValue("i",call_id),
+ obj,
+ NULL
+ );
+
+ LEAVE_PYTHON();
+ }
+}
+
+
+/*
+ * cb_on_incoming_call
+ * declares method on_incoming_call for callback struct
+ */
+static void cb_on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id,
+ pjsip_rx_data *rdata)
+{
+ if (PyCallable_Check(g_obj_callback->on_incoming_call))
+ {
+ PyObj_pjsip_rx_data * obj;
+
+ ENTER_PYTHON();
+
+ obj = (PyObj_pjsip_rx_data *)PyType_GenericNew(&PyTyp_pjsip_rx_data,
+ NULL, NULL);
+ obj->rdata = rdata;
+
+ PyObject_CallFunctionObjArgs(
+ g_obj_callback->on_incoming_call,
+ Py_BuildValue("i",acc_id),
+ Py_BuildValue("i",call_id),
+ obj,
+ NULL
+ );
+
+ LEAVE_PYTHON();
+ }
+}
+
+
+/*
+ * cb_on_call_media_state
+ * declares method on_call_media_state for callback struct
+ */
+static void cb_on_call_media_state(pjsua_call_id call_id)
+{
+ if (PyCallable_Check(g_obj_callback->on_call_media_state))
+ {
+ ENTER_PYTHON();
+
+ PyObject_CallFunction(
+ g_obj_callback->on_call_media_state,
+ "i",
+ call_id,
+ NULL
+ );
+
+ LEAVE_PYTHON();
+ }
+}
+
+
+/*
+ * cb_on_dtmf_digit()
+ * Callback from PJSUA-LIB on receiving DTMF digit
+ */
+static void cb_on_dtmf_digit(pjsua_call_id call_id, int digit)
+{
+ if (PyCallable_Check(g_obj_callback->on_dtmf_digit))
+ {
+ char digit_str[10];
+
+ ENTER_PYTHON();
+
+ pj_ansi_snprintf(digit_str, sizeof(digit_str), "%c", digit);
+
+ PyObject_CallFunctionObjArgs(
+ g_obj_callback->on_dtmf_digit,
+ Py_BuildValue("i",call_id),
+ PyString_FromString(digit_str),
+ NULL
+ );
+
+ LEAVE_PYTHON();
+ }
+}
+
+
+/*
+ * Notify application on call being transfered.
+ * !modified @061206
+ */
+static void cb_on_call_transfer_request(pjsua_call_id call_id,
+ const pj_str_t *dst,
+ pjsip_status_code *code)
+{
+ if (PyCallable_Check(g_obj_callback->on_call_transfer_request))
+ {
+ PyObject * ret;
+ int cd;
+
+ ENTER_PYTHON();
+
+ ret = PyObject_CallFunctionObjArgs(
+ g_obj_callback->on_call_transfer_request,
+ Py_BuildValue("i",call_id),
+ PyString_FromStringAndSize(dst->ptr, dst->slen),
+ Py_BuildValue("i",*code),
+ NULL
+ );
+ if (ret != NULL) {
+ if (ret != Py_None) {
+ if (PyArg_Parse(ret,"i",&cd)) {
+ *code = cd;
+ }
+ }
+ }
+
+ LEAVE_PYTHON();
+ }
+}
+
+
+/*
+ * Notify application of the status of previously sent call
+ * transfer request. Application can monitor the status of the
+ * call transfer request, for example to decide whether to
+ * terminate existing call.
+ * !modified @061206
+ */
+static void cb_on_call_transfer_status( pjsua_call_id call_id,
+ int status_code,
+ const pj_str_t *status_text,
+ pj_bool_t final,
+ pj_bool_t *p_cont)
+{
+ if (PyCallable_Check(g_obj_callback->on_call_transfer_status))
+ {
+ PyObject * ret;
+ int cnt;
+
+ ENTER_PYTHON();
+
+ ret = PyObject_CallFunctionObjArgs(
+ g_obj_callback->on_call_transfer_status,
+ Py_BuildValue("i",call_id),
+ Py_BuildValue("i",status_code),
+ PyString_FromStringAndSize(status_text->ptr, status_text->slen),
+ Py_BuildValue("i",final),
+ Py_BuildValue("i",*p_cont),
+ NULL
+ );
+ if (ret != NULL) {
+ if (ret != Py_None) {
+ if (PyArg_Parse(ret,"i",&cnt)) {
+ *p_cont = cnt;
+ }
+ }
+ }
+
+ LEAVE_PYTHON();
+ }
+}
+
+
+/*
+ * Notify application about incoming INVITE with Replaces header.
+ * Application may reject the request by setting non-2xx code.
+ * !modified @061206
+ */
+static void cb_on_call_replace_request( pjsua_call_id call_id,
+ pjsip_rx_data *rdata,
+ int *st_code,
+ pj_str_t *st_text)
+{
+ if (PyCallable_Check(g_obj_callback->on_call_replace_request))
+ {
+ PyObject * ret;
+ PyObject * txt;
+ int cd;
+ PyObj_pjsip_rx_data * obj;
+
+ ENTER_PYTHON();
+
+ obj = (PyObj_pjsip_rx_data *)PyType_GenericNew(&PyTyp_pjsip_rx_data,
+ NULL, NULL);
+ obj->rdata = rdata;
+
+ ret = PyObject_CallFunctionObjArgs(
+ g_obj_callback->on_call_replace_request,
+ Py_BuildValue("i",call_id),
+ obj,
+ Py_BuildValue("i",*st_code),
+ PyString_FromStringAndSize(st_text->ptr, st_text->slen),
+ NULL
+ );
+ if (ret != NULL) {
+ if (ret != Py_None) {
+ if (PyArg_ParseTuple(ret,"iO",&cd, &txt)) {
+ *st_code = cd;
+ st_text->ptr = PyString_AsString(txt);
+ st_text->slen = strlen(PyString_AsString(txt));
+ }
+ }
+ }
+
+ LEAVE_PYTHON();
+ }
+}
+
+
+/*
+ * Notify application that an existing call has been replaced with
+ * a new call. This happens when PJSUA-API receives incoming INVITE
+ * request with Replaces header.
+ */
+static void cb_on_call_replaced(pjsua_call_id old_call_id,
+ pjsua_call_id new_call_id)
+{
+ if (PyCallable_Check(g_obj_callback->on_call_replaced))
+ {
+ ENTER_PYTHON();
+
+ PyObject_CallFunctionObjArgs(
+ g_obj_callback->on_call_replaced,
+ Py_BuildValue("i",old_call_id),
+ Py_BuildValue("i",new_call_id),
+ NULL
+ );
+
+ LEAVE_PYTHON();
+ }
+}
+
+
+/*
+ * cb_on_reg_state
+ * declares method on_reg_state for callback struct
+ */
+static void cb_on_reg_state(pjsua_acc_id acc_id)
+{
+ if (PyCallable_Check(g_obj_callback->on_reg_state))
+ {
+ ENTER_PYTHON();
+
+ PyObject_CallFunction(
+ g_obj_callback->on_reg_state,
+ "i",
+ acc_id,
+ NULL
+ );
+
+ LEAVE_PYTHON();
+ }
+}
+
+
+/*
+ * cb_on_buddy_state
+ * declares method on_buddy state for callback struct
+ */
+static void cb_on_buddy_state(pjsua_buddy_id buddy_id)
+{
+ if (PyCallable_Check(g_obj_callback->on_buddy_state))
+ {
+ ENTER_PYTHON();
+
+ PyObject_CallFunction(
+ g_obj_callback->on_buddy_state,
+ "i",
+ buddy_id,
+ NULL
+ );
+
+ LEAVE_PYTHON();
+ }
+}
+
+/*
+ * cb_on_pager
+ * declares method on_pager for callback struct
+ */
+static void cb_on_pager(pjsua_call_id call_id, const pj_str_t *from,
+ const pj_str_t *to, const pj_str_t *contact,
+ const pj_str_t *mime_type, const pj_str_t *body)
+{
+ if (PyCallable_Check(g_obj_callback->on_pager))
+ {
+ ENTER_PYTHON();
+
+ PyObject_CallFunctionObjArgs(
+ g_obj_callback->on_pager,Py_BuildValue("i",call_id),
+ PyString_FromStringAndSize(from->ptr, from->slen),
+ PyString_FromStringAndSize(to->ptr, to->slen),
+ PyString_FromStringAndSize(contact->ptr, contact->slen),
+ PyString_FromStringAndSize(mime_type->ptr, mime_type->slen),
+ PyString_FromStringAndSize(body->ptr, body->slen),
+ NULL
+ );
+
+ LEAVE_PYTHON();
+ }
+}
+
+
+/*
+ * cb_on_pager_status
+ * declares method on_pager_status for callback struct
+ */
+static void cb_on_pager_status(pjsua_call_id call_id, const pj_str_t *to,
+ const pj_str_t *body, void *user_data,
+ pjsip_status_code status,
+ const pj_str_t *reason)
+{
+ if (PyCallable_Check(g_obj_callback->on_pager))
+ {
+ PyObject * obj_user_data;
+
+ ENTER_PYTHON();
+
+ obj_user_data = Py_BuildValue("i", user_data);
+
+ PyObject_CallFunctionObjArgs(
+ g_obj_callback->on_pager_status,
+ Py_BuildValue("i",call_id),
+ PyString_FromStringAndSize(to->ptr, to->slen),
+ PyString_FromStringAndSize(body->ptr, body->slen),
+ obj_user_data,
+ Py_BuildValue("i",status),
+ PyString_FromStringAndSize(reason->ptr,reason->slen),
+ NULL
+ );
+
+ LEAVE_PYTHON();
+ }
+}
+
+
+/*
+ * cb_on_typing
+ * declares method on_typing for callback struct
+ */
+static void cb_on_typing(pjsua_call_id call_id, const pj_str_t *from,
+ const pj_str_t *to, const pj_str_t *contact,
+ pj_bool_t is_typing)
+{
+ if (PyCallable_Check(g_obj_callback->on_typing))
+ {
+ ENTER_PYTHON();
+
+ PyObject_CallFunctionObjArgs(
+ g_obj_callback->on_typing,Py_BuildValue("i",call_id),
+ PyString_FromStringAndSize(from->ptr, from->slen),
+ PyString_FromStringAndSize(to->ptr, to->slen),
+ PyString_FromStringAndSize(contact->ptr, contact->slen),
+ Py_BuildValue("i",is_typing),
+ NULL
+ );
+
+ LEAVE_PYTHON();
+ }
+}
+
+
+
+/*
+ * translate_hdr
+ * internal function
+ * translate from hdr_list to pjsip_generic_string_hdr
+ */
+void translate_hdr(pj_pool_t *pool, pjsip_hdr *hdr, PyObject *py_hdr_list)
+{
+ pj_list_init(hdr);
+
+ if (PyList_Check(py_hdr_list)) {
+ int i;
+
+ for (i = 0; i < PyList_Size(py_hdr_list); i++)
+ {
+ pj_str_t hname, hvalue;
+ pjsip_generic_string_hdr * new_hdr;
+ PyObject * tuple = PyList_GetItem(py_hdr_list, i);
+
+ if (PyTuple_Check(tuple))
+ {
+ hname.ptr = PyString_AsString(PyTuple_GetItem(tuple,0));
+ hname.slen = strlen(PyString_AsString
+ (PyTuple_GetItem(tuple,0)));
+ hvalue.ptr = PyString_AsString(PyTuple_GetItem(tuple,1));
+ hvalue.slen = strlen(PyString_AsString
+ (PyTuple_GetItem(tuple,1)));
+ } else {
+ hname.ptr = "";
+ hname.slen = 0;
+ hvalue.ptr = "";
+ hvalue.slen = 0;
+ }
+ new_hdr = pjsip_generic_string_hdr_create(pool, &hname, &hvalue);
+ pj_list_push_back((pj_list_type *)hdr, (pj_list_type *)new_hdr);
+ }
+ }
+}
+
+/*
+ * translate_hdr_rev
+ * internal function
+ * translate from pjsip_generic_string_hdr to hdr_list
+ */
+
+void translate_hdr_rev(pjsip_generic_string_hdr *hdr, PyObject *py_hdr_list)
+{
+ int i;
+ int len;
+ pjsip_generic_string_hdr * p_hdr;
+
+ len = pj_list_size(hdr);
+
+ if (len > 0)
+ {
+ p_hdr = hdr;
+ Py_XDECREF(py_hdr_list);
+ py_hdr_list = PyList_New(len);
+
+ for (i = 0; i < len && p_hdr != NULL; i++)
+ {
+ PyObject * tuple;
+ PyObject * str;
+
+ tuple = PyTuple_New(2);
+
+ str = PyString_FromStringAndSize(p_hdr->name.ptr, p_hdr->name.slen);
+ PyTuple_SetItem(tuple, 0, str);
+ str = PyString_FromStringAndSize
+ (hdr->hvalue.ptr, p_hdr->hvalue.slen);
+ PyTuple_SetItem(tuple, 1, str);
+ PyList_SetItem(py_hdr_list, i, tuple);
+ p_hdr = p_hdr->next;
+ }
+ }
+
+
+}
+
+/*
+ * py_pjsua_thread_register
+ * !added @ 061206
+ */
+static PyObject *py_pjsua_thread_register(PyObject *pSelf, PyObject *pArgs)
+{
+
+ pj_status_t status;
+ const char *name;
+ PyObject *py_desc;
+ pj_thread_t *thread;
+ void *thread_desc;
+#if 0
+ int size;
+ int i;
+ int *td;
+#endif
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "sO", &name, &py_desc))
+ {
+ return NULL;
+ }
+#if 0
+ size = PyList_Size(py_desc);
+ td = (int *)malloc(size * sizeof(int));
+ for (i = 0; i < size; i++)
+ {
+ if (!PyArg_Parse(PyList_GetItem(py_desc,i),"i", td[i]))
+ {
+ return NULL;
+ }
+ }
+ thread_desc = td;
+#else
+ thread_desc = malloc(sizeof(pj_thread_desc));
+#endif
+ status = pj_thread_register(name, thread_desc, &thread);
+
+ if (status == PJ_SUCCESS)
+ status = pj_thread_local_set(thread_id, (void*)1);
+ return Py_BuildValue("i",status);
+}
+
+/*
+ * py_pjsua_logging_config_default
+ * !modified @ 051206
+ */
+static PyObject *py_pjsua_logging_config_default(PyObject *pSelf,
+ PyObject *pArgs)
+{
+ PyObj_pjsua_logging_config *obj;
+ pjsua_logging_config cfg;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, ""))
+ {
+ return NULL;
+ }
+
+ pjsua_logging_config_default(&cfg);
+ obj = (PyObj_pjsua_logging_config *) PyObj_pjsua_logging_config_new
+ (&PyTyp_pjsua_logging_config,NULL,NULL);
+ PyObj_pjsua_logging_config_import(obj, &cfg);
+
+ return (PyObject *)obj;
+}
+
+
+/*
+ * py_pjsua_config_default
+ * !modified @ 051206
+ */
+static PyObject *py_pjsua_config_default(PyObject *pSelf, PyObject *pArgs)
+{
+ PyObj_pjsua_config *obj;
+ pjsua_config cfg;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, ""))
+ {
+ return NULL;
+ }
+ pjsua_config_default(&cfg);
+ obj = (PyObj_pjsua_config *) PyObj_pjsua_config_new(&PyTyp_pjsua_config, NULL, NULL);
+ PyObj_pjsua_config_import(obj, &cfg);
+
+ return (PyObject *)obj;
+}
+
+
+/*
+ * py_pjsua_media_config_default
+ * !modified @ 051206
+ */
+static PyObject * py_pjsua_media_config_default(PyObject *pSelf,
+ PyObject *pArgs)
+{
+ PyObj_pjsua_media_config *obj;
+ pjsua_media_config cfg;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, ""))
+ {
+ return NULL;
+ }
+ pjsua_media_config_default(&cfg);
+ obj = (PyObj_pjsua_media_config *)
+ PyType_GenericNew(&PyTyp_pjsua_media_config, NULL, NULL);
+ PyObj_pjsua_media_config_import(obj, &cfg);
+ return (PyObject *)obj;
+}
+
+
+/*
+ * py_pjsua_msg_data_init
+ * !modified @ 051206
+ */
+static PyObject *py_pjsua_msg_data_init(PyObject *pSelf, PyObject *pArgs)
+{
+ PyObj_pjsua_msg_data *obj;
+ pjsua_msg_data msg;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, ""))
+ {
+ return NULL;
+ }
+ pjsua_msg_data_init(&msg);
+ obj = (PyObj_pjsua_msg_data *)PyObj_pjsua_msg_data_new(&PyTyp_pjsua_msg_data, NULL, NULL);
+ Py_XDECREF(obj->content_type);
+ obj->content_type = PyString_FromStringAndSize(
+ msg.content_type.ptr, msg.content_type.slen
+ );
+ Py_XDECREF(obj->msg_body);
+ obj->msg_body = PyString_FromStringAndSize(
+ msg.msg_body.ptr, msg.msg_body.slen
+ );
+
+ translate_hdr_rev((pjsip_generic_string_hdr *)&msg.hdr_list,obj->hdr_list);
+
+ return (PyObject *)obj;
+}
+
+
+/*
+ * py_pjsua_reconfigure_logging
+ */
+static PyObject *py_pjsua_reconfigure_logging(PyObject *pSelf, PyObject *pArgs)
+{
+ PyObject * logObj;
+ PyObj_pjsua_logging_config *log;
+ pjsua_logging_config cfg;
+ pj_status_t status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "O", &logObj))
+ {
+ return NULL;
+ }
+ if (logObj != Py_None)
+ {
+ log = (PyObj_pjsua_logging_config *)logObj;
+ cfg.msg_logging = log->msg_logging;
+ cfg.level = log->level;
+ cfg.console_level = log->console_level;
+ cfg.decor = log->decor;
+ cfg.log_filename.ptr = PyString_AsString(log->log_filename);
+ cfg.log_filename.slen = strlen(cfg.log_filename.ptr);
+ Py_XDECREF(obj_log_cb);
+ obj_log_cb = log->cb;
+ Py_INCREF(obj_log_cb);
+ cfg.cb = &cb_log_cb;
+ status = pjsua_reconfigure_logging(&cfg);
+ } else {
+ status = pjsua_reconfigure_logging(NULL);
+ }
+ return Py_BuildValue("i",status);
+}
+
+
+/*
+ * py_pjsua_pool_create
+ */
+static PyObject *py_pjsua_pool_create(PyObject *pSelf, PyObject *pArgs)
+{
+ pj_size_t init_size;
+ pj_size_t increment;
+ const char * name;
+ pj_pool_t *p;
+ PyObj_pj_pool *pool;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "sII", &name, &init_size, &increment))
+ {
+ return NULL;
+ }
+
+ p = pjsua_pool_create(name, init_size, increment);
+ pool = (PyObj_pj_pool *)PyType_GenericNew(&PyTyp_pj_pool_t, NULL, NULL);
+ pool->pool = p;
+ return (PyObject *)pool;
+
+}
+
+
+/*
+ * py_pjsua_get_pjsip_endpt
+ */
+static PyObject *py_pjsua_get_pjsip_endpt(PyObject *pSelf, PyObject *pArgs)
+{
+ PyObj_pjsip_endpoint *endpt;
+ pjsip_endpoint *e;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, ""))
+ {
+ return NULL;
+ }
+ e = pjsua_get_pjsip_endpt();
+ endpt = (PyObj_pjsip_endpoint *)PyType_GenericNew(
+ &PyTyp_pjsip_endpoint, NULL, NULL
+ );
+ endpt->endpt = e;
+ return (PyObject *)endpt;
+}
+
+
+/*
+ * py_pjsua_get_pjmedia_endpt
+ */
+static PyObject *py_pjsua_get_pjmedia_endpt(PyObject *pSelf, PyObject *pArgs)
+{
+ PyObj_pjmedia_endpt *endpt;
+ pjmedia_endpt *e;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, ""))
+ {
+ return NULL;
+ }
+ e = pjsua_get_pjmedia_endpt();
+ endpt = (PyObj_pjmedia_endpt *)PyType_GenericNew(
+ &PyTyp_pjmedia_endpt, NULL, NULL
+ );
+ endpt->endpt = e;
+ return (PyObject *)endpt;
+}
+
+
+/*
+ * py_pjsua_get_pool_factory
+ */
+static PyObject *py_pjsua_get_pool_factory(PyObject *pSelf, PyObject *pArgs)
+{
+ PyObj_pj_pool_factory *pool;
+ pj_pool_factory *p;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, ""))
+ {
+ return NULL;
+ }
+ p = pjsua_get_pool_factory();
+ pool = (PyObj_pj_pool_factory *)PyType_GenericNew(
+ &PyTyp_pj_pool_factory, NULL, NULL
+ );
+ pool->pool_fact = p;
+ return (PyObject *)pool;
+}
+
+
+/*
+ * py_pjsua_perror
+ */
+static PyObject *py_pjsua_perror(PyObject *pSelf, PyObject *pArgs)
+{
+ const char *sender;
+ const char *title;
+ pj_status_t status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "ssi", &sender, &title, &status))
+ {
+ return NULL;
+ }
+
+ pjsua_perror(sender, title, status);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+
+/*
+ * py_pjsua_create
+ */
+static PyObject *py_pjsua_create(PyObject *pSelf, PyObject *pArgs)
+{
+ pj_status_t status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, ""))
+ {
+ return NULL;
+ }
+ status = pjsua_create();
+
+ if (status == PJ_SUCCESS)
+ {
+ status = pj_thread_local_alloc(&thread_id);
+ if (status == PJ_SUCCESS)
+ status = pj_thread_local_set(thread_id, (void*)1);
+ }
+
+ return Py_BuildValue("i",status);
+}
+
+
+/*
+ * py_pjsua_init
+ */
+static PyObject *py_pjsua_init(PyObject *pSelf, PyObject *pArgs)
+{
+ pj_status_t status;
+ PyObject *o_ua_cfg, *o_log_cfg, *o_media_cfg;
+ pjsua_config cfg_ua, *p_cfg_ua;
+ pjsua_logging_config cfg_log, *p_cfg_log;
+ pjsua_media_config cfg_media, *p_cfg_media;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "OOO", &o_ua_cfg, &o_log_cfg, &o_media_cfg))
+ {
+ return NULL;
+ }
+
+ pjsua_config_default(&cfg_ua);
+ pjsua_logging_config_default(&cfg_log);
+ pjsua_media_config_default(&cfg_media);
+
+ if (o_ua_cfg != Py_None)
+ {
+ PyObj_pjsua_config *obj_ua_cfg = (PyObj_pjsua_config*)o_ua_cfg;
+
+ PyObj_pjsua_config_export(&cfg_ua, obj_ua_cfg);
+
+ g_obj_callback = obj_ua_cfg->cb;
+ Py_INCREF(g_obj_callback);
+
+ cfg_ua.cb.on_call_state = &cb_on_call_state;
+ cfg_ua.cb.on_incoming_call = &cb_on_incoming_call;
+ cfg_ua.cb.on_call_media_state = &cb_on_call_media_state;
+ cfg_ua.cb.on_dtmf_digit = &cb_on_dtmf_digit;
+ cfg_ua.cb.on_call_transfer_request = &cb_on_call_transfer_request;
+ cfg_ua.cb.on_call_transfer_status = &cb_on_call_transfer_status;
+ cfg_ua.cb.on_call_replace_request = &cb_on_call_replace_request;
+ cfg_ua.cb.on_call_replaced = &cb_on_call_replaced;
+ cfg_ua.cb.on_reg_state = &cb_on_reg_state;
+ cfg_ua.cb.on_buddy_state = &cb_on_buddy_state;
+ cfg_ua.cb.on_pager = &cb_on_pager;
+ cfg_ua.cb.on_pager_status = &cb_on_pager_status;
+ cfg_ua.cb.on_typing = &cb_on_typing;
+
+ p_cfg_ua = &cfg_ua;
+
+ } else {
+ p_cfg_ua = NULL;
+ }
+
+ if (o_log_cfg != Py_None)
+ {
+ PyObj_pjsua_logging_config * obj_log;
+
+ obj_log = (PyObj_pjsua_logging_config *)o_log_cfg;
+
+ PyObj_pjsua_logging_config_export(&cfg_log, obj_log);
+
+ Py_XDECREF(obj_log_cb);
+ obj_log_cb = obj_log->cb;
+ Py_INCREF(obj_log_cb);
+
+ cfg_log.cb = &cb_log_cb;
+ p_cfg_log = &cfg_log;
+
+ } else {
+ p_cfg_log = NULL;
+ }
+
+ if (o_media_cfg != Py_None)
+ {
+ PyObj_pjsua_media_config_export(&cfg_media,
+ (PyObj_pjsua_media_config*)o_media_cfg);
+ p_cfg_media = &cfg_media;
+
+ } else {
+ p_cfg_media = NULL;
+ }
+
+ status = pjsua_init(p_cfg_ua, p_cfg_log, p_cfg_media);
+ return Py_BuildValue("i",status);
+}
+
+
+/*
+ * py_pjsua_start
+ */
+static PyObject *py_pjsua_start(PyObject *pSelf, PyObject *pArgs)
+{
+ pj_status_t status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, ""))
+ {
+ return NULL;
+ }
+ status = pjsua_start();
+
+ return Py_BuildValue("i",status);
+}
+
+
+/*
+ * py_pjsua_destroy
+ */
+static PyObject *py_pjsua_destroy(PyObject *pSelf, PyObject *pArgs)
+{
+ pj_status_t status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, ""))
+ {
+ return NULL;
+ }
+ status = pjsua_destroy();
+
+ return Py_BuildValue("i",status);
+}
+
+
+/*
+ * py_pjsua_handle_events
+ */
+static PyObject *py_pjsua_handle_events(PyObject *pSelf, PyObject *pArgs)
+{
+ int ret;
+ unsigned msec;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &msec))
+ {
+ return NULL;
+ }
+
+ /* Since handle_events() will block, we must wrap it with ALLOW_THREADS
+ * construct, or otherwise many Python blocking functions (such as
+ * time.sleep(), readline(), etc.) may hang/block indefinitely.
+ * See http://www.python.org/doc/current/api/threads.html for more info.
+ */
+ Py_BEGIN_ALLOW_THREADS
+ ret = pjsua_handle_events(msec);
+ Py_END_ALLOW_THREADS
+
+ return Py_BuildValue("i",ret);
+}
+
+
+/*
+ * py_pjsua_verify_sip_url
+ */
+static PyObject *py_pjsua_verify_sip_url(PyObject *pSelf, PyObject *pArgs)
+{
+ pj_status_t status;
+ const char *url;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "s", &url))
+ {
+ return NULL;
+ }
+ status = pjsua_verify_sip_url(url);
+
+ return Py_BuildValue("i",status);
+}
+
+
+/*
+ * function doc
+ */
+
+static char pjsua_thread_register_doc[] =
+ "int py_pjsua.thread_register(string name, int[] desc)";
+static char pjsua_perror_doc[] =
+ "void py_pjsua.perror (string sender, string title, int status) "
+ "Display error message for the specified error code. Parameters: "
+ "sender: The log sender field; "
+ "title: Message title for the error; "
+ "status: Status code.";
+
+static char pjsua_create_doc[] =
+ "int py_pjsua.create (void) "
+ "Instantiate pjsua application. Application "
+ "must call this function before calling any other functions, to make sure "
+ "that the underlying libraries are properly initialized. Once this "
+ "function has returned success, application must call pjsua_destroy() "
+ "before quitting.";
+
+static char pjsua_init_doc[] =
+ "int py_pjsua.init (py_pjsua.Config obj_ua_cfg, "
+ "py_pjsua.Logging_Config log_cfg, py_pjsua.Media_Config media_cfg) "
+ "Initialize pjsua with the specified settings. All the settings are "
+ "optional, and the default values will be used when the config is not "
+ "specified. Parameters: "
+ "obj_ua_cfg : User agent configuration; "
+ "log_cfg : Optional logging configuration; "
+ "media_cfg : Optional media configuration.";
+
+static char pjsua_start_doc[] =
+ "int py_pjsua.start (void) "
+ "Application is recommended to call this function after all "
+ "initialization is done, so that the library can do additional checking "
+ "set up additional";
+
+static char pjsua_destroy_doc[] =
+ "int py_pjsua.destroy (void) "
+ "Destroy pjsua This function must be called once PJSUA is created. To "
+ "make it easier for application, application may call this function "
+ "several times with no danger.";
+
+static char pjsua_handle_events_doc[] =
+ "int py_pjsua.handle_events (int msec_timeout) "
+ "Poll pjsua for events, and if necessary block the caller thread for the "
+ "specified maximum interval (in miliseconds) Parameters: "
+ "msec_timeout: Maximum time to wait, in miliseconds. "
+ "Returns: The number of events that have been handled during the poll. "
+ "Negative value indicates error, and application can retrieve the error "
+ "as (err = -return_value).";
+
+static char pjsua_verify_sip_url_doc[] =
+ "int py_pjsua.verify_sip_url (string c_url) "
+ "Verify that valid SIP url is given Parameters: "
+ "c_url: The URL, as NULL terminated string.";
+
+static char pjsua_pool_create_doc[] =
+ "py_pjsua.Pj_Pool py_pjsua.pool_create (string name, int init_size, "
+ "int increment) "
+ "Create memory pool Parameters: "
+ "name: Optional pool name; "
+ "init_size: Initial size of the pool; "
+ "increment: Increment size.";
+
+static char pjsua_get_pjsip_endpt_doc[] =
+ "py_pjsua.Pjsip_Endpoint py_pjsua.get_pjsip_endpt (void) "
+ "Internal function to get SIP endpoint instance of pjsua, which is needed "
+ "for example to register module, create transports, etc. Probably is only "
+ "valid after pjsua_init() is called.";
+
+static char pjsua_get_pjmedia_endpt_doc[] =
+ "py_pjsua.Pjmedia_Endpt py_pjsua.get_pjmedia_endpt (void) "
+ "Internal function to get media endpoint instance. Only valid after "
+ "pjsua_init() is called.";
+
+static char pjsua_get_pool_factory_doc[] =
+ "py_pjsua.Pj_Pool_Factory py_pjsua.get_pool_factory (void) "
+ "Internal function to get PJSUA pool factory. Only valid after "
+ "pjsua_init() is called.";
+
+static char pjsua_reconfigure_logging_doc[] =
+ "int py_pjsua.reconfigure_logging (py_pjsua.Logging_Config c) "
+ "Application can call this function at any time (after pjsua_create(), of "
+ "course) to change logging settings. Parameters: "
+ "c: Logging configuration.";
+
+static char pjsua_logging_config_default_doc[] =
+ "py_pjsua.Logging_Config py_pjsua.logging_config_default () "
+ "Use this function to initialize logging config.";
+
+static char pjsua_config_default_doc[] =
+ "py_pjsua.Config py_pjsua.config_default (). Use this function to "
+ "initialize pjsua config. ";
+
+static char pjsua_media_config_default_doc[] =
+ "py_pjsua.Media_Config py_pjsua.media_config_default (). "
+ "Use this function to initialize media config.";
+
+static char pjsua_msg_data_init_doc[] =
+ "py_pjsua.Msg_Data void py_pjsua.msg_data_init () "
+ "Initialize message data ";
+
+
+/* END OF LIB BASE */
+
+/* LIB TRANSPORT */
+
+/*
+ * py_pjsua_transport_config_default
+ * !modified @ 051206
+ */
+static PyObject *py_pjsua_transport_config_default(PyObject *pSelf,
+ PyObject *pArgs)
+{
+ PyObj_pjsua_transport_config *obj;
+ pjsua_transport_config cfg;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "")) {
+ return NULL;
+ }
+
+ pjsua_transport_config_default(&cfg);
+ obj = (PyObj_pjsua_transport_config*)
+ PyObj_pjsua_transport_config_new(&PyTyp_pjsua_transport_config,
+ NULL, NULL);
+ PyObj_pjsua_transport_config_import(obj, &cfg);
+
+ return (PyObject *)obj;
+}
+
+/*
+ * py_pjsua_transport_create
+ * !modified @ 051206
+ */
+static PyObject *py_pjsua_transport_create(PyObject *pSelf, PyObject *pArgs)
+{
+ pj_status_t status;
+ int type;
+ PyObject * tmpObj;
+ pjsua_transport_config cfg;
+ pjsua_transport_id id;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "iO", &type, &tmpObj)) {
+ return NULL;
+ }
+
+ if (tmpObj != Py_None) {
+ PyObj_pjsua_transport_config *obj;
+ obj = (PyObj_pjsua_transport_config*)tmpObj;
+ PyObj_pjsua_transport_config_export(&cfg, obj);
+ status = pjsua_transport_create(type, &cfg, &id);
+ } else {
+ status = pjsua_transport_create(type, NULL, &id);
+ }
+
+
+ return Py_BuildValue("ii", status, id);
+}
+
+/*
+ * py_pjsua_enum_transports
+ * !modified @ 261206
+ */
+static PyObject *py_pjsua_enum_transports(PyObject *pSelf, PyObject *pArgs)
+{
+ pj_status_t status;
+ PyObject *list;
+
+ pjsua_transport_id id[PJSIP_MAX_TRANSPORTS];
+ unsigned c, i;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, ""))
+ {
+ return NULL;
+ }
+
+ c = PJ_ARRAY_SIZE(id);
+ status = pjsua_enum_transports(id, &c);
+
+ list = PyList_New(c);
+ for (i = 0; i < c; i++)
+ {
+ int ret = PyList_SetItem(list, i, Py_BuildValue("i", id[i]));
+ if (ret == -1)
+ {
+ return NULL;
+ }
+ }
+
+ return Py_BuildValue("O",list);
+}
+
+/*
+ * py_pjsua_transport_get_info
+ * !modified @ 051206
+ */
+static PyObject *py_pjsua_transport_get_info(PyObject *pSelf, PyObject *pArgs)
+{
+ pj_status_t status;
+ int id;
+ pjsua_transport_info info;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &id)) {
+ return NULL;
+ }
+
+ status = pjsua_transport_get_info(id, &info);
+ if (status == PJ_SUCCESS) {
+ PyObj_pjsua_transport_info *obj;
+ obj = (PyObj_pjsua_transport_info *)
+ PyObj_pjsua_transport_info_new(&PyTyp_pjsua_transport_info,
+ NULL, NULL);
+ PyObj_pjsua_transport_info_import(obj, &info);
+ return Py_BuildValue("O", obj);
+ } else {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+}
+
+/*
+ * py_pjsua_transport_set_enable
+ */
+static PyObject *py_pjsua_transport_set_enable
+(PyObject *pSelf, PyObject *pArgs)
+{
+ pj_status_t status;
+ int id;
+ int enabled;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "ii", &id, &enabled))
+ {
+ return NULL;
+ }
+ status = pjsua_transport_set_enable(id, enabled);
+
+ return Py_BuildValue("i",status);
+}
+
+/*
+ * py_pjsua_transport_close
+ */
+static PyObject *py_pjsua_transport_close(PyObject *pSelf, PyObject *pArgs)
+{
+ pj_status_t status;
+ int id;
+ int force;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "ii", &id, &force))
+ {
+ return NULL;
+ }
+ status = pjsua_transport_close(id, force);
+
+ return Py_BuildValue("i",status);
+}
+
+static char pjsua_transport_config_default_doc[] =
+ "py_pjsua.Transport_Config py_pjsua.transport_config_default () "
+ "Call this function to initialize UDP config with default values.";
+static char pjsua_transport_create_doc[] =
+ "int, int py_pjsua.transport_create (int type, "
+ "py_pjsua.Transport_Config cfg) "
+ "Create SIP transport.";
+static char pjsua_enum_transports_doc[] =
+ "int[] py_pjsua.enum_transports () "
+ "Enumerate all transports currently created in the system.";
+static char pjsua_transport_get_info_doc[] =
+ "void py_pjsua.transport_get_info "
+ "(py_pjsua.Transport_ID id, py_pjsua.Transport_Info info) "
+ "Get information about transports.";
+static char pjsua_transport_set_enable_doc[] =
+ "void py_pjsua.transport_set_enable "
+ "(py_pjsua.Transport_ID id, int enabled) "
+ "Disable a transport or re-enable it. "
+ "By default transport is always enabled after it is created. "
+ "Disabling a transport does not necessarily close the socket, "
+ "it will only discard incoming messages and prevent the transport "
+ "from being used to send outgoing messages.";
+static char pjsua_transport_close_doc[] =
+ "void py_pjsua.transport_close (py_pjsua.Transport_ID id, int force) "
+ "Close the transport. If transport is forcefully closed, "
+ "it will be immediately closed, and any pending transactions "
+ "that are using the transport may not terminate properly. "
+ "Otherwise, the system will wait until all transactions are closed "
+ "while preventing new users from using the transport, and will close "
+ "the transport when it is safe to do so.";
+
+/* END OF LIB TRANSPORT */
+
+/* LIB ACCOUNT */
+
+
+/*
+ * py_pjsua_acc_config_default
+ * !modified @ 051206
+ */
+static PyObject *py_pjsua_acc_config_default(PyObject *pSelf, PyObject *pArgs)
+{
+ PyObj_pjsua_acc_config *obj;
+ pjsua_acc_config cfg;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "")) {
+ return NULL;
+ }
+
+ pjsua_acc_config_default(&cfg);
+ obj = (PyObj_pjsua_acc_config *)
+ PyObj_pjsua_acc_config_new(&PyTyp_pjsua_acc_config,
+ NULL, NULL);
+ PyObj_pjsua_acc_config_import(obj, &cfg);
+ return (PyObject *)obj;
+}
+
+/*
+ * py_pjsua_acc_get_count
+ */
+static PyObject *py_pjsua_acc_get_count(PyObject *pSelf, PyObject *pArgs)
+{
+ int count;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "")) {
+ return NULL;
+ }
+
+ count = pjsua_acc_get_count();
+ return Py_BuildValue("i",count);
+}
+
+/*
+ * py_pjsua_acc_is_valid
+ */
+static PyObject *py_pjsua_acc_is_valid(PyObject *pSelf, PyObject *pArgs)
+{
+ int id;
+ int is_valid;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &id)) {
+ return NULL;
+ }
+
+ is_valid = pjsua_acc_is_valid(id);
+ return Py_BuildValue("i", is_valid);
+}
+
+/*
+ * py_pjsua_acc_set_default
+ */
+static PyObject *py_pjsua_acc_set_default(PyObject *pSelf, PyObject *pArgs)
+{
+ int id;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &id)) {
+ return NULL;
+ }
+ status = pjsua_acc_set_default(id);
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_acc_get_default
+ */
+static PyObject *py_pjsua_acc_get_default(PyObject *pSelf, PyObject *pArgs)
+{
+ int id;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "")) {
+ return NULL;
+ }
+
+ id = pjsua_acc_get_default();
+
+ return Py_BuildValue("i", id);
+}
+
+/*
+ * py_pjsua_acc_add
+ * !modified @ 051206
+ */
+static PyObject *py_pjsua_acc_add(PyObject *pSelf, PyObject *pArgs)
+{
+ int is_default;
+ PyObject * acObj;
+ PyObj_pjsua_acc_config * ac;
+ int acc_id;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "Oi", &acObj, &is_default)) {
+ return NULL;
+ }
+
+ if (acObj != Py_None) {
+ pjsua_acc_config cfg;
+
+ pjsua_acc_config_default(&cfg);
+ ac = (PyObj_pjsua_acc_config *)acObj;
+ PyObj_pjsua_acc_config_export(&cfg, ac);
+ status = pjsua_acc_add(&cfg, is_default, &acc_id);
+ } else {
+ status = PJ_EINVAL;
+ acc_id = PJSUA_INVALID_ID;
+ }
+
+ return Py_BuildValue("ii", status, acc_id);
+}
+
+/*
+ * py_pjsua_acc_add_local
+ * !modified @ 051206
+ */
+static PyObject *py_pjsua_acc_add_local(PyObject *pSelf, PyObject *pArgs)
+{
+ int is_default;
+ int tid;
+ int p_acc_id;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "ii", &tid, &is_default)) {
+ return NULL;
+ }
+
+
+ status = pjsua_acc_add_local(tid, is_default, &p_acc_id);
+
+ return Py_BuildValue("ii", status, p_acc_id);
+}
+
+/*
+ * py_pjsua_acc_del
+ */
+static PyObject *py_pjsua_acc_del(PyObject *pSelf, PyObject *pArgs)
+{
+ int acc_id;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &acc_id))
+ {
+ return NULL;
+ }
+
+
+ status = pjsua_acc_del(acc_id);
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_acc_modify
+ */
+static PyObject *py_pjsua_acc_modify(PyObject *pSelf, PyObject *pArgs)
+{
+ PyObject * acObj;
+ PyObj_pjsua_acc_config * ac;
+ int acc_id;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "iO", &acc_id, &acObj)) {
+ return NULL;
+ }
+
+ if (acObj != Py_None) {
+ pjsua_acc_config cfg;
+
+ pjsua_acc_config_default(&cfg);
+ ac = (PyObj_pjsua_acc_config *)acObj;
+ PyObj_pjsua_acc_config_export(&cfg, ac);
+
+ status = pjsua_acc_modify(acc_id, &cfg);
+ } else {
+ status = PJ_EINVAL;
+ }
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_acc_set_online_status
+ */
+static PyObject *py_pjsua_acc_set_online_status(PyObject *pSelf,
+ PyObject *pArgs)
+{
+ int is_online;
+ int acc_id;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "ii", &acc_id, &is_online)) {
+ return NULL;
+ }
+
+ status = pjsua_acc_set_online_status(acc_id, is_online);
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_acc_set_online_status2
+ */
+static PyObject *py_pjsua_acc_set_online_status2(PyObject *pSelf,
+ PyObject *pArgs)
+{
+ int is_online;
+ int acc_id;
+ int activity_id;
+ const char *activity_text;
+ pjrpid_element rpid;
+ pj_status_t status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "iiis", &acc_id, &is_online,
+ &activity_id, &activity_text)) {
+ return NULL;
+ }
+
+ pj_bzero(&rpid, sizeof(rpid));
+ rpid.activity = activity_id;
+ rpid.note = pj_str((char*)activity_text);
+
+ status = pjsua_acc_set_online_status2(acc_id, is_online, &rpid);
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_acc_set_registration
+ */
+static PyObject *py_pjsua_acc_set_registration(PyObject *pSelf,
+ PyObject *pArgs)
+{
+ int renew;
+ int acc_id;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "ii", &acc_id, &renew)) {
+ return NULL;
+ }
+
+ status = pjsua_acc_set_registration(acc_id, renew);
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_acc_get_info
+ * !modified @ 051206
+ */
+static PyObject *py_pjsua_acc_get_info(PyObject *pSelf, PyObject *pArgs)
+{
+ int acc_id;
+ PyObj_pjsua_acc_info * obj;
+ pjsua_acc_info info;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &acc_id)) {
+ return NULL;
+ }
+
+ status = pjsua_acc_get_info(acc_id, &info);
+ if (status == PJ_SUCCESS) {
+ obj = (PyObj_pjsua_acc_info *)
+ PyObj_pjsua_acc_info_new(&PyTyp_pjsua_acc_info,NULL, NULL);
+ PyObj_pjsua_acc_info_import(obj, &info);
+ return Py_BuildValue("O", obj);
+ } else {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+}
+
+/*
+ * py_pjsua_enum_accs
+ * !modified @ 241206
+ */
+static PyObject *py_pjsua_enum_accs(PyObject *pSelf, PyObject *pArgs)
+{
+ pj_status_t status;
+ PyObject *list;
+
+ pjsua_acc_id id[PJSUA_MAX_ACC];
+ unsigned c, i;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, ""))
+ {
+ return NULL;
+ }
+ c = PJ_ARRAY_SIZE(id);
+
+ status = pjsua_enum_accs(id, &c);
+
+ list = PyList_New(c);
+ for (i = 0; i < c; i++)
+ {
+ int ret = PyList_SetItem(list, i, Py_BuildValue("i", id[i]));
+ if (ret == -1)
+ {
+ return NULL;
+ }
+ }
+
+ return Py_BuildValue("O",list);
+}
+
+/*
+ * py_pjsua_acc_enum_info
+ * !modified @ 241206
+ */
+static PyObject *py_pjsua_acc_enum_info(PyObject *pSelf, PyObject *pArgs)
+{
+ pj_status_t status;
+ PyObject *list;
+ pjsua_acc_info info[PJSUA_MAX_ACC];
+ unsigned c, i;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "")) {
+ return NULL;
+ }
+
+ c = PJ_ARRAY_SIZE(info);
+ status = pjsua_acc_enum_info(info, &c);
+
+ list = PyList_New(c);
+ for (i = 0; i < c; i++) {
+ PyObj_pjsua_acc_info *obj;
+ obj = (PyObj_pjsua_acc_info *)
+ PyObj_pjsua_acc_info_new(&PyTyp_pjsua_acc_info, NULL, NULL);
+
+ PyObj_pjsua_acc_info_import(obj, &info[i]);
+
+ PyList_SetItem(list, i, (PyObject *)obj);
+ }
+
+ return Py_BuildValue("O",list);
+}
+
+/*
+ * py_pjsua_acc_find_for_outgoing
+ */
+static PyObject *py_pjsua_acc_find_for_outgoing(PyObject *pSelf,
+ PyObject *pArgs)
+{
+ int acc_id;
+ PyObject * url;
+ pj_str_t str;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "O", &url))
+ {
+ return NULL;
+ }
+ str.ptr = PyString_AsString(url);
+ str.slen = strlen(PyString_AsString(url));
+
+ acc_id = pjsua_acc_find_for_outgoing(&str);
+
+ return Py_BuildValue("i", acc_id);
+}
+
+/*
+ * py_pjsua_acc_find_for_incoming
+ */
+static PyObject *py_pjsua_acc_find_for_incoming(PyObject *pSelf,
+ PyObject *pArgs)
+{
+ int acc_id;
+ PyObject * tmpObj;
+ PyObj_pjsip_rx_data * obj;
+ pjsip_rx_data * rdata;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "O", &tmpObj))
+ {
+ return NULL;
+ }
+ if (tmpObj != Py_None)
+ {
+ obj = (PyObj_pjsip_rx_data *)tmpObj;
+ rdata = obj->rdata;
+ acc_id = pjsua_acc_find_for_incoming(rdata);
+ } else {
+ acc_id = pjsua_acc_find_for_incoming(NULL);
+ }
+ return Py_BuildValue("i", acc_id);
+}
+
+/*
+ * py_pjsua_acc_create_uac_contact
+ * !modified @ 061206
+ */
+static PyObject *py_pjsua_acc_create_uac_contact(PyObject *pSelf,
+ PyObject *pArgs)
+{
+ int status;
+ int acc_id;
+ PyObject * pObj;
+ PyObj_pj_pool * p;
+ pj_pool_t * pool;
+ PyObject * strc;
+ pj_str_t contact;
+ PyObject * stru;
+ pj_str_t uri;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "OiO", &pObj, &acc_id, &stru))
+ {
+ return NULL;
+ }
+ if (pObj != Py_None)
+ {
+ p = (PyObj_pj_pool *)pObj;
+ pool = p->pool;
+ uri.ptr = PyString_AsString(stru);
+ uri.slen = strlen(PyString_AsString(stru));
+ status = pjsua_acc_create_uac_contact(pool, &contact, acc_id, &uri);
+ } else {
+ status = pjsua_acc_create_uac_contact(NULL, &contact, acc_id, &uri);
+ }
+ strc = PyString_FromStringAndSize(contact.ptr, contact.slen);
+
+ return Py_BuildValue("O", strc);
+}
+
+/*
+ * py_pjsua_acc_create_uas_contact
+ * !modified @ 061206
+ */
+static PyObject *py_pjsua_acc_create_uas_contact(PyObject *pSelf,
+ PyObject *pArgs)
+{
+ int status;
+ int acc_id;
+ PyObject * pObj;
+ PyObj_pj_pool * p;
+ pj_pool_t * pool;
+ PyObject * strc;
+ pj_str_t contact;
+ PyObject * rObj;
+ PyObj_pjsip_rx_data * objr;
+ pjsip_rx_data * rdata;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "OiO", &pObj, &acc_id, &rObj))
+ {
+ return NULL;
+ }
+ if (pObj != Py_None)
+ {
+ p = (PyObj_pj_pool *)pObj;
+ pool = p->pool;
+ } else {
+ pool = NULL;
+ }
+ if (rObj != Py_None)
+ {
+ objr = (PyObj_pjsip_rx_data *)rObj;
+ rdata = objr->rdata;
+ } else {
+ rdata = NULL;
+ }
+ status = pjsua_acc_create_uas_contact(pool, &contact, acc_id, rdata);
+ strc = PyString_FromStringAndSize(contact.ptr, contact.slen);
+
+ return Py_BuildValue("O", strc);
+}
+
+static char pjsua_acc_config_default_doc[] =
+ "py_pjsua.Acc_Config py_pjsua.acc_config_default () "
+ "Call this function to initialize account config with default values.";
+static char pjsua_acc_get_count_doc[] =
+ "int py_pjsua.acc_get_count () "
+ "Get number of current accounts.";
+static char pjsua_acc_is_valid_doc[] =
+ "int py_pjsua.acc_is_valid (int acc_id) "
+ "Check if the specified account ID is valid.";
+static char pjsua_acc_set_default_doc[] =
+ "int py_pjsua.acc_set_default (int acc_id) "
+ "Set default account to be used when incoming "
+ "and outgoing requests doesn't match any accounts.";
+static char pjsua_acc_get_default_doc[] =
+ "int py_pjsua.acc_get_default () "
+ "Get default account.";
+static char pjsua_acc_add_doc[] =
+ "int, int py_pjsua.acc_add (py_pjsua.Acc_Config cfg, "
+ "int is_default) "
+ "Add a new account to pjsua. PJSUA must have been initialized "
+ "(with pjsua_init()) before calling this function.";
+static char pjsua_acc_add_local_doc[] =
+ "int,int py_pjsua.acc_add_local (int tid, "
+ "int is_default) "
+ "Add a local account. A local account is used to identify "
+ "local endpoint instead of a specific user, and for this reason, "
+ "a transport ID is needed to obtain the local address information.";
+static char pjsua_acc_del_doc[] =
+ "int py_pjsua.acc_del (int acc_id) "
+ "Delete account.";
+static char pjsua_acc_modify_doc[] =
+ "int py_pjsua.acc_modify (int acc_id, py_pjsua.Acc_Config cfg) "
+ "Modify account information.";
+static char pjsua_acc_set_online_status_doc[] =
+ "int py_pjsua.acc_set_online_status2(int acc_id, int is_online) "
+ "Modify account's presence status to be advertised "
+ "to remote/presence subscribers.";
+static char pjsua_acc_set_online_status2_doc[] =
+ "int py_pjsua.acc_set_online_status (int acc_id, int is_online, "
+ "int activity_id, string activity_text) "
+ "Modify account's presence status to be advertised "
+ "to remote/presence subscribers.";
+static char pjsua_acc_set_registration_doc[] =
+ "int py_pjsua.acc_set_registration (int acc_id, int renew) "
+ "Update registration or perform unregistration.";
+static char pjsua_acc_get_info_doc[] =
+ "py_pjsua.Acc_Info py_pjsua.acc_get_info (int acc_id) "
+ "Get account information.";
+static char pjsua_enum_accs_doc[] =
+ "int[] py_pjsua.enum_accs () "
+ "Enum accounts all account ids.";
+static char pjsua_acc_enum_info_doc[] =
+ "py_pjsua.Acc_Info[] py_pjsua.acc_enum_info () "
+ "Enum accounts info.";
+static char pjsua_acc_find_for_outgoing_doc[] =
+ "int py_pjsua.acc_find_for_outgoing (string url) "
+ "This is an internal function to find the most appropriate account "
+ "to used to reach to the specified URL.";
+static char pjsua_acc_find_for_incoming_doc[] =
+ "int py_pjsua.acc_find_for_incoming (PyObj_pjsip_rx_data rdata) "
+ "This is an internal function to find the most appropriate account "
+ "to be used to handle incoming calls.";
+static char pjsua_acc_create_uac_contact_doc[] =
+ "string py_pjsua.acc_create_uac_contact (PyObj_pj_pool pool, "
+ "int acc_id, string uri) "
+ "Create a suitable URI to be put as Contact based on the specified "
+ "target URI for the specified account.";
+static char pjsua_acc_create_uas_contact_doc[] =
+ "string py_pjsua.acc_create_uas_contact (PyObj_pj_pool pool, "
+ "int acc_id, PyObj_pjsip_rx_data rdata) "
+ "Create a suitable URI to be put as Contact based on the information "
+ "in the incoming request.";
+
+/* END OF LIB ACCOUNT */
+
+/* LIB BUDDY */
+
+
+
+/*
+ * py_pjsua_buddy_config_default
+ */
+static PyObject *py_pjsua_buddy_config_default(PyObject *pSelf,
+ PyObject *pArgs)
+{
+ PyObj_pjsua_buddy_config *obj;
+ pjsua_buddy_config cfg;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "")) {
+ return NULL;
+ }
+
+ pjsua_buddy_config_default(&cfg);
+ obj = (PyObj_pjsua_buddy_config *)
+ PyObj_pjsua_buddy_config_new(&PyTyp_pjsua_buddy_config, NULL, NULL);
+ PyObj_pjsua_buddy_config_import(obj, &cfg);
+
+ return (PyObject *)obj;
+}
+
+/*
+ * py_pjsua_get_buddy_count
+ */
+static PyObject *py_pjsua_get_buddy_count(PyObject *pSelf, PyObject *pArgs)
+{
+ int ret;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "")) {
+ return NULL;
+ }
+ ret = pjsua_get_buddy_count();
+
+ return Py_BuildValue("i", ret);
+}
+
+/*
+ * py_pjsua_buddy_is_valid
+ */
+static PyObject *py_pjsua_buddy_is_valid(PyObject *pSelf, PyObject *pArgs)
+{
+ int id;
+ int is_valid;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &id)) {
+ return NULL;
+ }
+ is_valid = pjsua_buddy_is_valid(id);
+
+ return Py_BuildValue("i", is_valid);
+}
+
+/*
+ * py_pjsua_enum_buddies
+ * !modified @ 241206
+ */
+static PyObject *py_pjsua_enum_buddies(PyObject *pSelf, PyObject *pArgs)
+{
+ pj_status_t status;
+ PyObject *list;
+
+ pjsua_buddy_id id[PJSUA_MAX_BUDDIES];
+ unsigned c, i;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "")) {
+ return NULL;
+ }
+ c = PJ_ARRAY_SIZE(id);
+ status = pjsua_enum_buddies(id, &c);
+ list = PyList_New(c);
+ for (i = 0; i < c; i++) {
+ PyList_SetItem(list, i, Py_BuildValue("i", id[i]));
+ }
+
+ return Py_BuildValue("O",list);
+}
+
+/*
+ * py_pjsua_buddy_get_info
+ * !modified @ 071206
+ */
+static PyObject *py_pjsua_buddy_get_info(PyObject *pSelf, PyObject *pArgs)
+{
+ int buddy_id;
+ PyObj_pjsua_buddy_info * obj;
+ pjsua_buddy_info info;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &buddy_id)) {
+ return NULL;
+ }
+
+ status = pjsua_buddy_get_info(buddy_id, &info);
+ if (status == PJ_SUCCESS) {
+ obj = (PyObj_pjsua_buddy_info *)
+ PyObj_pjsua_buddy_config_new(&PyTyp_pjsua_buddy_info,NULL,NULL);
+ PyObj_pjsua_buddy_info_import(obj, &info);
+ return Py_BuildValue("O", obj);
+ } else {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+}
+
+/*
+ * py_pjsua_buddy_add
+ * !modified @ 061206
+ */
+static PyObject *py_pjsua_buddy_add(PyObject *pSelf, PyObject *pArgs)
+{
+ PyObject * bcObj;
+ int buddy_id;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "O", &bcObj)) {
+ return NULL;
+ }
+
+ if (bcObj != Py_None) {
+ pjsua_buddy_config cfg;
+ PyObj_pjsua_buddy_config * bc;
+
+ bc = (PyObj_pjsua_buddy_config *)bcObj;
+
+ pjsua_buddy_config_default(&cfg);
+ PyObj_pjsua_buddy_config_export(&cfg, bc);
+
+ status = pjsua_buddy_add(&cfg, &buddy_id);
+ } else {
+ status = PJ_EINVAL;
+ buddy_id = PJSUA_INVALID_ID;
+ }
+ return Py_BuildValue("ii", status, buddy_id);
+}
+
+/*
+ * py_pjsua_buddy_del
+ */
+static PyObject *py_pjsua_buddy_del(PyObject *pSelf, PyObject *pArgs)
+{
+ int buddy_id;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &buddy_id)) {
+ return NULL;
+ }
+
+
+ status = pjsua_buddy_del(buddy_id);
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_buddy_subscribe_pres
+ */
+static PyObject *py_pjsua_buddy_subscribe_pres(PyObject *pSelf, PyObject *pArgs)
+{
+ int buddy_id;
+ int status;
+ int subscribe;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "ii", &buddy_id, &subscribe)) {
+ return NULL;
+ }
+
+
+ status = pjsua_buddy_subscribe_pres(buddy_id, subscribe);
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_pres_dump
+ */
+static PyObject *py_pjsua_pres_dump(PyObject *pSelf, PyObject *pArgs)
+{
+ int verbose;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &verbose)) {
+ return NULL;
+ }
+
+
+ pjsua_pres_dump(verbose);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+/*
+ * py_pjsua_im_send
+ * !modified @ 071206
+ */
+static PyObject *py_pjsua_im_send(PyObject *pSelf, PyObject *pArgs)
+{
+ int status;
+ int acc_id;
+ pj_str_t * mime_type, tmp_mime_type;
+ pj_str_t to, content;
+ PyObject * st;
+ PyObject * smt;
+ PyObject * sc;
+ pjsua_msg_data msg_data;
+ PyObject * omdObj;
+ PyObj_pjsua_msg_data * omd;
+
+ int user_data;
+ pj_pool_t *pool;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "iOOOOi", &acc_id,
+ &st, &smt, &sc, &omdObj, &user_data))
+ {
+ return NULL;
+ }
+ if (smt != Py_None) {
+ mime_type = &tmp_mime_type;
+ tmp_mime_type = PyString_to_pj_str(smt);
+ } else {
+ mime_type = NULL;
+ }
+ to = PyString_to_pj_str(st);
+ content = PyString_to_pj_str(sc);
+
+ if (omdObj != Py_None) {
+
+ omd = (PyObj_pjsua_msg_data *)omdObj;
+ msg_data.content_type = PyString_to_pj_str(omd->content_type);
+ msg_data.msg_body = PyString_to_pj_str(omd->msg_body);
+ pool = pjsua_pool_create("pjsua", POOL_SIZE, POOL_SIZE);
+
+ translate_hdr(pool, &msg_data.hdr_list, omd->hdr_list);
+ status = pjsua_im_send(acc_id, &to, mime_type,
+ &content, &msg_data, (void *)user_data);
+ pj_pool_release(pool);
+ } else {
+
+ status = pjsua_im_send(acc_id, &to, mime_type,
+ &content, NULL, NULL);
+ }
+
+ return Py_BuildValue("i",status);
+}
+
+/*
+ * py_pjsua_im_typing
+ */
+static PyObject *py_pjsua_im_typing(PyObject *pSelf, PyObject *pArgs)
+{
+ int status;
+ int acc_id;
+ pj_str_t to;
+ PyObject * st;
+ int is_typing;
+ pjsua_msg_data msg_data;
+ PyObject * omdObj;
+ PyObj_pjsua_msg_data * omd;
+ pj_pool_t * pool;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "iOiO", &acc_id, &st, &is_typing, &omdObj)) {
+ return NULL;
+ }
+
+ to = PyString_to_pj_str(st);
+
+ if (omdObj != Py_None) {
+ omd = (PyObj_pjsua_msg_data *)omdObj;
+ msg_data.content_type = PyString_to_pj_str(omd->content_type);
+ msg_data.msg_body = PyString_to_pj_str(omd->msg_body);
+ pool = pjsua_pool_create("pjsua", POOL_SIZE, POOL_SIZE);
+
+ translate_hdr(pool, &msg_data.hdr_list, omd->hdr_list);
+ status = pjsua_im_typing(acc_id, &to, is_typing, &msg_data);
+ pj_pool_release(pool);
+ } else {
+ status = pjsua_im_typing(acc_id, &to, is_typing, NULL);
+ }
+ return Py_BuildValue("i",status);
+}
+
+static char pjsua_buddy_config_default_doc[] =
+ "py_pjsua.Buddy_Config py_pjsua.buddy_config_default () "
+ "Set default values to the buddy config.";
+static char pjsua_get_buddy_count_doc[] =
+ "int py_pjsua.get_buddy_count () "
+ "Get total number of buddies.";
+static char pjsua_buddy_is_valid_doc[] =
+ "int py_pjsua.buddy_is_valid (int buddy_id) "
+ "Check if buddy ID is valid.";
+static char pjsua_enum_buddies_doc[] =
+ "int[] py_pjsua.enum_buddies () "
+ "Enum buddy IDs.";
+static char pjsua_buddy_get_info_doc[] =
+ "py_pjsua.Buddy_Info py_pjsua.buddy_get_info (int buddy_id) "
+ "Get detailed buddy info.";
+static char pjsua_buddy_add_doc[] =
+ "int,int py_pjsua.buddy_add (py_pjsua.Buddy_Config cfg) "
+ "Add new buddy.";
+static char pjsua_buddy_del_doc[] =
+ "int py_pjsua.buddy_del (int buddy_id) "
+ "Delete buddy.";
+static char pjsua_buddy_subscribe_pres_doc[] =
+ "int py_pjsua.buddy_subscribe_pres (int buddy_id, int subscribe) "
+ "Enable/disable buddy's presence monitoring.";
+static char pjsua_pres_dump_doc[] =
+ "void py_pjsua.pres_dump (int verbose) "
+ "Dump presence subscriptions to log file.";
+static char pjsua_im_send_doc[] =
+ "int py_pjsua.im_send (int acc_id, string to, string mime_type, "
+ "string content, py_pjsua.Msg_Data msg_data, int user_data) "
+ "Send instant messaging outside dialog, using the specified account "
+ "for route set and authentication.";
+static char pjsua_im_typing_doc[] =
+ "int py_pjsua.im_typing (int acc_id, string to, int is_typing, "
+ "py_pjsua.Msg_Data msg_data) "
+ "Send typing indication outside dialog.";
+
+/* END OF LIB BUDDY */
+
+/* LIB MEDIA */
+
+
+
+/*
+ * PyObj_pjsua_codec_info
+ * Codec Info
+ * !modified @ 071206
+ */
+typedef struct
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+
+ PyObject * codec_id;
+ pj_uint8_t priority;
+ char buf_[32];
+} PyObj_pjsua_codec_info;
+
+
+/*
+ * codec_info_dealloc
+ * deletes a codec_info from memory
+ * !modified @ 071206
+ */
+static void codec_info_dealloc(PyObj_pjsua_codec_info* self)
+{
+ Py_XDECREF(self->codec_id);
+
+ self->ob_type->tp_free((PyObject*)self);
+}
+
+
+/*
+ * codec_info_new
+ * constructor for codec_info object
+ * !modified @ 071206
+ */
+static PyObject * codec_info_new(PyTypeObject *type, PyObject *args,
+ PyObject *kwds)
+{
+ PyObj_pjsua_codec_info *self;
+
+ PJ_UNUSED_ARG(args);
+ PJ_UNUSED_ARG(kwds);
+
+ self = (PyObj_pjsua_codec_info *)type->tp_alloc(type, 0);
+ if (self != NULL)
+ {
+ self->codec_id = PyString_FromString("");
+ if (self->codec_id == NULL)
+ {
+ Py_DECREF(self);
+ return NULL;
+ }
+
+
+ }
+ return (PyObject *)self;
+}
+
+/*
+ * codec_info_members
+ * !modified @ 071206
+ */
+static PyMemberDef codec_info_members[] =
+{
+ {
+ "codec_id", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_codec_info, codec_id), 0,
+ "Codec unique identification."
+ },
+
+ {
+ "priority", T_INT,
+ offsetof(PyObj_pjsua_codec_info, priority), 0,
+ "Codec priority (integer 0-255)."
+ },
+
+
+
+ {NULL} /* Sentinel */
+};
+
+
+
+
+/*
+ * PyTyp_pjsua_codec_info
+ */
+static PyTypeObject PyTyp_pjsua_codec_info =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "py_pjsua.Codec_Info", /*tp_name*/
+ sizeof(PyObj_pjsua_codec_info), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor)codec_info_dealloc,/*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "Codec Info objects", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ codec_info_members, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ codec_info_new, /* tp_new */
+
+};
+
+/*
+ * PyObj_pjsua_conf_port_info
+ * Conf Port Info
+ */
+typedef struct
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+
+ int slot_id;
+ PyObject * name;
+ unsigned clock_rate;
+ unsigned channel_count;
+ unsigned samples_per_frame;
+ unsigned bits_per_sample;
+ PyListObject * listeners;
+
+} PyObj_pjsua_conf_port_info;
+
+
+/*
+ * conf_port_info_dealloc
+ * deletes a conf_port_info from memory
+ */
+static void conf_port_info_dealloc(PyObj_pjsua_conf_port_info* self)
+{
+ Py_XDECREF(self->name);
+ Py_XDECREF(self->listeners);
+ self->ob_type->tp_free((PyObject*)self);
+}
+
+
+/*
+ * conf_port_info_new
+ * constructor for conf_port_info object
+ */
+static PyObject * conf_port_info_new(PyTypeObject *type, PyObject *args,
+ PyObject *kwds)
+{
+ PyObj_pjsua_conf_port_info *self;
+
+ PJ_UNUSED_ARG(args);
+ PJ_UNUSED_ARG(kwds);
+
+ self = (PyObj_pjsua_conf_port_info *)type->tp_alloc(type, 0);
+ if (self != NULL)
+ {
+ self->name = PyString_FromString("");
+ if (self->name == NULL)
+ {
+ Py_DECREF(self);
+ return NULL;
+ }
+
+ self->listeners = (PyListObject *)PyList_New(0);
+ if (self->listeners == NULL)
+ {
+ Py_DECREF(self);
+ return NULL;
+ }
+ }
+ return (PyObject *)self;
+}
+
+/*
+ * conf_port_info_members
+ */
+static PyMemberDef conf_port_info_members[] =
+{
+ {
+ "slot_id", T_INT,
+ offsetof(PyObj_pjsua_conf_port_info, slot_id), 0,
+ "Conference port number."
+ },
+ {
+ "name", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_conf_port_info, name), 0,
+ "Port name"
+ },
+ {
+ "clock_rate", T_INT,
+ offsetof(PyObj_pjsua_conf_port_info, clock_rate), 0,
+ "Clock rate"
+ },
+ {
+ "channel_count", T_INT,
+ offsetof(PyObj_pjsua_conf_port_info, channel_count), 0,
+ "Number of channels."
+ },
+ {
+ "samples_per_frame", T_INT,
+ offsetof(PyObj_pjsua_conf_port_info, samples_per_frame), 0,
+ "Samples per frame "
+ },
+ {
+ "bits_per_sample", T_INT,
+ offsetof(PyObj_pjsua_conf_port_info, bits_per_sample), 0,
+ "Bits per sample"
+ },
+ {
+ "listeners", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_conf_port_info, listeners), 0,
+ "Array of listeners (in other words, ports where this port "
+ "is transmitting to"
+ },
+
+ {NULL} /* Sentinel */
+};
+
+
+
+
+/*
+ * PyTyp_pjsua_conf_port_info
+ */
+static PyTypeObject PyTyp_pjsua_conf_port_info =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "py_pjsua.Conf_Port_Info", /*tp_name*/
+ sizeof(PyObj_pjsua_conf_port_info), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor)conf_port_info_dealloc,/*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "Conf Port Info objects", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ conf_port_info_members, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ conf_port_info_new, /* tp_new */
+
+};
+
+/*
+ * PyObj_pjmedia_port
+ */
+typedef struct
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+ pjmedia_port * port;
+} PyObj_pjmedia_port;
+
+
+/*
+ * PyTyp_pjmedia_port
+ */
+static PyTypeObject PyTyp_pjmedia_port =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "py_pjsua.PJMedia_Port", /*tp_name*/
+ sizeof(PyObj_pjmedia_port), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ 0, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "pjmedia_port objects", /* tp_doc */
+
+};
+
+/*
+ * PyObj_pjmedia_snd_dev_info
+ * PJMedia Snd Dev Info
+ */
+typedef struct
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+
+
+ unsigned input_count;
+ unsigned output_count;
+ unsigned default_samples_per_sec;
+ PyObject * name;
+
+} PyObj_pjmedia_snd_dev_info;
+
+
+/*
+ * pjmedia_snd_dev_info_dealloc
+ * deletes a pjmedia_snd_dev_info from memory
+ */
+static void pjmedia_snd_dev_info_dealloc(PyObj_pjmedia_snd_dev_info* self)
+{
+ Py_XDECREF(self->name);
+ self->ob_type->tp_free((PyObject*)self);
+}
+
+
+/*
+ * pjmedia_snd_dev_info_new
+ * constructor for pjmedia_snd_dev_info object
+ */
+static PyObject * pjmedia_snd_dev_info_new(PyTypeObject *type, PyObject *args,
+ PyObject *kwds)
+{
+ PyObj_pjmedia_snd_dev_info *self;
+
+ PJ_UNUSED_ARG(args);
+ PJ_UNUSED_ARG(kwds);
+
+ self = (PyObj_pjmedia_snd_dev_info *)type->tp_alloc(type, 0);
+ if (self != NULL)
+ {
+ self->name = PyString_FromString("");
+ if (self->name == NULL)
+ {
+ Py_DECREF(self);
+ return NULL;
+ }
+
+ }
+ return (PyObject *)self;
+}
+
+/*
+ * pjmedia_snd_dev_info_members
+ */
+static PyMemberDef pjmedia_snd_dev_info_members[] =
+{
+
+ {
+ "name", T_OBJECT_EX,
+ offsetof(PyObj_pjmedia_snd_dev_info, name), 0,
+ "Device name"
+ },
+ {
+ "input_count", T_INT,
+ offsetof(PyObj_pjmedia_snd_dev_info, input_count), 0,
+ "Max number of input channels"
+ },
+ {
+ "output_count", T_INT,
+ offsetof(PyObj_pjmedia_snd_dev_info, output_count), 0,
+ "Max number of output channels"
+ },
+ {
+ "default_samples_per_sec", T_INT,
+ offsetof(PyObj_pjmedia_snd_dev_info, default_samples_per_sec), 0,
+ "Default sampling rate."
+ },
+
+
+ {NULL} /* Sentinel */
+};
+
+
+
+
+/*
+ * PyTyp_pjmedia_snd_dev_info
+ */
+static PyTypeObject PyTyp_pjmedia_snd_dev_info =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "py_pjsua.PJMedia_Snd_Dev_Info", /*tp_name*/
+ sizeof(PyObj_pjmedia_snd_dev_info), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor)pjmedia_snd_dev_info_dealloc,/*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "PJMedia Snd Dev Info objects", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ pjmedia_snd_dev_info_members, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ pjmedia_snd_dev_info_new, /* tp_new */
+
+};
+
+/*
+ * PyObj_pjmedia_codec_param_info
+ * PJMedia Codec Param Info
+ */
+typedef struct
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+
+ unsigned clock_rate;
+ unsigned channel_cnt;
+ pj_uint32_t avg_bps;
+ pj_uint16_t frm_ptime;
+ pj_uint8_t pcm_bits_per_sample;
+ pj_uint8_t pt;
+
+} PyObj_pjmedia_codec_param_info;
+
+
+
+/*
+ * pjmedia_codec_param_info_members
+ */
+static PyMemberDef pjmedia_codec_param_info_members[] =
+{
+
+ {
+ "clock_rate", T_INT,
+ offsetof(PyObj_pjmedia_codec_param_info, clock_rate), 0,
+ "Sampling rate in Hz"
+ },
+ {
+ "channel_cnt", T_INT,
+ offsetof(PyObj_pjmedia_codec_param_info, channel_cnt), 0,
+ "Channel count"
+ },
+ {
+ "avg_bps", T_INT,
+ offsetof(PyObj_pjmedia_codec_param_info, avg_bps), 0,
+ "Average bandwidth in bits/sec"
+ },
+ {
+ "frm_ptime", T_INT,
+ offsetof(PyObj_pjmedia_codec_param_info, frm_ptime), 0,
+ "Base frame ptime in msec."
+ },
+ {
+ "pcm_bits_per_sample", T_INT,
+ offsetof(PyObj_pjmedia_codec_param_info, pcm_bits_per_sample), 0,
+ "Bits/sample in the PCM side"
+ },
+ {
+ "pt", T_INT,
+ offsetof(PyObj_pjmedia_codec_param_info, pt), 0,
+ "Payload type"
+ },
+
+ {NULL} /* Sentinel */
+};
+
+
+
+
+/*
+ * PyTyp_pjmedia_codec_param_info
+ */
+static PyTypeObject PyTyp_pjmedia_codec_param_info =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "py_pjsua.PJMedia_Codec_Param_Info", /*tp_name*/
+ sizeof(PyObj_pjmedia_codec_param_info), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ 0,/*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "PJMedia Codec Param Info objects", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ pjmedia_codec_param_info_members, /* tp_members */
+
+
+};
+
+/*
+ * PyObj_pjmedia_codec_param_setting
+ * PJMedia Codec Param Setting
+ */
+typedef struct
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+ pj_uint8_t frm_per_pkt;
+ unsigned vad;
+ unsigned cng;
+ unsigned penh;
+ unsigned plc;
+ unsigned reserved;
+ pj_uint8_t enc_fmtp_mode;
+ pj_uint8_t dec_fmtp_mode;
+
+} PyObj_pjmedia_codec_param_setting;
+
+
+
+/*
+ * pjmedia_codec_param_setting_members
+ */
+static PyMemberDef pjmedia_codec_param_setting_members[] =
+{
+
+ {
+ "frm_per_pkt", T_INT,
+ offsetof(PyObj_pjmedia_codec_param_setting, frm_per_pkt), 0,
+ "Number of frames per packet"
+ },
+ {
+ "vad", T_INT,
+ offsetof(PyObj_pjmedia_codec_param_setting, vad), 0,
+ "Voice Activity Detector"
+ },
+ {
+ "penh", T_INT,
+ offsetof(PyObj_pjmedia_codec_param_setting, penh), 0,
+ "Perceptual Enhancement"
+ },
+ {
+ "plc", T_INT,
+ offsetof(PyObj_pjmedia_codec_param_setting, plc), 0,
+ "Packet loss concealment"
+ },
+ {
+ "reserved", T_INT,
+ offsetof(PyObj_pjmedia_codec_param_setting, reserved), 0,
+ "Reserved, must be zero"
+ },
+ {
+ "cng", T_INT,
+ offsetof(PyObj_pjmedia_codec_param_setting, cng), 0,
+ "Comfort Noise Generator"
+ },
+ {
+ "enc_fmtp_mode", T_INT,
+ offsetof(PyObj_pjmedia_codec_param_setting, enc_fmtp_mode), 0,
+ "Mode param in fmtp (def:0)"
+ },
+ {
+ "dec_fmtp_mode", T_INT,
+ offsetof(PyObj_pjmedia_codec_param_setting, dec_fmtp_mode), 0,
+ "Mode param in fmtp (def:0)"
+ },
+
+ {NULL} /* Sentinel */
+};
+
+
+
+
+/*
+ * PyTyp_pjmedia_codec_param_setting
+ */
+static PyTypeObject PyTyp_pjmedia_codec_param_setting =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "py_pjsua.PJMedia_Codec_Param_Setting", /*tp_name*/
+ sizeof(PyObj_pjmedia_codec_param_setting), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ 0,/*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "PJMedia Codec Param Setting objects", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ pjmedia_codec_param_setting_members, /* tp_members */
+
+
+};
+
+/*
+ * PyObj_pjmedia_codec_param
+ * PJMedia Codec Param
+ */
+typedef struct
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+
+ PyObj_pjmedia_codec_param_info * info;
+ PyObj_pjmedia_codec_param_setting * setting;
+
+} PyObj_pjmedia_codec_param;
+
+
+/*
+ * pjmedia_codec_param_dealloc
+ * deletes a pjmedia_codec_param from memory
+ */
+static void pjmedia_codec_param_dealloc(PyObj_pjmedia_codec_param* self)
+{
+ Py_XDECREF(self->info);
+ Py_XDECREF(self->setting);
+ self->ob_type->tp_free((PyObject*)self);
+}
+
+
+/*
+ * pjmedia_codec_param_new
+ * constructor for pjmedia_codec_param object
+ */
+static PyObject * pjmedia_codec_param_new(PyTypeObject *type, PyObject *args,
+ PyObject *kwds)
+{
+ PyObj_pjmedia_codec_param *self;
+
+ PJ_UNUSED_ARG(args);
+ PJ_UNUSED_ARG(kwds);
+
+ self = (PyObj_pjmedia_codec_param *)type->tp_alloc(type, 0);
+ if (self != NULL)
+ {
+ self->info = (PyObj_pjmedia_codec_param_info *)
+ PyType_GenericNew(&PyTyp_pjmedia_codec_param_info, NULL, NULL);
+ if (self->info == NULL)
+ {
+ Py_DECREF(self);
+ return NULL;
+ }
+ self->setting = (PyObj_pjmedia_codec_param_setting *)
+ PyType_GenericNew(&PyTyp_pjmedia_codec_param_setting, NULL, NULL);
+ if (self->setting == NULL)
+ {
+ Py_DECREF(self);
+ return NULL;
+ }
+ }
+ return (PyObject *)self;
+}
+
+/*
+ * pjmedia_codec_param_members
+ */
+static PyMemberDef pjmedia_codec_param_members[] =
+{
+
+ {
+ "info", T_OBJECT_EX,
+ offsetof(PyObj_pjmedia_codec_param, info), 0,
+ "The 'info' part of codec param describes the capability of the codec,"
+ " and the value should NOT be changed by application."
+ },
+ {
+ "setting", T_OBJECT_EX,
+ offsetof(PyObj_pjmedia_codec_param, setting), 0,
+ "The 'setting' part of codec param describes various settings to be "
+ "applied to the codec. When the codec param is retrieved from the "
+ "codec or codec factory, the values of these will be filled by "
+ "the capability of the codec. Any features that are supported by "
+ "the codec (e.g. vad or plc) will be turned on, so that application "
+ "can query which capabilities are supported by the codec. "
+ "Application may change the settings here before instantiating "
+ "the codec/stream."
+ },
+
+ {NULL} /* Sentinel */
+};
+
+
+
+
+/*
+ * PyTyp_pjmedia_codec_param
+ */
+static PyTypeObject PyTyp_pjmedia_codec_param =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "py_pjsua.PJMedia_Codec_Param", /*tp_name*/
+ sizeof(PyObj_pjmedia_codec_param), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor)pjmedia_codec_param_dealloc,/*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "PJMedia Codec Param objects", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ pjmedia_codec_param_members, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ pjmedia_codec_param_new, /* tp_new */
+
+};
+
+/*
+ * py_pjsua_conf_get_max_ports
+ */
+static PyObject *py_pjsua_conf_get_max_ports
+(PyObject *pSelf, PyObject *pArgs)
+{
+ int ret;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, ""))
+ {
+ return NULL;
+ }
+ ret = pjsua_conf_get_max_ports();
+
+ return Py_BuildValue("i", ret);
+}
+
+/*
+ * py_pjsua_conf_get_active_ports
+ */
+static PyObject *py_pjsua_conf_get_active_ports
+(PyObject *pSelf, PyObject *pArgs)
+{
+ int ret;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, ""))
+ {
+ return NULL;
+ }
+ ret = pjsua_conf_get_active_ports();
+
+ return Py_BuildValue("i", ret);
+}
+
+/*
+ * py_pjsua_enum_conf_ports
+ * !modified @ 241206
+ */
+static PyObject *py_pjsua_enum_conf_ports(PyObject *pSelf, PyObject *pArgs)
+{
+ pj_status_t status;
+ PyObject *list;
+
+ pjsua_conf_port_id id[PJSUA_MAX_CONF_PORTS];
+ unsigned c, i;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, ""))
+ {
+ return NULL;
+ }
+
+ c = PJ_ARRAY_SIZE(id);
+ status = pjsua_enum_conf_ports(id, &c);
+
+ list = PyList_New(c);
+ for (i = 0; i < c; i++)
+ {
+ int ret = PyList_SetItem(list, i, Py_BuildValue("i", id[i]));
+ if (ret == -1)
+ {
+ return NULL;
+ }
+ }
+
+ return Py_BuildValue("O",list);
+}
+
+/*
+ * py_pjsua_conf_get_port_info
+ */
+static PyObject *py_pjsua_conf_get_port_info
+(PyObject *pSelf, PyObject *pArgs)
+{
+ int id;
+ PyObj_pjsua_conf_port_info * obj;
+ pjsua_conf_port_info info;
+ int status;
+ unsigned i;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &id))
+ {
+ return NULL;
+ }
+
+
+ status = pjsua_conf_get_port_info(id, &info);
+ obj = (PyObj_pjsua_conf_port_info *)conf_port_info_new
+ (&PyTyp_pjsua_conf_port_info,NULL,NULL);
+ obj->bits_per_sample = info.bits_per_sample;
+ obj->channel_count = info.bits_per_sample;
+ obj->clock_rate = info.clock_rate;
+ obj->name = PyString_FromStringAndSize(info.name.ptr, info.name.slen);
+ obj->samples_per_frame = info.samples_per_frame;
+ obj->slot_id = info.slot_id;
+
+ obj->listeners = (PyListObject *)PyList_New(info.listener_cnt);
+ for (i = 0; i < info.listener_cnt; i++) {
+ PyObject * item = Py_BuildValue("i",info.listeners[i]);
+ PyList_SetItem((PyObject *)obj->listeners, i, item);
+ }
+ return Py_BuildValue("O", obj);
+}
+
+/*
+ * py_pjsua_conf_add_port
+ */
+static PyObject *py_pjsua_conf_add_port
+(PyObject *pSelf, PyObject *pArgs)
+{
+ int p_id;
+ PyObject * oportObj;
+ PyObj_pjmedia_port * oport;
+ pjmedia_port * port;
+ PyObject * opoolObj;
+ PyObj_pj_pool * opool;
+ pj_pool_t * pool;
+
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "OO", &opoolObj, &oportObj))
+ {
+ return NULL;
+ }
+ if (opoolObj != Py_None)
+ {
+ opool = (PyObj_pj_pool *)opoolObj;
+ pool = opool->pool;
+ } else {
+ opool = NULL;
+ pool = NULL;
+ }
+ if (oportObj != Py_None)
+ {
+ oport = (PyObj_pjmedia_port *)oportObj;
+ port = oport->port;
+ } else {
+ oport = NULL;
+ port = NULL;
+ }
+
+ status = pjsua_conf_add_port(pool, port, &p_id);
+
+
+ return Py_BuildValue("ii", status, p_id);
+}
+
+/*
+ * py_pjsua_conf_remove_port
+ */
+static PyObject *py_pjsua_conf_remove_port
+(PyObject *pSelf, PyObject *pArgs)
+{
+ int id;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &id))
+ {
+ return NULL;
+ }
+
+ status = pjsua_conf_remove_port(id);
+
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_conf_connect
+ */
+static PyObject *py_pjsua_conf_connect
+(PyObject *pSelf, PyObject *pArgs)
+{
+ int source, sink;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "ii", &source, &sink))
+ {
+ return NULL;
+ }
+
+ status = pjsua_conf_connect(source, sink);
+
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_conf_disconnect
+ */
+static PyObject *py_pjsua_conf_disconnect
+(PyObject *pSelf, PyObject *pArgs)
+{
+ int source, sink;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "ii", &source, &sink))
+ {
+ return NULL;
+ }
+
+ status = pjsua_conf_disconnect(source, sink);
+
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_player_create
+ */
+static PyObject *py_pjsua_player_create
+(PyObject *pSelf, PyObject *pArgs)
+{
+ int id;
+ int options;
+ PyObject * filename;
+ pj_str_t str;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "Oi", &filename, &options))
+ {
+ return NULL;
+ }
+ str.ptr = PyString_AsString(filename);
+ str.slen = strlen(PyString_AsString(filename));
+ status = pjsua_player_create(&str, options, &id);
+
+ return Py_BuildValue("ii", status, id);
+}
+
+/*
+ * py_pjsua_player_get_conf_port
+ */
+static PyObject *py_pjsua_player_get_conf_port
+(PyObject *pSelf, PyObject *pArgs)
+{
+
+ int id, port_id;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &id))
+ {
+ return NULL;
+ }
+
+ port_id = pjsua_player_get_conf_port(id);
+
+
+ return Py_BuildValue("i", port_id);
+}
+
+/*
+ * py_pjsua_player_set_pos
+ */
+static PyObject *py_pjsua_player_set_pos
+(PyObject *pSelf, PyObject *pArgs)
+{
+ int id;
+ pj_uint32_t samples;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "iI", &id, &samples))
+ {
+ return NULL;
+ }
+
+ status = pjsua_player_set_pos(id, samples);
+
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_player_destroy
+ */
+static PyObject *py_pjsua_player_destroy
+(PyObject *pSelf, PyObject *pArgs)
+{
+ int id;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &id))
+ {
+ return NULL;
+ }
+
+ status = pjsua_player_destroy(id);
+
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_recorder_create
+ * !modified @ 261206
+ */
+static PyObject *py_pjsua_recorder_create
+(PyObject *pSelf, PyObject *pArgs)
+{
+ int p_id;
+ int options;
+ int max_size;
+ PyObject * filename;
+ pj_str_t str;
+ PyObject * enc_param;
+ pj_str_t strparam;
+ int enc_type;
+
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "OiOii", &filename,
+ &enc_type, &enc_param, &max_size, &options))
+ {
+ return NULL;
+ }
+ str.ptr = PyString_AsString(filename);
+ str.slen = strlen(PyString_AsString(filename));
+ if (enc_param != Py_None)
+ {
+ strparam.ptr = PyString_AsString(enc_param);
+ strparam.slen = strlen(PyString_AsString(enc_param));
+ status = pjsua_recorder_create
+ (&str, enc_type, NULL, max_size, options, &p_id);
+ } else {
+ status = pjsua_recorder_create
+ (&str, enc_type, NULL, max_size, options, &p_id);
+ }
+ return Py_BuildValue("ii", status, p_id);
+}
+
+/*
+ * py_pjsua_recorder_get_conf_port
+ */
+static PyObject *py_pjsua_recorder_get_conf_port
+(PyObject *pSelf, PyObject *pArgs)
+{
+
+ int id, port_id;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &id))
+ {
+ return NULL;
+ }
+
+ port_id = pjsua_recorder_get_conf_port(id);
+
+
+ return Py_BuildValue("i", port_id);
+}
+
+/*
+ * py_pjsua_recorder_destroy
+ */
+static PyObject *py_pjsua_recorder_destroy
+(PyObject *pSelf, PyObject *pArgs)
+{
+ int id;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &id))
+ {
+ return NULL;
+ }
+
+ status = pjsua_recorder_destroy(id);
+
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_enum_snd_devs
+ */
+static PyObject *py_pjsua_enum_snd_devs(PyObject *pSelf, PyObject *pArgs)
+{
+ pj_status_t status;
+ PyObject *list;
+
+ pjmedia_snd_dev_info info[SND_DEV_NUM];
+ unsigned c, i;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, ""))
+ {
+ return NULL;
+ }
+
+ c = PJ_ARRAY_SIZE(info);
+ status = pjsua_enum_snd_devs(info, &c);
+
+ list = PyList_New(c);
+ for (i = 0; i < c; i++)
+ {
+ int ret;
+ int j;
+ char * str;
+
+ PyObj_pjmedia_snd_dev_info * obj;
+ obj = (PyObj_pjmedia_snd_dev_info *)pjmedia_snd_dev_info_new
+ (&PyTyp_pjmedia_snd_dev_info, NULL, NULL);
+ obj->default_samples_per_sec = info[i].default_samples_per_sec;
+ obj->input_count = info[i].input_count;
+ obj->output_count = info[i].output_count;
+ str = (char *)malloc(SND_NAME_LEN * sizeof(char));
+ memset(str, 0, SND_NAME_LEN);
+ for (j = 0; j < SND_NAME_LEN; j++)
+ {
+ str[j] = info[i].name[j];
+ }
+ obj->name = PyString_FromStringAndSize(str, SND_NAME_LEN);
+ free(str);
+ ret = PyList_SetItem(list, i, (PyObject *)obj);
+ if (ret == -1)
+ {
+ return NULL;
+ }
+ }
+
+ return Py_BuildValue("O",list);
+}
+
+/*
+ * py_pjsua_get_snd_dev
+ */
+static PyObject *py_pjsua_get_snd_dev
+(PyObject *pSelf, PyObject *pArgs)
+{
+ int capture_dev, playback_dev;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, ""))
+ {
+ return NULL;
+ }
+
+ status = pjsua_get_snd_dev(&capture_dev, &playback_dev);
+
+
+ return Py_BuildValue("ii", capture_dev, playback_dev);
+}
+
+/*
+ * py_pjsua_set_snd_dev
+ */
+static PyObject *py_pjsua_set_snd_dev
+(PyObject *pSelf, PyObject *pArgs)
+{
+ int capture_dev, playback_dev;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "ii", &capture_dev, &playback_dev))
+ {
+ return NULL;
+ }
+
+ status = pjsua_set_snd_dev(capture_dev, playback_dev);
+
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_set_null_snd_dev
+ */
+static PyObject *py_pjsua_set_null_snd_dev
+(PyObject *pSelf, PyObject *pArgs)
+{
+
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, ""))
+ {
+ return NULL;
+ }
+
+ status = pjsua_set_null_snd_dev();
+
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_set_no_snd_dev
+ */
+static PyObject *py_pjsua_set_no_snd_dev
+(PyObject *pSelf, PyObject *pArgs)
+{
+
+ PyObj_pjmedia_port * obj;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, ""))
+ {
+ return NULL;
+ }
+
+ obj = (PyObj_pjmedia_port *)PyType_GenericNew
+ (&PyTyp_pjmedia_port, NULL, NULL);
+ obj->port = pjsua_set_no_snd_dev();
+ return Py_BuildValue("O", obj);
+}
+
+/*
+ * py_pjsua_set_ec
+ */
+static PyObject *py_pjsua_set_ec
+(PyObject *pSelf, PyObject *pArgs)
+{
+ int options;
+ int tail_ms;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "ii", &tail_ms, &options))
+ {
+ return NULL;
+ }
+
+ status = pjsua_set_ec(tail_ms, options);
+
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_get_ec_tail
+ */
+static PyObject *py_pjsua_get_ec_tail
+(PyObject *pSelf, PyObject *pArgs)
+{
+
+ int status;
+ unsigned p_tail_ms;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, ""))
+ {
+ return NULL;
+ }
+
+ status = pjsua_get_ec_tail(&p_tail_ms);
+
+
+ return Py_BuildValue("i", p_tail_ms);
+}
+
+/*
+ * py_pjsua_enum_codecs
+ * !modified @ 261206
+ */
+static PyObject *py_pjsua_enum_codecs(PyObject *pSelf, PyObject *pArgs)
+{
+ pj_status_t status;
+ PyObject *list;
+
+ pjsua_codec_info info[PJMEDIA_CODEC_MGR_MAX_CODECS];
+ unsigned c, i;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, ""))
+ {
+ return NULL;
+ }
+
+ c = PJ_ARRAY_SIZE(info);
+ status = pjsua_enum_codecs(info, &c);
+
+ list = PyList_New(c);
+ for (i = 0; i < c; i++)
+ {
+ int ret;
+ int j;
+ PyObj_pjsua_codec_info * obj;
+ obj = (PyObj_pjsua_codec_info *)codec_info_new
+ (&PyTyp_pjsua_codec_info, NULL, NULL);
+ obj->codec_id = PyString_FromStringAndSize
+ (info[i].codec_id.ptr, info[i].codec_id.slen);
+ obj->priority = info[i].priority;
+ for (j = 0; j < 32; j++)
+ {
+ obj->buf_[j] = info[i].buf_[j];
+ }
+ ret = PyList_SetItem(list, i, (PyObject *)obj);
+ if (ret == -1) {
+ return NULL;
+ }
+ }
+
+
+ return Py_BuildValue("O",list);
+}
+
+/*
+ * py_pjsua_codec_set_priority
+ */
+static PyObject *py_pjsua_codec_set_priority
+(PyObject *pSelf, PyObject *pArgs)
+{
+
+ int status;
+ PyObject * id;
+ pj_str_t str;
+ pj_uint8_t priority;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "OB", &id, &priority))
+ {
+ return NULL;
+ }
+ str.ptr = PyString_AsString(id);
+ str.slen = strlen(PyString_AsString(id));
+ status = pjsua_codec_set_priority(&str, priority);
+
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_codec_get_param
+ */
+static PyObject *py_pjsua_codec_get_param
+(PyObject *pSelf, PyObject *pArgs)
+{
+
+ int status;
+ PyObject * id;
+ pj_str_t str;
+ pjmedia_codec_param param;
+ PyObj_pjmedia_codec_param *obj;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "O", &id))
+ {
+ return NULL;
+ }
+ str.ptr = PyString_AsString(id);
+ str.slen = strlen(PyString_AsString(id));
+ status = pjsua_codec_get_param(&str, &param);
+ obj = (PyObj_pjmedia_codec_param *)pjmedia_codec_param_new
+ (&PyTyp_pjmedia_codec_param, NULL, NULL);
+ obj->info->avg_bps = param.info.avg_bps;
+ obj->info->channel_cnt = param.info.channel_cnt;
+ obj->info->clock_rate = param.info.clock_rate;
+ obj->info->frm_ptime = param.info.frm_ptime;
+ obj->info->pcm_bits_per_sample = param.info.pcm_bits_per_sample;
+ obj->info->pt = param.info.pt;
+ obj->setting->cng = param.setting.cng;
+ //deprecated:
+ //obj->setting->dec_fmtp_mode = param.setting.dec_fmtp_mode;
+ //obj->setting->enc_fmtp_mode = param.setting.enc_fmtp_mode;
+ obj->setting->frm_per_pkt = param.setting.frm_per_pkt;
+ obj->setting->penh = param.setting.penh;
+ obj->setting->plc = param.setting.plc;
+ obj->setting->reserved = param.setting.reserved;
+ obj->setting->vad = param.setting.vad;
+
+ return Py_BuildValue("O", obj);
+}
+/*
+ * py_pjsua_codec_set_param
+ */
+static PyObject *py_pjsua_codec_set_param
+(PyObject *pSelf, PyObject *pArgs)
+{
+
+ int status;
+ PyObject * id;
+ pj_str_t str;
+ pjmedia_codec_param param;
+ PyObject * tmpObj;
+ PyObj_pjmedia_codec_param *obj;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "OO", &id, &tmpObj))
+ {
+ return NULL;
+ }
+
+ str.ptr = PyString_AsString(id);
+ str.slen = strlen(PyString_AsString(id));
+ if (tmpObj != Py_None)
+ {
+ obj = (PyObj_pjmedia_codec_param *)tmpObj;
+ param.info.avg_bps = obj->info->avg_bps;
+ param.info.channel_cnt = obj->info->channel_cnt;
+ param.info.clock_rate = obj->info->clock_rate;
+ param.info.frm_ptime = obj->info->frm_ptime;
+ param.info.pcm_bits_per_sample = obj->info->pcm_bits_per_sample;
+ param.info.pt = obj->info->pt;
+ param.setting.cng = obj->setting->cng;
+ //Deprecated:
+ //param.setting.dec_fmtp_mode = obj->setting->dec_fmtp_mode;
+ //param.setting.enc_fmtp_mode = obj->setting->enc_fmtp_mode;
+ param.setting.frm_per_pkt = obj->setting->frm_per_pkt;
+ param.setting.penh = obj->setting->penh;
+ param.setting.plc = obj->setting->plc;
+ param.setting.reserved = obj->setting->reserved;
+ param.setting.vad = obj->setting->vad;
+ status = pjsua_codec_set_param(&str, &param);
+ } else {
+ status = pjsua_codec_set_param(&str, NULL);
+ }
+ return Py_BuildValue("i", status);
+}
+
+static char pjsua_conf_get_max_ports_doc[] =
+ "int py_pjsua.conf_get_max_ports () "
+ "Get maxinum number of conference ports.";
+static char pjsua_conf_get_active_ports_doc[] =
+ "int py_pjsua.conf_get_active_ports () "
+ "Get current number of active ports in the bridge.";
+static char pjsua_enum_conf_ports_doc[] =
+ "int[] py_pjsua.enum_conf_ports () "
+ "Enumerate all conference ports.";
+static char pjsua_conf_get_port_info_doc[] =
+ "py_pjsua.Conf_Port_Info py_pjsua.conf_get_port_info (int id) "
+ "Get information about the specified conference port";
+static char pjsua_conf_add_port_doc[] =
+ "int, int py_pjsua.conf_add_port "
+ "(py_pjsua.Pj_Pool pool, py_pjsua.PJMedia_Port port) "
+ "Add arbitrary media port to PJSUA's conference bridge. "
+ "Application can use this function to add the media port "
+ "that it creates. For media ports that are created by PJSUA-LIB "
+ "(such as calls, file player, or file recorder), PJSUA-LIB will "
+ "automatically add the port to the bridge.";
+static char pjsua_conf_remove_port_doc[] =
+ "int py_pjsua.conf_remove_port (int id) "
+ "Remove arbitrary slot from the conference bridge. "
+ "Application should only call this function "
+ "if it registered the port manually.";
+static char pjsua_conf_connect_doc[] =
+ "int py_pjsua.conf_connect (int source, int sink) "
+ "Establish unidirectional media flow from souce to sink. "
+ "One source may transmit to multiple destinations/sink. "
+ "And if multiple sources are transmitting to the same sink, "
+ "the media will be mixed together. Source and sink may refer "
+ "to the same ID, effectively looping the media. "
+ "If bidirectional media flow is desired, application "
+ "needs to call this function twice, with the second "
+ "one having the arguments reversed.";
+static char pjsua_conf_disconnect_doc[] =
+ "int py_pjsua.conf_disconnect (int source, int sink) "
+ "Disconnect media flow from the source to destination port.";
+static char pjsua_player_create_doc[] =
+ "int, int py_pjsua.player_create (string filename, int options) "
+ "Create a file player, and automatically connect "
+ "this player to the conference bridge.";
+static char pjsua_player_get_conf_port_doc[] =
+ "int py_pjsua.player_get_conf_port (int) "
+ "Get conference port ID associated with player.";
+static char pjsua_player_set_pos_doc[] =
+ "int py_pjsua.player_set_pos (int id, int samples) "
+ "Set playback position.";
+static char pjsua_player_destroy_doc[] =
+ "int py_pjsua.player_destroy (int id) "
+ "Close the file, remove the player from the bridge, "
+ "and free resources associated with the file player.";
+static char pjsua_recorder_create_doc[] =
+ "int, int py_pjsua.recorder_create (string filename, "
+ "int enc_type, int enc_param, int max_size, int options) "
+ "Create a file recorder, and automatically connect this recorder "
+ "to the conference bridge. The recorder currently supports recording "
+ "WAV file, and on Windows, MP3 file. The type of the recorder to use "
+ "is determined by the extension of the file (e.g. '.wav' or '.mp3').";
+static char pjsua_recorder_get_conf_port_doc[] =
+ "int py_pjsua.recorder_get_conf_port (int id) "
+ "Get conference port associated with recorder.";
+static char pjsua_recorder_destroy_doc[] =
+ "int py_pjsua.recorder_destroy (int id) "
+ "Destroy recorder (this will complete recording).";
+static char pjsua_enum_snd_devs_doc[] =
+ "py_pjsua.PJMedia_Snd_Dev_Info[] py_pjsua.enum_snd_devs (int count) "
+ "Enum sound devices.";
+static char pjsua_get_snd_dev_doc[] =
+ "int, int py_pjsua.get_snd_dev () "
+ "Get currently active sound devices. "
+ "If sound devices has not been created "
+ "(for example when pjsua_start() is not called), "
+ "it is possible that the function returns "
+ "PJ_SUCCESS with -1 as device IDs.";
+static char pjsua_set_snd_dev_doc[] =
+ "int py_pjsua.set_snd_dev (int capture_dev, int playback_dev) "
+ "Select or change sound device. Application may call this function "
+ "at any time to replace current sound device.";
+static char pjsua_set_null_snd_dev_doc[] =
+ "int py_pjsua.set_null_snd_dev () "
+ "Set pjsua to use null sound device. The null sound device only "
+ "provides the timing needed by the conference bridge, and will not "
+ "interract with any hardware.";
+static char pjsua_set_no_snd_dev_doc[] =
+ "py_pjsua.PJMedia_Port py_pjsua.set_no_snd_dev () "
+ "Disconnect the main conference bridge from any sound devices, "
+ "and let application connect the bridge to it's "
+ "own sound device/master port.";
+static char pjsua_set_ec_doc[] =
+ "int py_pjsua.set_ec (int tail_ms, int options) "
+ "Configure the echo canceller tail length of the sound port.";
+static char pjsua_get_ec_tail_doc[] =
+ "int py_pjsua.get_ec_tail () "
+ "Get current echo canceller tail length.";
+static char pjsua_enum_codecs_doc[] =
+ "py_pjsua.Codec_Info[] py_pjsua.enum_codecs () "
+ "Enum all supported codecs in the system.";
+static char pjsua_codec_set_priority_doc[] =
+ "int py_pjsua.codec_set_priority (string id, int priority) "
+ "Change codec priority.";
+static char pjsua_codec_get_param_doc[] =
+ "py_pjsua.PJMedia_Codec_Param py_pjsua.codec_get_param (string id) "
+ "Get codec parameters";
+static char pjsua_codec_set_param_doc[] =
+ "int py_pjsua.codec_set_param (string id, "
+ "py_pjsua.PJMedia_Codec_Param param) "
+ "Set codec parameters.";
+
+/* END OF LIB MEDIA */
+
+/* LIB CALL */
+
+/*
+ * PyObj_pj_time_val
+ * PJ Time Val
+ */
+typedef struct
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+ long sec;
+ long msec;
+
+} PyObj_pj_time_val;
+
+
+
+/*
+ * pj_time_val_members
+ */
+static PyMemberDef pj_time_val_members[] =
+{
+
+ {
+ "sec", T_INT,
+ offsetof(PyObj_pj_time_val, sec), 0,
+ "The seconds part of the time"
+ },
+ {
+ "msec", T_INT,
+ offsetof(PyObj_pj_time_val, sec), 0,
+ "The milliseconds fraction of the time"
+ },
+
+
+ {NULL} /* Sentinel */
+};
+
+
+
+
+/*
+ * PyTyp_pj_time_val
+ */
+static PyTypeObject PyTyp_pj_time_val =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "py_pjsua.PJ_Time_Val", /*tp_name*/
+ sizeof(PyObj_pj_time_val), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ 0,/*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "PJ Time Val objects", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ pj_time_val_members, /* tp_members */
+
+
+};
+
+/*
+ * PyObj_pjsua_call_info
+ * Call Info
+ */
+typedef struct
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+
+ int id;
+ int role;
+ int acc_id;
+ PyObject * local_info;
+ PyObject * local_contact;
+ PyObject * remote_info;
+ PyObject * remote_contact;
+ PyObject * call_id;
+ int state;
+ PyObject * state_text;
+ int last_status;
+ PyObject * last_status_text;
+ int media_status;
+ int media_dir;
+ int conf_slot;
+ PyObj_pj_time_val * connect_duration;
+ PyObj_pj_time_val * total_duration;
+ struct {
+ char local_info[128];
+ char local_contact[128];
+ char remote_info[128];
+ char remote_contact[128];
+ char call_id[128];
+ char last_status_text[128];
+ } buf_;
+
+} PyObj_pjsua_call_info;
+
+
+/*
+ * call_info_dealloc
+ * deletes a call_info from memory
+ */
+static void call_info_dealloc(PyObj_pjsua_call_info* self)
+{
+ Py_XDECREF(self->local_info);
+ Py_XDECREF(self->local_contact);
+ Py_XDECREF(self->remote_info);
+ Py_XDECREF(self->remote_contact);
+ Py_XDECREF(self->call_id);
+ Py_XDECREF(self->state_text);
+ Py_XDECREF(self->last_status_text);
+ Py_XDECREF(self->connect_duration);
+ Py_XDECREF(self->total_duration);
+ self->ob_type->tp_free((PyObject*)self);
+}
+
+
+/*
+ * call_info_new
+ * constructor for call_info object
+ */
+static PyObject * call_info_new(PyTypeObject *type, PyObject *args,
+ PyObject *kwds)
+{
+ PyObj_pjsua_call_info *self;
+
+ PJ_UNUSED_ARG(args);
+ PJ_UNUSED_ARG(kwds);
+
+ self = (PyObj_pjsua_call_info *)type->tp_alloc(type, 0);
+ if (self != NULL)
+ {
+ self->local_info = PyString_FromString("");
+ if (self->local_info == NULL)
+ {
+ Py_DECREF(self);
+ return NULL;
+ }
+ self->local_contact = PyString_FromString("");
+ if (self->local_contact == NULL)
+ {
+ Py_DECREF(self);
+ return NULL;
+ }
+ self->remote_info = PyString_FromString("");
+ if (self->remote_info == NULL)
+ {
+ Py_DECREF(self);
+ return NULL;
+ }
+ self->remote_contact = PyString_FromString("");
+ if (self->remote_contact == NULL)
+ {
+ Py_DECREF(self);
+ return NULL;
+ }
+ self->call_id = PyString_FromString("");
+ if (self->call_id == NULL)
+ {
+ Py_DECREF(self);
+ return NULL;
+ }
+ self->state_text = PyString_FromString("");
+ if (self->state_text == NULL)
+ {
+ Py_DECREF(self);
+ return NULL;
+ }
+ self->last_status_text = PyString_FromString("");
+ if (self->last_status_text == NULL)
+ {
+ Py_DECREF(self);
+ return NULL;
+ }
+ self->connect_duration = (PyObj_pj_time_val *)PyType_GenericNew
+ (&PyTyp_pj_time_val,NULL,NULL);
+ if (self->connect_duration == NULL)
+ {
+ Py_DECREF(self);
+ return NULL;
+ }
+ self->total_duration = (PyObj_pj_time_val *)PyType_GenericNew
+ (&PyTyp_pj_time_val,NULL,NULL);
+ if (self->total_duration == NULL)
+ {
+ Py_DECREF(self);
+ return NULL;
+ }
+ }
+ return (PyObject *)self;
+}
+
+/*
+ * call_info_members
+ */
+static PyMemberDef call_info_members[] =
+{
+ {
+ "id", T_INT,
+ offsetof(PyObj_pjsua_call_info, id), 0,
+ "Call identification"
+ },
+ {
+ "role", T_INT,
+ offsetof(PyObj_pjsua_call_info, role), 0,
+ "Initial call role (UAC == caller)"
+ },
+ {
+ "acc_id", T_INT,
+ offsetof(PyObj_pjsua_call_info, acc_id), 0,
+ "The account ID where this call belongs."
+ },
+ {
+ "local_info", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_call_info, local_info), 0,
+ "Local URI"
+ },
+ {
+ "local_contact", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_call_info, local_contact), 0,
+ "Local Contact"
+ },
+ {
+ "remote_info", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_call_info, remote_info), 0,
+ "Remote URI"
+ },
+ {
+ "remote_contact", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_call_info, remote_contact), 0,
+ "Remote Contact"
+ },
+ {
+ "call_id", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_call_info, call_id), 0,
+ "Dialog Call-ID string"
+ },
+ {
+ "state", T_INT,
+ offsetof(PyObj_pjsua_call_info, state), 0,
+ "Call state"
+ },
+ {
+ "state_text", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_call_info, state_text), 0,
+ "Text describing the state "
+ },
+ {
+ "last_status", T_INT,
+ offsetof(PyObj_pjsua_call_info, last_status), 0,
+ "Last status code heard, which can be used as cause code"
+ },
+ {
+ "last_status_text", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_call_info, last_status_text), 0,
+ "The reason phrase describing the status."
+ },
+ {
+ "media_status", T_INT,
+ offsetof(PyObj_pjsua_call_info, media_status), 0,
+ "Call media status."
+ },
+ {
+ "media_dir", T_INT,
+ offsetof(PyObj_pjsua_call_info, media_dir), 0,
+ "Media direction"
+ },
+ {
+ "conf_slot", T_INT,
+ offsetof(PyObj_pjsua_call_info, conf_slot), 0,
+ "The conference port number for the call"
+ },
+ {
+ "connect_duration", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_call_info, connect_duration), 0,
+ "Up-to-date call connected duration(zero when call is not established)"
+ },
+ {
+ "total_duration", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_call_info, total_duration), 0,
+ "Total call duration, including set-up time"
+ },
+
+ {NULL} /* Sentinel */
+};
+
+
+
+
+/*
+ * PyTyp_pjsua_call_info
+ */
+static PyTypeObject PyTyp_pjsua_call_info =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "py_pjsua.Call_Info", /*tp_name*/
+ sizeof(PyObj_pjsua_call_info), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor)call_info_dealloc,/*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "Call Info objects", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ call_info_members, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ call_info_new, /* tp_new */
+
+};
+
+/*
+ * py_pjsua_call_get_max_count
+ */
+static PyObject *py_pjsua_call_get_max_count
+(PyObject *pSelf, PyObject *pArgs)
+{
+ int count;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, ""))
+ {
+ return NULL;
+ }
+
+ count = pjsua_call_get_max_count();
+
+
+ return Py_BuildValue("i", count);
+}
+
+/*
+ * py_pjsua_call_get_count
+ */
+static PyObject *py_pjsua_call_get_count
+(PyObject *pSelf, PyObject *pArgs)
+{
+
+ int count;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, ""))
+ {
+ return NULL;
+ }
+
+ count = pjsua_call_get_count();
+
+
+ return Py_BuildValue("i", count);
+}
+
+/*
+ * py_pjsua_enum_calls
+ */
+static PyObject *py_pjsua_enum_calls(PyObject *pSelf, PyObject *pArgs)
+{
+ pj_status_t status;
+ PyObject *list;
+
+ pjsua_transport_id id[PJSUA_MAX_CALLS];
+ unsigned c, i;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, ""))
+ {
+ return NULL;
+ }
+
+ c = PJ_ARRAY_SIZE(id);
+ status = pjsua_enum_calls(id, &c);
+
+ list = PyList_New(c);
+ for (i = 0; i < c; i++)
+ {
+ int ret = PyList_SetItem(list, i, Py_BuildValue("i", id[i]));
+ if (ret == -1)
+ {
+ return NULL;
+ }
+ }
+
+ return Py_BuildValue("O",list);
+}
+
+/*
+ * py_pjsua_call_make_call
+ */
+static PyObject *py_pjsua_call_make_call
+(PyObject *pSelf, PyObject *pArgs)
+{
+ int status;
+ int acc_id;
+ pj_str_t dst_uri;
+ PyObject * sd;
+ unsigned options;
+ pjsua_msg_data msg_data;
+ PyObject * omdObj;
+ PyObj_pjsua_msg_data * omd;
+ int user_data;
+ int call_id;
+ pj_pool_t * pool;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple
+ (pArgs, "iOIiO", &acc_id, &sd, &options, &user_data, &omdObj))
+ {
+ return NULL;
+ }
+
+ dst_uri.ptr = PyString_AsString(sd);
+ dst_uri.slen = strlen(PyString_AsString(sd));
+ if (omdObj != Py_None)
+ {
+ omd = (PyObj_pjsua_msg_data *)omdObj;
+ msg_data.content_type.ptr = PyString_AsString(omd->content_type);
+ msg_data.content_type.slen = strlen
+ (PyString_AsString(omd->content_type));
+ msg_data.msg_body.ptr = PyString_AsString(omd->msg_body);
+ msg_data.msg_body.slen = strlen(PyString_AsString(omd->msg_body));
+ pool = pjsua_pool_create("pjsua", POOL_SIZE, POOL_SIZE);
+ translate_hdr(pool, &msg_data.hdr_list, omd->hdr_list);
+ status = pjsua_call_make_call(acc_id, &dst_uri,
+ options, (void*)user_data, &msg_data, &call_id);
+ pj_pool_release(pool);
+ } else {
+
+ status = pjsua_call_make_call(acc_id, &dst_uri,
+ options, (void*)user_data, NULL, &call_id);
+ }
+
+ return Py_BuildValue("ii",status, call_id);
+
+}
+
+/*
+ * py_pjsua_call_is_active
+ */
+static PyObject *py_pjsua_call_is_active
+(PyObject *pSelf, PyObject *pArgs)
+{
+ int call_id;
+ int isActive;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &call_id))
+ {
+ return NULL;
+ }
+
+ isActive = pjsua_call_is_active(call_id);
+
+
+ return Py_BuildValue("i", isActive);
+}
+
+/*
+ * py_pjsua_call_has_media
+ */
+static PyObject *py_pjsua_call_has_media
+(PyObject *pSelf, PyObject *pArgs)
+{
+ int call_id;
+ int hasMedia;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &call_id))
+ {
+ return NULL;
+ }
+
+ hasMedia = pjsua_call_has_media(call_id);
+
+
+ return Py_BuildValue("i", hasMedia);
+}
+
+/*
+ * py_pjsua_call_get_conf_port
+ */
+static PyObject *py_pjsua_call_get_conf_port
+(PyObject *pSelf, PyObject *pArgs)
+{
+ int call_id;
+ int port_id;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &call_id))
+ {
+ return NULL;
+ }
+
+ port_id = pjsua_call_get_conf_port(call_id);
+
+
+ return Py_BuildValue("i", port_id);
+}
+
+/*
+ * py_pjsua_call_get_info
+ */
+static PyObject *py_pjsua_call_get_info
+(PyObject *pSelf, PyObject *pArgs)
+{
+ int call_id;
+ int status;
+ PyObj_pjsua_call_info * oi;
+ pjsua_call_info info;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &call_id))
+ {
+ return NULL;
+ }
+
+
+ status = pjsua_call_get_info(call_id, &info);
+ if (status == PJ_SUCCESS)
+ {
+ oi = (PyObj_pjsua_call_info *)call_info_new(&PyTyp_pjsua_call_info, NULL, NULL);
+ oi->acc_id = info.acc_id;
+ pj_ansi_snprintf(oi->buf_.call_id, sizeof(oi->buf_.call_id),
+ "%.*s", (int)info.call_id.slen, info.call_id.ptr);
+ pj_ansi_snprintf(oi->buf_.last_status_text,
+ sizeof(oi->buf_.last_status_text),
+ "%.*s", (int)info.last_status_text.slen, info.last_status_text.ptr);
+ pj_ansi_snprintf(oi->buf_.local_contact, sizeof(oi->buf_.local_contact),
+ "%.*s", (int)info.local_contact.slen, info.local_contact.ptr);
+ pj_ansi_snprintf(oi->buf_.local_info, sizeof(oi->buf_.local_info),
+ "%.*s", (int)info.local_info.slen, info.local_info.ptr);
+ pj_ansi_snprintf(oi->buf_.remote_contact,
+ sizeof(oi->buf_.remote_contact),
+ "%.*s", (int)info.remote_contact.slen, info.remote_contact.ptr);
+ pj_ansi_snprintf(oi->buf_.remote_info, sizeof(oi->buf_.remote_info),
+ "%.*s", (int)info.remote_info.slen, info.remote_info.ptr);
+
+ oi->call_id = PyString_FromStringAndSize(info.call_id.ptr,
+ info.call_id.slen);
+ oi->conf_slot = info.conf_slot;
+ oi->connect_duration->sec = info.connect_duration.sec;
+ oi->connect_duration->msec = info.connect_duration.msec;
+ oi->total_duration->sec = info.total_duration.sec;
+ oi->total_duration->msec = info.total_duration.msec;
+ oi->id = info.id;
+ oi->last_status = info.last_status;
+ oi->last_status_text = PyString_FromStringAndSize(
+ info.last_status_text.ptr, info.last_status_text.slen);
+ oi->local_contact = PyString_FromStringAndSize(
+ info.local_contact.ptr, info.local_contact.slen);
+ oi->local_info = PyString_FromStringAndSize(
+ info.local_info.ptr, info.local_info.slen);
+ oi->remote_contact = PyString_FromStringAndSize(
+ info.remote_contact.ptr, info.remote_contact.slen);
+ oi->remote_info = PyString_FromStringAndSize(
+ info.remote_info.ptr, info.remote_info.slen);
+ oi->media_dir = info.media_dir;
+ oi->media_status = info.media_status;
+ oi->role = info.role;
+ oi->state = info.state;
+ oi->state_text = PyString_FromStringAndSize(
+ info.state_text.ptr, info.state_text.slen);
+
+ return Py_BuildValue("O", oi);
+ } else {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+}
+
+/*
+ * py_pjsua_call_set_user_data
+ */
+static PyObject *py_pjsua_call_set_user_data
+(PyObject *pSelf, PyObject *pArgs)
+{
+ int call_id;
+ int user_data;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "ii", &call_id, &user_data))
+ {
+ return NULL;
+ }
+
+ status = pjsua_call_set_user_data(call_id, (void*)user_data);
+
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_call_get_user_data
+ */
+static PyObject *py_pjsua_call_get_user_data
+(PyObject *pSelf, PyObject *pArgs)
+{
+ int call_id;
+ void * user_data;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &call_id))
+ {
+ return NULL;
+ }
+
+ user_data = pjsua_call_get_user_data(call_id);
+
+
+ return Py_BuildValue("i", (int)user_data);
+}
+
+/*
+ * py_pjsua_call_answer
+ */
+static PyObject *py_pjsua_call_answer
+(PyObject *pSelf, PyObject *pArgs)
+{
+ int status;
+ int call_id;
+ pj_str_t * reason, tmp_reason;
+ PyObject * sr;
+ unsigned code;
+ pjsua_msg_data msg_data;
+ PyObject * omdObj;
+ PyObj_pjsua_msg_data * omd;
+ pj_pool_t * pool;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "iIOO", &call_id, &code, &sr, &omdObj))
+ {
+ return NULL;
+ }
+ if (sr == Py_None)
+ {
+ reason = NULL;
+ } else {
+ reason = &tmp_reason;
+ tmp_reason.ptr = PyString_AsString(sr);
+ tmp_reason.slen = strlen(PyString_AsString(sr));
+ }
+ if (omdObj != Py_None)
+ {
+ omd = (PyObj_pjsua_msg_data *)omdObj;
+ msg_data.content_type.ptr = PyString_AsString(omd->content_type);
+ msg_data.content_type.slen = strlen
+ (PyString_AsString(omd->content_type));
+ msg_data.msg_body.ptr = PyString_AsString(omd->msg_body);
+ msg_data.msg_body.slen = strlen(PyString_AsString(omd->msg_body));
+ pool = pjsua_pool_create("pjsua", POOL_SIZE, POOL_SIZE);
+ translate_hdr(pool, &msg_data.hdr_list, omd->hdr_list);
+
+ status = pjsua_call_answer(call_id, code, reason, &msg_data);
+
+ pj_pool_release(pool);
+ } else {
+
+ status = pjsua_call_answer(call_id, code, reason, NULL);
+
+ }
+
+ return Py_BuildValue("i",status);
+}
+
+/*
+ * py_pjsua_call_hangup
+ */
+static PyObject *py_pjsua_call_hangup
+(PyObject *pSelf, PyObject *pArgs)
+{
+ int status;
+ int call_id;
+ pj_str_t * reason, tmp_reason;
+ PyObject * sr;
+ unsigned code;
+ pjsua_msg_data msg_data;
+ PyObject * omdObj;
+ PyObj_pjsua_msg_data * omd;
+ pj_pool_t * pool = NULL;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "iIOO", &call_id, &code, &sr, &omdObj))
+ {
+ return NULL;
+ }
+ if (sr == Py_None)
+ {
+ reason = NULL;
+ } else {
+ reason = &tmp_reason;
+ tmp_reason.ptr = PyString_AsString(sr);
+ tmp_reason.slen = strlen(PyString_AsString(sr));
+ }
+ if (omdObj != Py_None)
+ {
+ omd = (PyObj_pjsua_msg_data *)omdObj;
+ msg_data.content_type.ptr = PyString_AsString(omd->content_type);
+ msg_data.content_type.slen = strlen
+ (PyString_AsString(omd->content_type));
+ msg_data.msg_body.ptr = PyString_AsString(omd->msg_body);
+ msg_data.msg_body.slen = strlen(PyString_AsString(omd->msg_body));
+ pool = pjsua_pool_create("pjsua", POOL_SIZE, POOL_SIZE);
+ translate_hdr(pool, &msg_data.hdr_list, omd->hdr_list);
+ status = pjsua_call_hangup(call_id, code, reason, &msg_data);
+ pj_pool_release(pool);
+ } else {
+ status = pjsua_call_hangup(call_id, code, reason, NULL);
+ }
+
+ return Py_BuildValue("i",status);
+}
+
+/*
+ * py_pjsua_call_set_hold
+ */
+static PyObject *py_pjsua_call_set_hold
+(PyObject *pSelf, PyObject *pArgs)
+{
+ int status;
+ int call_id;
+ pjsua_msg_data msg_data;
+ PyObject * omdObj;
+ PyObj_pjsua_msg_data * omd;
+ pj_pool_t * pool;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "iO", &call_id, &omdObj))
+ {
+ return NULL;
+ }
+
+ if (omdObj != Py_None)
+ {
+ omd = (PyObj_pjsua_msg_data *)omdObj;
+ msg_data.content_type.ptr = PyString_AsString(omd->content_type);
+ msg_data.content_type.slen = strlen
+ (PyString_AsString(omd->content_type));
+ msg_data.msg_body.ptr = PyString_AsString(omd->msg_body);
+ msg_data.msg_body.slen = strlen(PyString_AsString(omd->msg_body));
+ pool = pjsua_pool_create("pjsua", POOL_SIZE, POOL_SIZE);
+ translate_hdr(pool, &msg_data.hdr_list, omd->hdr_list);
+ status = pjsua_call_set_hold(call_id, &msg_data);
+ pj_pool_release(pool);
+ } else {
+ status = pjsua_call_set_hold(call_id, NULL);
+ }
+ return Py_BuildValue("i",status);
+}
+
+/*
+ * py_pjsua_call_reinvite
+ */
+static PyObject *py_pjsua_call_reinvite
+(PyObject *pSelf, PyObject *pArgs)
+{
+ int status;
+ int call_id;
+ int unhold;
+ pjsua_msg_data msg_data;
+ PyObject * omdObj;
+ PyObj_pjsua_msg_data * omd;
+ pj_pool_t * pool;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "iiO", &call_id, &unhold, &omdObj))
+ {
+ return NULL;
+ }
+
+ if (omdObj != Py_None)
+ {
+ omd = (PyObj_pjsua_msg_data *)omdObj;
+ msg_data.content_type.ptr = PyString_AsString(omd->content_type);
+ msg_data.content_type.slen = strlen
+ (PyString_AsString(omd->content_type));
+ msg_data.msg_body.ptr = PyString_AsString(omd->msg_body);
+ msg_data.msg_body.slen = strlen(PyString_AsString(omd->msg_body));
+ pool = pjsua_pool_create("pjsua", POOL_SIZE, POOL_SIZE);
+ translate_hdr(pool, &msg_data.hdr_list, omd->hdr_list);
+ status = pjsua_call_reinvite(call_id, unhold, &msg_data);
+ pj_pool_release(pool);
+ } else {
+ status = pjsua_call_reinvite(call_id, unhold, NULL);
+ }
+ return Py_BuildValue("i",status);
+}
+
+/*
+ * py_pjsua_call_xfer
+ */
+static PyObject *py_pjsua_call_xfer
+(PyObject *pSelf, PyObject *pArgs)
+{
+ int status;
+ int call_id;
+ pj_str_t dest;
+ PyObject * sd;
+ pjsua_msg_data msg_data;
+ PyObject * omdObj;
+ PyObj_pjsua_msg_data * omd;
+ pj_pool_t * pool;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "iOO", &call_id, &sd, &omdObj))
+ {
+ return NULL;
+ }
+
+ dest.ptr = PyString_AsString(sd);
+ dest.slen = strlen(PyString_AsString(sd));
+
+ if (omdObj != Py_None)
+ {
+ omd = (PyObj_pjsua_msg_data *)omdObj;
+ msg_data.content_type.ptr = PyString_AsString(omd->content_type);
+ msg_data.content_type.slen = strlen
+ (PyString_AsString(omd->content_type));
+ msg_data.msg_body.ptr = PyString_AsString(omd->msg_body);
+ msg_data.msg_body.slen = strlen(PyString_AsString(omd->msg_body));
+ pool = pjsua_pool_create("pjsua", POOL_SIZE, POOL_SIZE);
+ translate_hdr(pool, &msg_data.hdr_list, omd->hdr_list);
+ status = pjsua_call_xfer(call_id, &dest, &msg_data);
+ pj_pool_release(pool);
+ } else {
+ status = pjsua_call_xfer(call_id, &dest, NULL);
+ }
+ return Py_BuildValue("i",status);
+}
+
+/*
+ * py_pjsua_call_xfer_replaces
+ */
+static PyObject *py_pjsua_call_xfer_replaces
+(PyObject *pSelf, PyObject *pArgs)
+{
+ int status;
+ int call_id;
+ int dest_call_id;
+ unsigned options;
+ pjsua_msg_data msg_data;
+ PyObject * omdObj;
+ PyObj_pjsua_msg_data * omd;
+ pj_pool_t * pool;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple
+ (pArgs, "iiIO", &call_id, &dest_call_id, &options, &omdObj))
+ {
+ return NULL;
+ }
+
+ if (omdObj != Py_None)
+ {
+ omd = (PyObj_pjsua_msg_data *)omdObj;
+ msg_data.content_type.ptr = PyString_AsString(omd->content_type);
+ msg_data.content_type.slen = strlen
+ (PyString_AsString(omd->content_type));
+ msg_data.msg_body.ptr = PyString_AsString(omd->msg_body);
+ msg_data.msg_body.slen = strlen(PyString_AsString(omd->msg_body));
+ pool = pjsua_pool_create("pjsua", POOL_SIZE, POOL_SIZE);
+ translate_hdr(pool, &msg_data.hdr_list, omd->hdr_list);
+ status = pjsua_call_xfer_replaces
+ (call_id, dest_call_id, options, &msg_data);
+ pj_pool_release(pool);
+ } else {
+ status = pjsua_call_xfer_replaces(call_id, dest_call_id,options, NULL);
+ }
+ return Py_BuildValue("i",status);
+}
+
+/*
+ * py_pjsua_call_dial_dtmf
+ */
+static PyObject *py_pjsua_call_dial_dtmf
+(PyObject *pSelf, PyObject *pArgs)
+{
+ int call_id;
+ PyObject * sd;
+ pj_str_t digits;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "iO", &call_id, &sd))
+ {
+ return NULL;
+ }
+ digits.ptr = PyString_AsString(sd);
+ digits.slen = strlen(PyString_AsString(sd));
+ status = pjsua_call_dial_dtmf(call_id, &digits);
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_call_send_im
+ */
+static PyObject *py_pjsua_call_send_im
+(PyObject *pSelf, PyObject *pArgs)
+{
+ int status;
+ int call_id;
+ pj_str_t content;
+ pj_str_t * mime_type, tmp_mime_type;
+ PyObject * sm;
+ PyObject * sc;
+ pjsua_msg_data msg_data;
+ PyObject * omdObj;
+ PyObj_pjsua_msg_data * omd;
+ int user_data;
+ pj_pool_t * pool;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple
+ (pArgs, "iOOOi", &call_id, &sm, &sc, &omdObj, &user_data))
+ {
+ return NULL;
+ }
+ if (sm == Py_None)
+ {
+ mime_type = NULL;
+ } else {
+ mime_type = &tmp_mime_type;
+ tmp_mime_type.ptr = PyString_AsString(sm);
+ tmp_mime_type.slen = strlen(PyString_AsString(sm));
+ }
+ content.ptr = PyString_AsString(sc);
+ content.slen = strlen(PyString_AsString(sc));
+
+ if (omdObj != Py_None)
+ {
+ omd = (PyObj_pjsua_msg_data *)omdObj;
+ msg_data.content_type.ptr = PyString_AsString(omd->content_type);
+ msg_data.content_type.slen = strlen
+ (PyString_AsString(omd->content_type));
+ msg_data.msg_body.ptr = PyString_AsString(omd->msg_body);
+ msg_data.msg_body.slen = strlen(PyString_AsString(omd->msg_body));
+ pool = pjsua_pool_create("pjsua", POOL_SIZE, POOL_SIZE);
+ translate_hdr(pool, &msg_data.hdr_list, omd->hdr_list);
+ status = pjsua_call_send_im
+ (call_id, mime_type, &content, &msg_data, (void *)user_data);
+ pj_pool_release(pool);
+ } else {
+ status = pjsua_call_send_im
+ (call_id, mime_type, &content, NULL, (void *)user_data);
+ }
+
+ return Py_BuildValue("i",status);
+}
+
+/*
+ * py_pjsua_call_send_typing_ind
+ */
+static PyObject *py_pjsua_call_send_typing_ind
+(PyObject *pSelf, PyObject *pArgs)
+{
+ int status;
+ int call_id;
+ int is_typing;
+ pjsua_msg_data msg_data;
+ PyObject * omdObj;
+ PyObj_pjsua_msg_data * omd;
+ pj_pool_t * pool;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "iiO", &call_id, &is_typing, &omdObj))
+ {
+ return NULL;
+ }
+
+ if (omdObj != Py_None)
+ {
+ omd = (PyObj_pjsua_msg_data *)omdObj;
+ msg_data.content_type.ptr = PyString_AsString(omd->content_type);
+ msg_data.content_type.slen = strlen
+ (PyString_AsString(omd->content_type));
+ msg_data.msg_body.ptr = PyString_AsString(omd->msg_body);
+ msg_data.msg_body.slen = strlen(PyString_AsString(omd->msg_body));
+ pool = pjsua_pool_create("pjsua", POOL_SIZE, POOL_SIZE);
+ translate_hdr(pool, &msg_data.hdr_list, omd->hdr_list);
+ status = pjsua_call_send_typing_ind(call_id, is_typing, &msg_data);
+ pj_pool_release(pool);
+ } else {
+ status = pjsua_call_send_typing_ind(call_id, is_typing, NULL);
+ }
+ return Py_BuildValue("i",status);
+}
+
+/*
+ * py_pjsua_call_hangup_all
+ */
+static PyObject *py_pjsua_call_hangup_all
+(PyObject *pSelf, PyObject *pArgs)
+{
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, ""))
+ {
+ return NULL;
+ }
+
+ pjsua_call_hangup_all();
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+/*
+ * py_pjsua_call_dump
+ */
+static PyObject *py_pjsua_call_dump
+(PyObject *pSelf, PyObject *pArgs)
+{
+ int call_id;
+ int with_media;
+ PyObject * sb;
+ PyObject * si;
+ char * buffer;
+ char * indent;
+ unsigned maxlen;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "iiIO", &call_id, &with_media, &maxlen, &si))
+ {
+ return NULL;
+ }
+ buffer = (char *) malloc (maxlen * sizeof(char));
+ indent = PyString_AsString(si);
+
+ status = pjsua_call_dump(call_id, with_media, buffer, maxlen, indent);
+ sb = PyString_FromStringAndSize(buffer, maxlen);
+ free(buffer);
+ return Py_BuildValue("O", sb);
+}
+
+
+/*
+ * py_pjsua_dump
+ * Dump application states.
+ */
+static PyObject *py_pjsua_dump(PyObject *pSelf, PyObject *pArgs)
+{
+ unsigned old_decor;
+ char buf[1024];
+ int detail;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &detail))
+ {
+ return NULL;
+ }
+
+ PJ_LOG(3,(THIS_FILE, "Start dumping application states:"));
+
+ old_decor = pj_log_get_decor();
+ pj_log_set_decor(old_decor & (PJ_LOG_HAS_NEWLINE | PJ_LOG_HAS_CR));
+
+ if (detail)
+ pj_dump_config();
+
+ pjsip_endpt_dump(pjsua_get_pjsip_endpt(), detail);
+ pjmedia_endpt_dump(pjsua_get_pjmedia_endpt());
+ pjsip_tsx_layer_dump(detail);
+ pjsip_ua_dump(detail);
+
+
+ /* Dump all invite sessions: */
+ PJ_LOG(3,(THIS_FILE, "Dumping invite sessions:"));
+
+ if (pjsua_call_get_count() == 0) {
+
+ PJ_LOG(3,(THIS_FILE, " - no sessions -"));
+
+ } else {
+ unsigned i, max;
+
+ max = pjsua_call_get_max_count();
+ for (i=0; i<max; ++i) {
+ if (pjsua_call_is_active(i)) {
+ pjsua_call_dump(i, detail, buf, sizeof(buf), " ");
+ PJ_LOG(3,(THIS_FILE, "%s", buf));
+ }
+ }
+ }
+
+ /* Dump presence status */
+ pjsua_pres_dump(detail);
+
+ pj_log_set_decor(old_decor);
+ PJ_LOG(3,(THIS_FILE, "Dump complete"));
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+
+static char pjsua_call_get_max_count_doc[] =
+ "int py_pjsua.call_get_max_count () "
+ "Get maximum number of calls configured in pjsua.";
+static char pjsua_call_get_count_doc[] =
+ "int py_pjsua.call_get_count () "
+ "Get number of currently active calls.";
+static char pjsua_enum_calls_doc[] =
+ "int[] py_pjsua.enum_calls () "
+ "Get maximum number of calls configured in pjsua.";
+static char pjsua_call_make_call_doc[] =
+ "int,int py_pjsua.call_make_call (int acc_id, string dst_uri, int options,"
+ "int user_data, py_pjsua.Msg_Data msg_data) "
+ "Make outgoing call to the specified URI using the specified account.";
+static char pjsua_call_is_active_doc[] =
+ "int py_pjsua.call_is_active (int call_id) "
+ "Check if the specified call has active INVITE session and the INVITE "
+ "session has not been disconnected.";
+static char pjsua_call_has_media_doc[] =
+ "int py_pjsua.call_has_media (int call_id) "
+ "Check if call has an active media session.";
+static char pjsua_call_get_conf_port_doc[] =
+ "int py_pjsua.call_get_conf_port (int call_id) "
+ "Get the conference port identification associated with the call.";
+static char pjsua_call_get_info_doc[] =
+ "py_pjsua.Call_Info py_pjsua.call_get_info (int call_id) "
+ "Obtain detail information about the specified call.";
+static char pjsua_call_set_user_data_doc[] =
+ "int py_pjsua.call_set_user_data (int call_id, int user_data) "
+ "Attach application specific data to the call.";
+static char pjsua_call_get_user_data_doc[] =
+ "int py_pjsua.call_get_user_data (int call_id) "
+ "Get user data attached to the call.";
+static char pjsua_call_answer_doc[] =
+ "int py_pjsua.call_answer (int call_id, int code, string reason, "
+ "py_pjsua.Msg_Data msg_data) "
+ "Send response to incoming INVITE request.";
+static char pjsua_call_hangup_doc[] =
+ "int py_pjsua.call_hangup (int call_id, int code, string reason, "
+ "py_pjsua.Msg_Data msg_data) "
+ "Hangup call by using method that is appropriate according "
+ "to the call state.";
+static char pjsua_call_set_hold_doc[] =
+ "int py_pjsua.call_set_hold (int call_id, py_pjsua.Msg_Data msg_data) "
+ "Put the specified call on hold.";
+static char pjsua_call_reinvite_doc[] =
+ "int py_pjsua.call_reinvite (int call_id, int unhold, "
+ "py_pjsua.Msg_Data msg_data) "
+ "Send re-INVITE (to release hold).";
+static char pjsua_call_xfer_doc[] =
+ "int py_pjsua.call_xfer (int call_id, string dest, "
+ "py_pjsua.Msg_Data msg_data) "
+ "Initiate call transfer to the specified address. "
+ "This function will send REFER request to instruct remote call party "
+ "to initiate a new INVITE session to the specified destination/target.";
+static char pjsua_call_xfer_replaces_doc[] =
+ "int py_pjsua.call_xfer_replaces (int call_id, int dest_call_id, "
+ "int options, py_pjsua.Msg_Data msg_data) "
+ "Initiate attended call transfer. This function will send REFER request "
+ "to instruct remote call party to initiate new INVITE session to the URL "
+ "of dest_call_id. The party at dest_call_id then should 'replace' the call"
+ "with us with the new call from the REFER recipient.";
+static char pjsua_call_dial_dtmf_doc[] =
+ "int py_pjsua.call_dial_dtmf (int call_id, string digits) "
+ "Send DTMF digits to remote using RFC 2833 payload formats.";
+static char pjsua_call_send_im_doc[] =
+ "int py_pjsua.call_send_im (int call_id, string mime_type, string content,"
+ "py_pjsua.Msg_Data msg_data, int user_data) "
+ "Send instant messaging inside INVITE session.";
+static char pjsua_call_send_typing_ind_doc[] =
+ "int py_pjsua.call_send_typing_ind (int call_id, int is_typing, "
+ "py_pjsua.Msg_Data msg_data) "
+ "Send IM typing indication inside INVITE session.";
+static char pjsua_call_hangup_all_doc[] =
+ "void py_pjsua.call_hangup_all () "
+ "Terminate all calls.";
+static char pjsua_call_dump_doc[] =
+ "int py_pjsua.call_dump (int call_id, int with_media, int maxlen, "
+ "string indent) "
+ "Dump call and media statistics to string.";
+
+/* END OF LIB CALL */
+
+/*
+ * Map of function names to functions
+ */
+static PyMethodDef py_pjsua_methods[] =
+{
+ {
+ "thread_register", py_pjsua_thread_register, METH_VARARGS,
+ pjsua_thread_register_doc
+ },
+ {
+ "perror", py_pjsua_perror, METH_VARARGS, pjsua_perror_doc
+ },
+ {
+ "create", py_pjsua_create, METH_VARARGS, pjsua_create_doc
+ },
+ {
+ "init", py_pjsua_init, METH_VARARGS, pjsua_init_doc
+ },
+ {
+ "start", py_pjsua_start, METH_VARARGS, pjsua_start_doc
+ },
+ {
+ "destroy", py_pjsua_destroy, METH_VARARGS, pjsua_destroy_doc
+ },
+ {
+ "handle_events", py_pjsua_handle_events, METH_VARARGS,
+ pjsua_handle_events_doc
+ },
+ {
+ "verify_sip_url", py_pjsua_verify_sip_url, METH_VARARGS,
+ pjsua_verify_sip_url_doc
+ },
+ {
+ "pool_create", py_pjsua_pool_create, METH_VARARGS,
+ pjsua_pool_create_doc
+ },
+ {
+ "get_pjsip_endpt", py_pjsua_get_pjsip_endpt, METH_VARARGS,
+ pjsua_get_pjsip_endpt_doc
+ },
+ {
+ "get_pjmedia_endpt", py_pjsua_get_pjmedia_endpt, METH_VARARGS,
+ pjsua_get_pjmedia_endpt_doc
+ },
+ {
+ "get_pool_factory", py_pjsua_get_pool_factory, METH_VARARGS,
+ pjsua_get_pool_factory_doc
+ },
+ {
+ "reconfigure_logging", py_pjsua_reconfigure_logging, METH_VARARGS,
+ pjsua_reconfigure_logging_doc
+ },
+ {
+ "logging_config_default", py_pjsua_logging_config_default,
+ METH_VARARGS, pjsua_logging_config_default_doc
+ },
+ {
+ "config_default", py_pjsua_config_default, METH_VARARGS,
+ pjsua_config_default_doc
+ },
+ {
+ "media_config_default", py_pjsua_media_config_default, METH_VARARGS,
+ pjsua_media_config_default_doc
+ },
+
+
+ {
+ "msg_data_init", py_pjsua_msg_data_init, METH_VARARGS,
+ pjsua_msg_data_init_doc
+ },
+ {
+ "transport_config_default", py_pjsua_transport_config_default,
+ METH_VARARGS,pjsua_transport_config_default_doc
+ },
+ {
+ "transport_create", py_pjsua_transport_create, METH_VARARGS,
+ pjsua_transport_create_doc
+ },
+ {
+ "transport_enum_transports", py_pjsua_enum_transports, METH_VARARGS,
+ pjsua_enum_transports_doc
+ },
+ {
+ "transport_get_info", py_pjsua_transport_get_info, METH_VARARGS,
+ pjsua_transport_get_info_doc
+ },
+ {
+ "transport_set_enable", py_pjsua_transport_set_enable, METH_VARARGS,
+ pjsua_transport_set_enable_doc
+ },
+ {
+ "transport_close", py_pjsua_transport_close, METH_VARARGS,
+ pjsua_transport_close_doc
+ },
+ {
+ "acc_config_default", py_pjsua_acc_config_default, METH_VARARGS,
+ pjsua_acc_config_default_doc
+ },
+ {
+ "acc_get_count", py_pjsua_acc_get_count, METH_VARARGS,
+ pjsua_acc_get_count_doc
+ },
+ {
+ "acc_is_valid", py_pjsua_acc_is_valid, METH_VARARGS,
+ pjsua_acc_is_valid_doc
+ },
+ {
+ "acc_set_default", py_pjsua_acc_set_default, METH_VARARGS,
+ pjsua_acc_set_default_doc
+ },
+ {
+ "acc_get_default", py_pjsua_acc_get_default, METH_VARARGS,
+ pjsua_acc_get_default_doc
+ },
+ {
+ "acc_add", py_pjsua_acc_add, METH_VARARGS,
+ pjsua_acc_add_doc
+ },
+ {
+ "acc_add_local", py_pjsua_acc_add_local, METH_VARARGS,
+ pjsua_acc_add_local_doc
+ },
+ {
+ "acc_del", py_pjsua_acc_del, METH_VARARGS,
+ pjsua_acc_del_doc
+ },
+ {
+ "acc_modify", py_pjsua_acc_modify, METH_VARARGS,
+ pjsua_acc_modify_doc
+ },
+ {
+ "acc_set_online_status", py_pjsua_acc_set_online_status, METH_VARARGS,
+ pjsua_acc_set_online_status_doc
+ },
+ {
+ "acc_set_online_status2", py_pjsua_acc_set_online_status2, METH_VARARGS,
+ pjsua_acc_set_online_status2_doc
+ },
+ {
+ "acc_set_registration", py_pjsua_acc_set_registration, METH_VARARGS,
+ pjsua_acc_set_registration_doc
+ },
+ {
+ "acc_get_info", py_pjsua_acc_get_info, METH_VARARGS,
+ pjsua_acc_get_info_doc
+ },
+ {
+ "enum_accs", py_pjsua_enum_accs, METH_VARARGS,
+ pjsua_enum_accs_doc
+ },
+ {
+ "acc_enum_info", py_pjsua_acc_enum_info, METH_VARARGS,
+ pjsua_acc_enum_info_doc
+ },
+ {
+ "acc_find_for_outgoing", py_pjsua_acc_find_for_outgoing, METH_VARARGS,
+ pjsua_acc_find_for_outgoing_doc
+ },
+ {
+ "acc_find_for_incoming", py_pjsua_acc_find_for_incoming, METH_VARARGS,
+ pjsua_acc_find_for_incoming_doc
+ },
+ {
+ "acc_create_uac_contact", py_pjsua_acc_create_uac_contact, METH_VARARGS,
+ pjsua_acc_create_uac_contact_doc
+ },
+ {
+ "acc_create_uas_contact", py_pjsua_acc_create_uas_contact, METH_VARARGS,
+ pjsua_acc_create_uas_contact_doc
+ },
+ {
+ "buddy_config_default", py_pjsua_buddy_config_default, METH_VARARGS,
+ pjsua_buddy_config_default_doc
+ },
+ {
+ "get_buddy_count", py_pjsua_get_buddy_count, METH_VARARGS,
+ pjsua_get_buddy_count_doc
+ },
+ {
+ "buddy_is_valid", py_pjsua_buddy_is_valid, METH_VARARGS,
+ pjsua_buddy_is_valid_doc
+ },
+ {
+ "enum_buddies", py_pjsua_enum_buddies, METH_VARARGS,
+ pjsua_enum_buddies_doc
+ },
+ {
+ "buddy_get_info", py_pjsua_buddy_get_info, METH_VARARGS,
+ pjsua_buddy_get_info_doc
+ },
+ {
+ "buddy_add", py_pjsua_buddy_add, METH_VARARGS,
+ pjsua_buddy_add_doc
+ },
+ {
+ "buddy_del", py_pjsua_buddy_del, METH_VARARGS,
+ pjsua_buddy_del_doc
+ },
+ {
+ "buddy_subscribe_pres", py_pjsua_buddy_subscribe_pres, METH_VARARGS,
+ pjsua_buddy_subscribe_pres_doc
+ },
+ {
+ "pres_dump", py_pjsua_pres_dump, METH_VARARGS,
+ pjsua_pres_dump_doc
+ },
+ {
+ "im_send", py_pjsua_im_send, METH_VARARGS,
+ pjsua_im_send_doc
+ },
+ {
+ "im_typing", py_pjsua_im_typing, METH_VARARGS,
+ pjsua_im_typing_doc
+ },
+ {
+ "conf_get_max_ports", py_pjsua_conf_get_max_ports, METH_VARARGS,
+ pjsua_conf_get_max_ports_doc
+ },
+ {
+ "conf_get_active_ports", py_pjsua_conf_get_active_ports, METH_VARARGS,
+ pjsua_conf_get_active_ports_doc
+ },
+ {
+ "enum_conf_ports", py_pjsua_enum_conf_ports, METH_VARARGS,
+ pjsua_enum_conf_ports_doc
+ },
+ {
+ "conf_get_port_info", py_pjsua_conf_get_port_info, METH_VARARGS,
+ pjsua_conf_get_port_info_doc
+ },
+ {
+ "conf_add_port", py_pjsua_conf_add_port, METH_VARARGS,
+ pjsua_conf_add_port_doc
+ },
+ {
+ "conf_remove_port", py_pjsua_conf_remove_port, METH_VARARGS,
+ pjsua_conf_remove_port_doc
+ },
+ {
+ "conf_connect", py_pjsua_conf_connect, METH_VARARGS,
+ pjsua_conf_connect_doc
+ },
+ {
+ "conf_disconnect", py_pjsua_conf_disconnect, METH_VARARGS,
+ pjsua_conf_disconnect_doc
+ },
+ {
+ "player_create", py_pjsua_player_create, METH_VARARGS,
+ pjsua_player_create_doc
+ },
+ {
+ "player_get_conf_port", py_pjsua_player_get_conf_port, METH_VARARGS,
+ pjsua_player_get_conf_port_doc
+ },
+ {
+ "player_set_pos", py_pjsua_player_set_pos, METH_VARARGS,
+ pjsua_player_set_pos_doc
+ },
+ {
+ "player_destroy", py_pjsua_player_destroy, METH_VARARGS,
+ pjsua_player_destroy_doc
+ },
+ {
+ "recorder_create", py_pjsua_recorder_create, METH_VARARGS,
+ pjsua_recorder_create_doc
+ },
+ {
+ "recorder_get_conf_port", py_pjsua_recorder_get_conf_port, METH_VARARGS,
+ pjsua_recorder_get_conf_port_doc
+ },
+ {
+ "recorder_destroy", py_pjsua_recorder_destroy, METH_VARARGS,
+ pjsua_recorder_destroy_doc
+ },
+ {
+ "enum_snd_devs", py_pjsua_enum_snd_devs, METH_VARARGS,
+ pjsua_enum_snd_devs_doc
+ },
+ {
+ "get_snd_dev", py_pjsua_get_snd_dev, METH_VARARGS,
+ pjsua_get_snd_dev_doc
+ },
+ {
+ "set_snd_dev", py_pjsua_set_snd_dev, METH_VARARGS,
+ pjsua_set_snd_dev_doc
+ },
+ {
+ "set_null_snd_dev", py_pjsua_set_null_snd_dev, METH_VARARGS,
+ pjsua_set_null_snd_dev_doc
+ },
+ {
+ "set_no_snd_dev", py_pjsua_set_no_snd_dev, METH_VARARGS,
+ pjsua_set_no_snd_dev_doc
+ },
+ {
+ "set_ec", py_pjsua_set_ec, METH_VARARGS,
+ pjsua_set_ec_doc
+ },
+ {
+ "get_ec_tail", py_pjsua_get_ec_tail, METH_VARARGS,
+ pjsua_get_ec_tail_doc
+ },
+ {
+ "enum_codecs", py_pjsua_enum_codecs, METH_VARARGS,
+ pjsua_enum_codecs_doc
+ },
+ {
+ "codec_set_priority", py_pjsua_codec_set_priority, METH_VARARGS,
+ pjsua_codec_set_priority_doc
+ },
+ {
+ "codec_get_param", py_pjsua_codec_get_param, METH_VARARGS,
+ pjsua_codec_get_param_doc
+ },
+ {
+ "codec_set_param", py_pjsua_codec_set_param, METH_VARARGS,
+ pjsua_codec_set_param_doc
+ },
+ {
+ "call_get_max_count", py_pjsua_call_get_max_count, METH_VARARGS,
+ pjsua_call_get_max_count_doc
+ },
+ {
+ "call_get_count", py_pjsua_call_get_count, METH_VARARGS,
+ pjsua_call_get_count_doc
+ },
+ {
+ "enum_calls", py_pjsua_enum_calls, METH_VARARGS,
+ pjsua_enum_calls_doc
+ },
+ {
+ "call_make_call", py_pjsua_call_make_call, METH_VARARGS,
+ pjsua_call_make_call_doc
+ },
+ {
+ "call_is_active", py_pjsua_call_is_active, METH_VARARGS,
+ pjsua_call_is_active_doc
+ },
+ {
+ "call_has_media", py_pjsua_call_has_media, METH_VARARGS,
+ pjsua_call_has_media_doc
+ },
+ {
+ "call_get_conf_port", py_pjsua_call_get_conf_port, METH_VARARGS,
+ pjsua_call_get_conf_port_doc
+ },
+ {
+ "call_get_info", py_pjsua_call_get_info, METH_VARARGS,
+ pjsua_call_get_info_doc
+ },
+ {
+ "call_set_user_data", py_pjsua_call_set_user_data, METH_VARARGS,
+ pjsua_call_set_user_data_doc
+ },
+ {
+ "call_get_user_data", py_pjsua_call_get_user_data, METH_VARARGS,
+ pjsua_call_get_user_data_doc
+ },
+ {
+ "call_answer", py_pjsua_call_answer, METH_VARARGS,
+ pjsua_call_answer_doc
+ },
+ {
+ "call_hangup", py_pjsua_call_hangup, METH_VARARGS,
+ pjsua_call_hangup_doc
+ },
+ {
+ "call_set_hold", py_pjsua_call_set_hold, METH_VARARGS,
+ pjsua_call_set_hold_doc
+ },
+ {
+ "call_reinvite", py_pjsua_call_reinvite, METH_VARARGS,
+ pjsua_call_reinvite_doc
+ },
+ {
+ "call_xfer", py_pjsua_call_xfer, METH_VARARGS,
+ pjsua_call_xfer_doc
+ },
+ {
+ "call_xfer_replaces", py_pjsua_call_xfer_replaces, METH_VARARGS,
+ pjsua_call_xfer_replaces_doc
+ },
+ {
+ "call_dial_dtmf", py_pjsua_call_dial_dtmf, METH_VARARGS,
+ pjsua_call_dial_dtmf_doc
+ },
+ {
+ "call_send_im", py_pjsua_call_send_im, METH_VARARGS,
+ pjsua_call_send_im_doc
+ },
+ {
+ "call_send_typing_ind", py_pjsua_call_send_typing_ind, METH_VARARGS,
+ pjsua_call_send_typing_ind_doc
+ },
+ {
+ "call_hangup_all", py_pjsua_call_hangup_all, METH_VARARGS,
+ pjsua_call_hangup_all_doc
+ },
+ {
+ "call_dump", py_pjsua_call_dump, METH_VARARGS,
+ pjsua_call_dump_doc
+ },
+ {
+ "dump", py_pjsua_dump, METH_VARARGS, "Dump application state"
+ },
+
+
+ {NULL, NULL} /* end of function list */
+};
+
+
+
+/*
+ * Mapping C structs from and to Python objects & initializing object
+ */
+DL_EXPORT(void)
+initpy_pjsua(void)
+{
+ PyObject* m = NULL;
+#define ADD_CONSTANT(mod,name) PyModule_AddIntConstant(mod,#name,name)
+
+
+ PyEval_InitThreads();
+
+ if (PyType_Ready(&PyTyp_pjsua_callback) < 0)
+ return;
+ if (PyType_Ready(&PyTyp_pjsua_config) < 0)
+ return;
+ if (PyType_Ready(&PyTyp_pjsua_logging_config) < 0)
+ return;
+ if (PyType_Ready(&PyTyp_pjsua_msg_data) < 0)
+ return;
+ PyTyp_pjsua_media_config.tp_new = PyType_GenericNew;
+ if (PyType_Ready(&PyTyp_pjsua_media_config) < 0)
+ return;
+ PyTyp_pjsip_event.tp_new = PyType_GenericNew;
+ if (PyType_Ready(&PyTyp_pjsip_event) < 0)
+ return;
+ PyTyp_pjsip_rx_data.tp_new = PyType_GenericNew;
+ if (PyType_Ready(&PyTyp_pjsip_rx_data) < 0)
+ return;
+ PyTyp_pj_pool_t.tp_new = PyType_GenericNew;
+ if (PyType_Ready(&PyTyp_pj_pool_t) < 0)
+ return;
+ PyTyp_pjsip_endpoint.tp_new = PyType_GenericNew;
+ if (PyType_Ready(&PyTyp_pjsip_endpoint) < 0)
+ return;
+ PyTyp_pjmedia_endpt.tp_new = PyType_GenericNew;
+ if (PyType_Ready(&PyTyp_pjmedia_endpt) < 0)
+ return;
+ PyTyp_pj_pool_factory.tp_new = PyType_GenericNew;
+ if (PyType_Ready(&PyTyp_pj_pool_factory) < 0)
+ return;
+ PyTyp_pjsip_cred_info.tp_new = PyType_GenericNew;
+ if (PyType_Ready(&PyTyp_pjsip_cred_info) < 0)
+ return;
+
+ /* LIB TRANSPORT */
+
+ if (PyType_Ready(&PyTyp_pjsua_transport_config) < 0)
+ return;
+
+ if (PyType_Ready(&PyTyp_pjsua_transport_info) < 0)
+ return;
+
+ /* END OF LIB TRANSPORT */
+
+ /* LIB ACCOUNT */
+
+
+ if (PyType_Ready(&PyTyp_pjsua_acc_config) < 0)
+ return;
+ if (PyType_Ready(&PyTyp_pjsua_acc_info) < 0)
+ return;
+
+ /* END OF LIB ACCOUNT */
+
+ /* LIB BUDDY */
+
+ if (PyType_Ready(&PyTyp_pjsua_buddy_config) < 0)
+ return;
+ if (PyType_Ready(&PyTyp_pjsua_buddy_info) < 0)
+ return;
+
+ /* END OF LIB BUDDY */
+
+ /* LIB MEDIA */
+
+ if (PyType_Ready(&PyTyp_pjsua_codec_info) < 0)
+ return;
+
+ if (PyType_Ready(&PyTyp_pjsua_conf_port_info) < 0)
+ return;
+
+ PyTyp_pjmedia_port.tp_new = PyType_GenericNew;
+ if (PyType_Ready(&PyTyp_pjmedia_port) < 0)
+ return;
+
+ if (PyType_Ready(&PyTyp_pjmedia_snd_dev_info) < 0)
+ return;
+
+ PyTyp_pjmedia_codec_param_info.tp_new = PyType_GenericNew;
+ if (PyType_Ready(&PyTyp_pjmedia_codec_param_info) < 0)
+ return;
+ PyTyp_pjmedia_codec_param_setting.tp_new = PyType_GenericNew;
+ if (PyType_Ready(&PyTyp_pjmedia_codec_param_setting) < 0)
+ return;
+
+ if (PyType_Ready(&PyTyp_pjmedia_codec_param) < 0)
+ return;
+
+ /* END OF LIB MEDIA */
+
+ /* LIB CALL */
+
+ PyTyp_pj_time_val.tp_new = PyType_GenericNew;
+ if (PyType_Ready(&PyTyp_pj_time_val) < 0)
+ return;
+
+ if (PyType_Ready(&PyTyp_pjsua_call_info) < 0)
+ return;
+
+ /* END OF LIB CALL */
+
+ m = Py_InitModule3(
+ "py_pjsua", py_pjsua_methods,"PJSUA-lib module for python"
+ );
+
+ Py_INCREF(&PyTyp_pjsua_callback);
+ PyModule_AddObject(m, "Callback", (PyObject *)&PyTyp_pjsua_callback);
+
+ Py_INCREF(&PyTyp_pjsua_config);
+ PyModule_AddObject(m, "Config", (PyObject *)&PyTyp_pjsua_config);
+
+ Py_INCREF(&PyTyp_pjsua_media_config);
+ PyModule_AddObject(m, "Media_Config", (PyObject *)&PyTyp_pjsua_media_config);
+
+ Py_INCREF(&PyTyp_pjsua_logging_config);
+ PyModule_AddObject(m, "Logging_Config", (PyObject *)&PyTyp_pjsua_logging_config);
+
+ Py_INCREF(&PyTyp_pjsua_msg_data);
+ PyModule_AddObject(m, "Msg_Data", (PyObject *)&PyTyp_pjsua_msg_data);
+
+ Py_INCREF(&PyTyp_pjsip_event);
+ PyModule_AddObject(m, "Pjsip_Event", (PyObject *)&PyTyp_pjsip_event);
+
+ Py_INCREF(&PyTyp_pjsip_rx_data);
+ PyModule_AddObject(m, "Pjsip_Rx_Data", (PyObject *)&PyTyp_pjsip_rx_data);
+
+ Py_INCREF(&PyTyp_pj_pool_t);
+ PyModule_AddObject(m, "Pj_Pool", (PyObject *)&PyTyp_pj_pool_t);
+
+ Py_INCREF(&PyTyp_pjsip_endpoint);
+ PyModule_AddObject(m, "Pjsip_Endpoint", (PyObject *)&PyTyp_pjsip_endpoint);
+
+ Py_INCREF(&PyTyp_pjmedia_endpt);
+ PyModule_AddObject(m, "Pjmedia_Endpt", (PyObject *)&PyTyp_pjmedia_endpt);
+
+ Py_INCREF(&PyTyp_pj_pool_factory);
+ PyModule_AddObject(
+ m, "Pj_Pool_Factory", (PyObject *)&PyTyp_pj_pool_factory
+ );
+
+ Py_INCREF(&PyTyp_pjsip_cred_info);
+ PyModule_AddObject(m, "Pjsip_Cred_Info",
+ (PyObject *)&PyTyp_pjsip_cred_info
+ );
+
+ /* LIB TRANSPORT */
+
+ Py_INCREF(&PyTyp_pjsua_transport_config);
+ PyModule_AddObject
+ (m, "Transport_Config", (PyObject *)&PyTyp_pjsua_transport_config);
+
+ Py_INCREF(&PyTyp_pjsua_transport_info);
+ PyModule_AddObject(m, "Transport_Info", (PyObject *)&PyTyp_pjsua_transport_info);
+
+
+ /* END OF LIB TRANSPORT */
+
+ /* LIB ACCOUNT */
+
+
+ Py_INCREF(&PyTyp_pjsua_acc_config);
+ PyModule_AddObject(m, "Acc_Config", (PyObject *)&PyTyp_pjsua_acc_config);
+ Py_INCREF(&PyTyp_pjsua_acc_info);
+ PyModule_AddObject(m, "Acc_Info", (PyObject *)&PyTyp_pjsua_acc_info);
+
+ /* END OF LIB ACCOUNT */
+
+ /* LIB BUDDY */
+
+ Py_INCREF(&PyTyp_pjsua_buddy_config);
+ PyModule_AddObject(m, "Buddy_Config", (PyObject *)&PyTyp_pjsua_buddy_config);
+ Py_INCREF(&PyTyp_pjsua_buddy_info);
+ PyModule_AddObject(m, "Buddy_Info", (PyObject *)&PyTyp_pjsua_buddy_info);
+
+ /* END OF LIB BUDDY */
+
+ /* LIB MEDIA */
+
+ Py_INCREF(&PyTyp_pjsua_codec_info);
+ PyModule_AddObject(m, "Codec_Info", (PyObject *)&PyTyp_pjsua_codec_info);
+ Py_INCREF(&PyTyp_pjsua_conf_port_info);
+ PyModule_AddObject(m, "Conf_Port_Info", (PyObject *)&PyTyp_pjsua_conf_port_info);
+ Py_INCREF(&PyTyp_pjmedia_port);
+ PyModule_AddObject(m, "PJMedia_Port", (PyObject *)&PyTyp_pjmedia_port);
+ Py_INCREF(&PyTyp_pjmedia_snd_dev_info);
+ PyModule_AddObject(m, "PJMedia_Snd_Dev_Info",
+ (PyObject *)&PyTyp_pjmedia_snd_dev_info);
+ Py_INCREF(&PyTyp_pjmedia_codec_param_info);
+ PyModule_AddObject(m, "PJMedia_Codec_Param_Info",
+ (PyObject *)&PyTyp_pjmedia_codec_param_info);
+ Py_INCREF(&PyTyp_pjmedia_codec_param_setting);
+ PyModule_AddObject(m, "PJMedia_Codec_Param_Setting",
+ (PyObject *)&PyTyp_pjmedia_codec_param_setting);
+ Py_INCREF(&PyTyp_pjmedia_codec_param);
+ PyModule_AddObject(m, "PJMedia_Codec_Param",
+ (PyObject *)&PyTyp_pjmedia_codec_param);
+
+ /* END OF LIB MEDIA */
+
+ /* LIB CALL */
+
+ Py_INCREF(&PyTyp_pj_time_val);
+ PyModule_AddObject(m, "PJ_Time_Val", (PyObject *)&PyTyp_pj_time_val);
+
+ Py_INCREF(&PyTyp_pjsua_call_info);
+ PyModule_AddObject(m, "Call_Info", (PyObject *)&PyTyp_pjsua_call_info);
+
+ /* END OF LIB CALL */
+
+
+ /*
+ * Add various constants.
+ */
+
+ /* Call states */
+ ADD_CONSTANT(m, PJSIP_INV_STATE_NULL);
+ ADD_CONSTANT(m, PJSIP_INV_STATE_CALLING);
+ ADD_CONSTANT(m, PJSIP_INV_STATE_INCOMING);
+ ADD_CONSTANT(m, PJSIP_INV_STATE_EARLY);
+ ADD_CONSTANT(m, PJSIP_INV_STATE_CONNECTING);
+ ADD_CONSTANT(m, PJSIP_INV_STATE_CONFIRMED);
+ ADD_CONSTANT(m, PJSIP_INV_STATE_DISCONNECTED);
+
+ /* Call media status (enum pjsua_call_media_status) */
+ ADD_CONSTANT(m, PJSUA_CALL_MEDIA_NONE);
+ ADD_CONSTANT(m, PJSUA_CALL_MEDIA_ACTIVE);
+ ADD_CONSTANT(m, PJSUA_CALL_MEDIA_LOCAL_HOLD);
+ ADD_CONSTANT(m, PJSUA_CALL_MEDIA_REMOTE_HOLD);
+
+ /* Buddy status */
+ ADD_CONSTANT(m, PJSUA_BUDDY_STATUS_UNKNOWN);
+ ADD_CONSTANT(m, PJSUA_BUDDY_STATUS_ONLINE);
+ ADD_CONSTANT(m, PJSUA_BUDDY_STATUS_OFFLINE);
+
+ /* PJSIP transport types (enum pjsip_transport_type_e) */
+ ADD_CONSTANT(m, PJSIP_TRANSPORT_UNSPECIFIED);
+ ADD_CONSTANT(m, PJSIP_TRANSPORT_UDP);
+ ADD_CONSTANT(m, PJSIP_TRANSPORT_TCP);
+ ADD_CONSTANT(m, PJSIP_TRANSPORT_TLS);
+ ADD_CONSTANT(m, PJSIP_TRANSPORT_SCTP);
+ ADD_CONSTANT(m, PJSIP_TRANSPORT_LOOP);
+ ADD_CONSTANT(m, PJSIP_TRANSPORT_LOOP_DGRAM);
+
+
+ /* Invalid IDs */
+ ADD_CONSTANT(m, PJSUA_INVALID_ID);
+
+
+ /* Various compile time constants */
+ ADD_CONSTANT(m, PJSUA_ACC_MAX_PROXIES);
+ ADD_CONSTANT(m, PJSUA_MAX_ACC);
+ ADD_CONSTANT(m, PJSUA_REG_INTERVAL);
+ ADD_CONSTANT(m, PJSUA_PUBLISH_EXPIRATION);
+ ADD_CONSTANT(m, PJSUA_DEFAULT_ACC_PRIORITY);
+ ADD_CONSTANT(m, PJSUA_MAX_BUDDIES);
+ ADD_CONSTANT(m, PJSUA_MAX_CONF_PORTS);
+ ADD_CONSTANT(m, PJSUA_DEFAULT_CLOCK_RATE);
+ ADD_CONSTANT(m, PJSUA_DEFAULT_CODEC_QUALITY);
+ ADD_CONSTANT(m, PJSUA_DEFAULT_ILBC_MODE);
+ ADD_CONSTANT(m, PJSUA_DEFAULT_EC_TAIL_LEN);
+ ADD_CONSTANT(m, PJSUA_MAX_CALLS);
+ ADD_CONSTANT(m, PJSUA_XFER_NO_REQUIRE_REPLACES);
+
+
+#undef ADD_CONSTANT
+}
diff --git a/pjsip-apps/src/py_pjsua/py_pjsua.def b/pjsip-apps/src/py_pjsua/py_pjsua.def
new file mode 100644
index 0000000..a8dd2f3
--- /dev/null
+++ b/pjsip-apps/src/py_pjsua/py_pjsua.def
@@ -0,0 +1,2 @@
+EXPORTS
+ initpy_pjsua
diff --git a/pjsip-apps/src/py_pjsua/py_pjsua.h b/pjsip-apps/src/py_pjsua/py_pjsua.h
new file mode 100644
index 0000000..4068635
--- /dev/null
+++ b/pjsip-apps/src/py_pjsua/py_pjsua.h
@@ -0,0 +1,2662 @@
+/* $Id: py_pjsua.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __PY_PJSUA_H__
+#define __PY_PJSUA_H__
+
+#define _CRT_SECURE_NO_DEPRECATE
+
+#include <Python.h>
+#include <structmember.h>
+#include <pjsua-lib/pjsua.h>
+
+
+PJ_INLINE(pj_str_t) PyString_to_pj_str(const PyObject *obj)
+{
+ pj_str_t str;
+
+ if (obj) {
+ str.ptr = PyString_AS_STRING(obj);
+ str.slen = PyString_GET_SIZE(obj);
+ } else {
+ str.ptr = NULL;
+ str.slen = 0;
+ }
+
+ return str;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+/*
+ * PyObj_pj_pool
+ */
+typedef struct
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+ pj_pool_t * pool;
+} PyObj_pj_pool;
+
+
+/*
+ * PyTyp_pj_pool_t
+ */
+static PyTypeObject PyTyp_pj_pool_t =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "py_pjsua.Pj_Pool", /*tp_name*/
+ sizeof(PyObj_pj_pool), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ 0, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "pj_pool_t objects", /* tp_doc */
+
+};
+
+
+//////////////////////////////////////////////////////////////////////////////
+/*
+ * PyObj_pjsip_endpoint
+ */
+typedef struct
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+ pjsip_endpoint * endpt;
+} PyObj_pjsip_endpoint;
+
+
+/*
+ * PyTyp_pjsip_endpoint
+ */
+static PyTypeObject PyTyp_pjsip_endpoint =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "py_pjsua.Pjsip_Endpoint", /*tp_name*/
+ sizeof(PyObj_pjsip_endpoint),/*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ 0, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "pjsip_endpoint objects", /* tp_doc */
+};
+
+
+/*
+ * PyObj_pjmedia_endpt
+ */
+typedef struct
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+ pjmedia_endpt * endpt;
+} PyObj_pjmedia_endpt;
+
+
+//////////////////////////////////////////////////////////////////////////////
+/*
+ * PyTyp_pjmedia_endpt
+ */
+static PyTypeObject PyTyp_pjmedia_endpt =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "py_pjsua.Pjmedia_Endpt", /*tp_name*/
+ sizeof(PyObj_pjmedia_endpt), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ 0, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "pjmedia_endpt objects", /* tp_doc */
+
+};
+
+
+//////////////////////////////////////////////////////////////////////////////
+/*
+ * PyObj_pj_pool_factory
+ */
+typedef struct
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+ pj_pool_factory * pool_fact;
+} PyObj_pj_pool_factory;
+
+
+
+/*
+ * PyTyp_pj_pool_factory
+ */
+static PyTypeObject PyTyp_pj_pool_factory =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "py_pjsua.Pj_Pool_Factory",/*tp_name*/
+ sizeof(PyObj_pj_pool_factory), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ 0, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "pj_pool_factory objects", /* tp_doc */
+
+};
+
+
+//////////////////////////////////////////////////////////////////////////////
+/*
+ * PyObj_pjsip_cred_info
+ */
+typedef struct
+{
+ PyObject_HEAD
+
+ /* Type-specific fields go here. */
+ PyObject *realm;
+ PyObject *scheme;
+ PyObject *username;
+ int data_type;
+ PyObject *data;
+
+} PyObj_pjsip_cred_info;
+
+/*
+ * cred_info_dealloc
+ * deletes a cred info from memory
+ */
+static void PyObj_pjsip_cred_info_delete(PyObj_pjsip_cred_info* self)
+{
+ Py_XDECREF(self->realm);
+ Py_XDECREF(self->scheme);
+ Py_XDECREF(self->username);
+ Py_XDECREF(self->data);
+ self->ob_type->tp_free((PyObject*)self);
+}
+
+
+static void PyObj_pjsip_cred_info_import(PyObj_pjsip_cred_info *obj,
+ const pjsip_cred_info *cfg)
+{
+ Py_XDECREF(obj->realm);
+ obj->realm = PyString_FromStringAndSize(cfg->realm.ptr, cfg->realm.slen);
+ Py_XDECREF(obj->scheme);
+ obj->scheme = PyString_FromStringAndSize(cfg->scheme.ptr, cfg->scheme.slen);
+ Py_XDECREF(obj->username);
+ obj->username = PyString_FromStringAndSize(cfg->username.ptr, cfg->username.slen);
+ obj->data_type = cfg->data_type;
+ Py_XDECREF(obj->data);
+ obj->data = PyString_FromStringAndSize(cfg->data.ptr, cfg->data.slen);
+}
+
+static void PyObj_pjsip_cred_info_export(pjsip_cred_info *cfg,
+ PyObj_pjsip_cred_info *obj)
+{
+ cfg->realm = PyString_to_pj_str(obj->realm);
+ cfg->scheme = PyString_to_pj_str(obj->scheme);
+ cfg->username = PyString_to_pj_str(obj->username);
+ cfg->data_type = obj->data_type;
+ cfg->data = PyString_to_pj_str(obj->data);
+}
+
+
+/*
+ * cred_info_new
+ * constructor for cred_info object
+ */
+static PyObject * PyObj_pjsip_cred_info_new(PyTypeObject *type,
+ PyObject *args,
+ PyObject *kwds)
+{
+ PyObj_pjsip_cred_info *self;
+
+ PJ_UNUSED_ARG(args);
+ PJ_UNUSED_ARG(kwds);
+
+ self = (PyObj_pjsip_cred_info *)type->tp_alloc(type, 0);
+ if (self != NULL)
+ {
+ self->realm = PyString_FromString("");
+ if (self->realm == NULL)
+ {
+ Py_DECREF(self);
+ return NULL;
+ }
+ self->scheme = PyString_FromString("");
+ if (self->scheme == NULL)
+ {
+ Py_DECREF(self);
+ return NULL;
+ }
+ self->username = PyString_FromString("");
+ if (self->username == NULL)
+ {
+ Py_DECREF(self);
+ return NULL;
+ }
+ self->data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
+ self->data = PyString_FromString("");
+ if (self->data == NULL)
+ {
+ Py_DECREF(self);
+ return NULL;
+ }
+ }
+
+ return (PyObject *)self;
+}
+
+
+/*
+ * PyObj_pjsip_cred_info_members
+ */
+static PyMemberDef PyObj_pjsip_cred_info_members[] =
+{
+ {
+ "realm", T_OBJECT_EX,
+ offsetof(PyObj_pjsip_cred_info, realm), 0,
+ "Realm"
+ },
+ {
+ "scheme", T_OBJECT_EX,
+ offsetof(PyObj_pjsip_cred_info, scheme), 0,
+ "Scheme"
+ },
+ {
+ "username", T_OBJECT_EX,
+ offsetof(PyObj_pjsip_cred_info, username), 0,
+ "User name"
+ },
+ {
+ "data", T_OBJECT_EX,
+ offsetof(PyObj_pjsip_cred_info, data), 0,
+ "The data, which can be a plaintext password or a hashed digest, "
+ "depending on the value of data_type"
+ },
+ {
+ "data_type", T_INT,
+ offsetof(PyObj_pjsip_cred_info, data_type), 0,
+ "Type of data"
+ },
+
+ {NULL} /* Sentinel */
+};
+
+/*
+ * PyTyp_pjsip_cred_info
+ */
+static PyTypeObject PyTyp_pjsip_cred_info =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "py_pjsua.Pjsip_Cred_Info", /*tp_name*/
+ sizeof(PyObj_pjsip_cred_info), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor)PyObj_pjsip_cred_info_delete,/*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "PJSIP credential information", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ PyObj_pjsip_cred_info_members, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ PyObj_pjsip_cred_info_new, /* tp_new */
+
+};
+
+
+//////////////////////////////////////////////////////////////////////////////
+/*
+ * PyObj_pjsip_event
+ * C/python typewrapper for event struct
+ */
+typedef struct
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+ pjsip_event * event;
+} PyObj_pjsip_event;
+
+
+
+/*
+ * PyTyp_pjsip_event
+ * event struct signatures
+ */
+static PyTypeObject PyTyp_pjsip_event =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "py_pjsua.Pjsip_Event", /*tp_name*/
+ sizeof(PyObj_pjsip_event), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ 0, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "pjsip_event object", /*tp_doc */
+};
+
+
+//////////////////////////////////////////////////////////////////////////////
+/*
+ * PyObj_pjsip_rx_data
+ * C/python typewrapper for pjsip_rx_data struct
+ */
+typedef struct
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+ pjsip_rx_data * rdata;
+} PyObj_pjsip_rx_data;
+
+
+/*
+ * PyTyp_pjsip_rx_data
+ */
+static PyTypeObject PyTyp_pjsip_rx_data =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "py_pjsua.Pjsip_Rx_Data", /*tp_name*/
+ sizeof(PyObj_pjsip_rx_data), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ 0, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "pjsip_rx_data object", /*tp_doc*/
+};
+
+
+
+//////////////////////////////////////////////////////////////////////////////
+/*
+ * PyObj_pjsua_callback
+ * C/python typewrapper for callback struct
+ */
+typedef struct PyObj_pjsua_callback
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+ PyObject * on_call_state;
+ PyObject * on_incoming_call;
+ PyObject * on_call_media_state;
+ PyObject * on_dtmf_digit;
+ PyObject * on_call_transfer_request;
+ PyObject * on_call_transfer_status;
+ PyObject * on_call_replace_request;
+ PyObject * on_call_replaced;
+ PyObject * on_reg_state;
+ PyObject * on_buddy_state;
+ PyObject * on_pager;
+ PyObject * on_pager_status;
+ PyObject * on_typing;
+} PyObj_pjsua_callback;
+
+
+/*
+ * PyObj_pjsua_callback_delete
+ * destructor function for callback struct
+ */
+static void PyObj_pjsua_callback_delete(PyObj_pjsua_callback* self)
+{
+ Py_XDECREF(self->on_call_state);
+ Py_XDECREF(self->on_incoming_call);
+ Py_XDECREF(self->on_call_media_state);
+ Py_XDECREF(self->on_dtmf_digit);
+ Py_XDECREF(self->on_call_transfer_request);
+ Py_XDECREF(self->on_call_transfer_status);
+ Py_XDECREF(self->on_call_replace_request);
+ Py_XDECREF(self->on_call_replaced);
+ Py_XDECREF(self->on_reg_state);
+ Py_XDECREF(self->on_buddy_state);
+ Py_XDECREF(self->on_pager);
+ Py_XDECREF(self->on_pager_status);
+ Py_XDECREF(self->on_typing);
+ self->ob_type->tp_free((PyObject*)self);
+}
+
+
+/*
+ * PyObj_pjsua_callback_new
+ * * declares constructor for callback struct
+ */
+static PyObject * PyObj_pjsua_callback_new(PyTypeObject *type,
+ PyObject *args,
+ PyObject *kwds)
+{
+ PyObj_pjsua_callback *self;
+
+ PJ_UNUSED_ARG(args);
+ PJ_UNUSED_ARG(kwds);
+
+ self = (PyObj_pjsua_callback *)type->tp_alloc(type, 0);
+ if (self != NULL)
+ {
+ Py_INCREF(Py_None);
+ self->on_call_state = Py_None;
+ if (self->on_call_state == NULL)
+ {
+ Py_DECREF(Py_None);
+ return NULL;
+ }
+ Py_INCREF(Py_None);
+ self->on_incoming_call = Py_None;
+ if (self->on_incoming_call == NULL)
+ {
+ Py_DECREF(Py_None);
+ return NULL;
+ }
+ Py_INCREF(Py_None);
+ self->on_call_media_state = Py_None;
+ if (self->on_call_media_state == NULL)
+ {
+ Py_DECREF(Py_None);
+ return NULL;
+ }
+ Py_INCREF(Py_None);
+ self->on_dtmf_digit = Py_None;
+ if (self->on_dtmf_digit == NULL)
+ {
+ Py_DECREF(Py_None);
+ return NULL;
+ }
+ Py_INCREF(Py_None);
+ self->on_call_transfer_request = Py_None;
+ if (self->on_call_transfer_request == NULL)
+ {
+ Py_DECREF(Py_None);
+ return NULL;
+ }
+ Py_INCREF(Py_None);
+ self->on_call_transfer_status = Py_None;
+ if (self->on_call_transfer_status == NULL)
+ {
+ Py_DECREF(Py_None);
+ return NULL;
+ }
+ Py_INCREF(Py_None);
+ self->on_call_replace_request = Py_None;
+ if (self->on_call_replace_request == NULL)
+ {
+ Py_DECREF(Py_None);
+ return NULL;
+ }
+ Py_INCREF(Py_None);
+ self->on_call_replaced = Py_None;
+ if (self->on_call_replaced == NULL)
+ {
+ Py_DECREF(Py_None);
+ return NULL;
+ }
+ Py_INCREF(Py_None);
+ self->on_reg_state = Py_None;
+ if (self->on_reg_state == NULL)
+ {
+ Py_DECREF(Py_None);
+ return NULL;
+ }
+ Py_INCREF(Py_None);
+ self->on_buddy_state = Py_None;
+ if (self->on_buddy_state == NULL)
+ {
+ Py_DECREF(Py_None);
+ return NULL;
+ }
+ Py_INCREF(Py_None);
+ self->on_pager = Py_None;
+ if (self->on_pager == NULL)
+ {
+ Py_DECREF(Py_None);
+ return NULL;
+ }
+ Py_INCREF(Py_None);
+ self->on_pager_status = Py_None;
+ if (self->on_pager_status == NULL)
+ {
+ Py_DECREF(Py_None);
+ return NULL;
+ }
+ Py_INCREF(Py_None);
+ self->on_typing = Py_None;
+ if (self->on_typing == NULL)
+ {
+ Py_DECREF(Py_None);
+ return NULL;
+ }
+ }
+
+ return (PyObject *)self;
+}
+
+
+/*
+ * PyObj_pjsua_callback_members
+ * declares available functions for callback object
+ */
+static PyMemberDef PyObj_pjsua_callback_members[] =
+{
+ {
+ "on_call_state", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_callback, on_call_state), 0,
+ "Notify application when invite state has changed. Application may "
+ "then query the call info to get the detail call states."
+ },
+ {
+ "on_incoming_call", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_callback, on_incoming_call), 0,
+ "Notify application on incoming call."
+ },
+ {
+ "on_call_media_state", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_callback, on_call_media_state), 0,
+ "Notify application when media state in the call has changed. Normal "
+ "application would need to implement this callback, e.g. to connect "
+ "the call's media to sound device."
+ },
+ {
+ "on_dtmf_digit", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_callback, on_dtmf_digit), 0,
+ "Notify application upon receiving incoming DTMF digit."
+ },
+ {
+ "on_call_transfer_request", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_callback, on_call_transfer_request), 0,
+ "Notify application on call being transfered. "
+ "Application can decide to accept/reject transfer request "
+ "by setting the code (default is 200). When this callback "
+ "is not defined, the default behavior is to accept the "
+ "transfer."
+ },
+ {
+ "on_call_transfer_status", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_callback, on_call_transfer_status), 0,
+ "Notify application of the status of previously sent call "
+ "transfer request. Application can monitor the status of the "
+ "call transfer request, for example to decide whether to "
+ "terminate existing call."
+ },
+ {
+ "on_call_replace_request", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_callback, on_call_replace_request), 0,
+ "Notify application about incoming INVITE with Replaces header. "
+ "Application may reject the request by setting non-2xx code."
+ },
+ {
+ "on_call_replaced", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_callback, on_call_replaced), 0,
+ "Notify application that an existing call has been replaced with "
+ "a new call. This happens when PJSUA-API receives incoming INVITE "
+ "request with Replaces header."
+ " "
+ "After this callback is called, normally PJSUA-API will disconnect "
+ "old_call_id and establish new_call_id."
+ },
+ {
+ "on_reg_state", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_callback, on_reg_state), 0,
+ "Notify application when registration status has changed. Application "
+ "may then query the account info to get the registration details."
+ },
+ {
+ "on_buddy_state", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_callback, on_buddy_state), 0,
+ "Notify application when the buddy state has changed. Application may "
+ "then query the buddy into to get the details."
+ },
+ {
+ "on_pager", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_callback, on_pager), 0,
+ "Notify application on incoming pager (i.e. MESSAGE request). "
+ "Argument call_id will be -1 if MESSAGE request is not related to an "
+ "existing call."
+ },
+ {
+ "on_pager_status", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_callback, on_pager_status), 0,
+ "Notify application about the delivery status of outgoing pager "
+ "request."
+ },
+ {
+ "on_typing", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_callback, on_typing), 0,
+ "Notify application about typing indication."
+ },
+ {NULL} /* Sentinel */
+};
+
+
+/*
+ * PyTyp_pjsua_callback
+ * callback class definition
+ */
+static PyTypeObject PyTyp_pjsua_callback =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "py_pjsua.Callback", /*tp_name*/
+ sizeof(PyObj_pjsua_callback), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor)PyObj_pjsua_callback_delete, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "This structure describes application callback "
+ "to receive various event notifications from "
+ "PJSUA-API", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ PyObj_pjsua_callback_members, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ PyObj_pjsua_callback_new, /* tp_new */
+
+};
+
+
+//////////////////////////////////////////////////////////////////////////////
+/*
+ * PyObj_pjsua_media_config
+ * C/Python wrapper for pjsua_media_config object
+ */
+typedef struct
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+ unsigned clock_rate;
+ unsigned max_media_ports;
+ int has_ioqueue;
+ unsigned thread_cnt;
+ unsigned quality;
+ unsigned ptime;
+ int no_vad;
+ unsigned ilbc_mode;
+ unsigned tx_drop_pct;
+ unsigned rx_drop_pct;
+ unsigned ec_options;
+ unsigned ec_tail_len;
+} PyObj_pjsua_media_config;
+
+
+/*
+ * PyObj_pjsua_media_config_members
+ * declares attributes accessible from both C and Python for media_config file
+ */
+static PyMemberDef PyObj_pjsua_media_config_members[] =
+{
+ {
+ "clock_rate", T_INT,
+ offsetof(PyObj_pjsua_media_config, clock_rate), 0,
+ "Clock rate to be applied to the conference bridge. If value is zero, "
+ "default clock rate will be used (16KHz)."
+ },
+ {
+ "max_media_ports", T_INT,
+ offsetof(PyObj_pjsua_media_config, max_media_ports), 0,
+ "Specify maximum number of media ports to be created in the "
+ "conference bridge. Since all media terminate in the bridge (calls, "
+ "file player, file recorder, etc), the value must be large enough to "
+ "support all of them. However, the larger the value, the more "
+ "computations are performed."
+ },
+ {
+ "has_ioqueue", T_INT,
+ offsetof(PyObj_pjsua_media_config, has_ioqueue), 0,
+ "Specify whether the media manager should manage its own ioqueue for "
+ "the RTP/RTCP sockets. If yes, ioqueue will be created and at least "
+ "one worker thread will be created too. If no, the RTP/RTCP sockets "
+ "will share the same ioqueue as SIP sockets, and no worker thread is "
+ "needed."
+ },
+ {
+ "thread_cnt", T_INT,
+ offsetof(PyObj_pjsua_media_config, thread_cnt), 0,
+ "Specify the number of worker threads to handle incoming RTP packets. "
+ "A value of one is recommended for most applications."
+ },
+ {
+ "quality", T_INT,
+ offsetof(PyObj_pjsua_media_config, quality), 0,
+ "The media quality also sets speex codec quality/complexity to the "
+ "number."
+ },
+ {
+ "ptime", T_INT,
+ offsetof(PyObj_pjsua_media_config, ptime), 0,
+ "Specify default ptime."
+ },
+ {
+ "no_vad", T_INT,
+ offsetof(PyObj_pjsua_media_config, no_vad), 0,
+ "Disable VAD?"
+ },
+ {
+ "ilbc_mode", T_INT,
+ offsetof(PyObj_pjsua_media_config, ilbc_mode), 0,
+ "iLBC mode (20 or 30)."
+ },
+ {
+ "tx_drop_pct", T_INT,
+ offsetof(PyObj_pjsua_media_config, tx_drop_pct), 0,
+ "Percentage of RTP packet to drop in TX direction (to simulate packet "
+ "lost)."
+ },
+ {
+ "rx_drop_pct", T_INT,
+ offsetof(PyObj_pjsua_media_config, rx_drop_pct), 0,
+ "Percentage of RTP packet to drop in RX direction (to simulate packet "
+ "lost)."},
+ {
+ "ec_options", T_INT,
+ offsetof(PyObj_pjsua_media_config, ec_options), 0,
+ "Echo canceller options (see pjmedia_echo_create())"
+ },
+ {
+ "ec_tail_len", T_INT,
+ offsetof(PyObj_pjsua_media_config, ec_tail_len), 0,
+ "Echo canceller tail length, in miliseconds."
+ },
+ {NULL} /* Sentinel */
+};
+
+
+/*
+ * PyTyp_pjsua_media_config
+ */
+static PyTypeObject PyTyp_pjsua_media_config =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "py_pjsua.Media_Config", /*tp_name*/
+ sizeof(PyObj_pjsua_media_config),/*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ 0, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "Media Config objects", /*tp_doc*/
+ 0, /*tp_traverse*/
+ 0, /*tp_clear*/
+ 0, /*tp_richcompare*/
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ PyObj_pjsua_media_config_members, /* tp_members */
+
+};
+
+
+static void PyObj_pjsua_media_config_import(PyObj_pjsua_media_config *obj,
+ const pjsua_media_config *cfg)
+{
+ obj->clock_rate = cfg->clock_rate;
+ obj->max_media_ports = cfg->max_media_ports;
+ obj->has_ioqueue = cfg->has_ioqueue;
+ obj->thread_cnt = cfg->thread_cnt;
+ obj->quality = cfg->quality;
+ obj->ptime = cfg->ptime;
+ obj->no_vad = cfg->no_vad;
+ obj->ilbc_mode = cfg->ilbc_mode;
+ obj->tx_drop_pct = cfg->tx_drop_pct;
+ obj->rx_drop_pct = cfg->rx_drop_pct;
+ obj->ec_options = cfg->ec_options;
+ obj->ec_tail_len = cfg->ec_tail_len;
+}
+
+static void PyObj_pjsua_media_config_export(pjsua_media_config *cfg,
+ const PyObj_pjsua_media_config *obj)
+{
+ cfg->clock_rate = obj->clock_rate;
+ cfg->max_media_ports = obj->max_media_ports;
+ cfg->has_ioqueue = obj->has_ioqueue;
+ cfg->thread_cnt = obj->thread_cnt;
+ cfg->quality = obj->quality;
+ cfg->ptime = obj->ptime;
+ cfg->no_vad = obj->no_vad;
+ cfg->ilbc_mode = obj->ilbc_mode;
+ cfg->tx_drop_pct = obj->tx_drop_pct;
+ cfg->rx_drop_pct = obj->rx_drop_pct;
+ cfg->ec_options = obj->ec_options;
+ cfg->ec_tail_len = obj->ec_tail_len;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+/*
+ * PyObj_pjsua_config
+ * attribute list for config object
+ */
+typedef struct
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+ unsigned max_calls;
+ unsigned thread_cnt;
+ PyObject *outbound_proxy;
+ PyObject *stun_domain;
+ PyObject *stun_host;
+ PyObject *stun_relay_host;
+ PyObj_pjsua_callback *cb;
+ PyObject *user_agent;
+} PyObj_pjsua_config;
+
+
+static void PyObj_pjsua_config_delete(PyObj_pjsua_config* self)
+{
+ Py_XDECREF(self->outbound_proxy);
+ Py_XDECREF(self->stun_domain);
+ Py_XDECREF(self->stun_host);
+ Py_XDECREF(self->stun_relay_host);
+ Py_XDECREF(self->cb);
+ Py_XDECREF(self->user_agent);
+ self->ob_type->tp_free((PyObject*)self);
+}
+
+
+static void PyObj_pjsua_config_import(PyObj_pjsua_config *obj,
+ const pjsua_config *cfg)
+{
+ obj->max_calls = cfg->max_calls;
+ obj->thread_cnt = cfg->thread_cnt;
+ Py_XDECREF(obj->outbound_proxy);
+ obj->outbound_proxy = PyString_FromStringAndSize(cfg->outbound_proxy[0].ptr,
+ cfg->outbound_proxy[0].slen);
+ Py_XDECREF(obj->stun_domain);
+ obj->stun_domain = PyString_FromStringAndSize(cfg->stun_domain.ptr,
+ cfg->stun_domain.slen);
+ Py_XDECREF(obj->stun_host);
+ obj->stun_host = PyString_FromStringAndSize(cfg->stun_host.ptr,
+ cfg->stun_host.slen);
+ Py_XDECREF(obj->stun_relay_host);
+ obj->stun_relay_host= PyString_FromStringAndSize(cfg->stun_host.ptr,
+ cfg->stun_host.slen);
+ Py_XDECREF(obj->user_agent);
+ obj->user_agent = PyString_FromStringAndSize(cfg->user_agent.ptr,
+ cfg->user_agent.slen);
+}
+
+
+static void PyObj_pjsua_config_export(pjsua_config *cfg,
+ PyObj_pjsua_config *obj)
+{
+ cfg->max_calls = obj->max_calls;
+ cfg->thread_cnt = obj->thread_cnt;
+ if (PyString_Size(obj->outbound_proxy) > 0) {
+ cfg->outbound_proxy_cnt = 1;
+ cfg->outbound_proxy[0] = PyString_to_pj_str(obj->outbound_proxy);
+ } else {
+ cfg->outbound_proxy_cnt = 0;
+ }
+ cfg->stun_domain = PyString_to_pj_str(obj->stun_domain);
+ cfg->stun_host = PyString_to_pj_str(obj->stun_host);
+ //cfg->stun_relay_host= PyString_to_pj_str(obj->stun_host);
+ cfg->user_agent = PyString_to_pj_str(obj->user_agent);
+
+}
+
+
+static PyObject *PyObj_pjsua_config_new(PyTypeObject *type,
+ PyObject *args,
+ PyObject *kwds)
+{
+ PyObj_pjsua_config *self;
+
+ PJ_UNUSED_ARG(args);
+ PJ_UNUSED_ARG(kwds);
+
+ self = (PyObj_pjsua_config *)type->tp_alloc(type, 0);
+ if (self != NULL)
+ {
+ self->user_agent = PyString_FromString("");
+ if (self->user_agent == NULL)
+ {
+ Py_DECREF(self);
+ return NULL;
+ }
+ self->outbound_proxy = PyString_FromString("");
+ if (self->outbound_proxy == NULL)
+ {
+ Py_DECREF(self);
+ return NULL;
+ }
+ self->cb = (PyObj_pjsua_callback *)
+ PyType_GenericNew(&PyTyp_pjsua_callback, NULL, NULL);
+ if (self->cb == NULL)
+ {
+ Py_DECREF(Py_None);
+ return NULL;
+ }
+ }
+ return (PyObject *)self;
+}
+
+
+/*
+ * PyObj_pjsua_config_members
+ * attribute list accessible from Python/C
+ */
+static PyMemberDef PyObj_pjsua_config_members[] =
+{
+ {
+ "max_calls", T_INT,
+ offsetof(PyObj_pjsua_config, max_calls), 0,
+ "Maximum calls to support (default: 4) "
+ },
+ {
+ "thread_cnt", T_INT,
+ offsetof(PyObj_pjsua_config, thread_cnt), 0,
+ "Number of worker threads. Normally application will want to have at "
+ "least one worker thread, unless when it wants to poll the library "
+ "periodically, which in this case the worker thread can be set to "
+ "zero."
+ },
+ {
+ "outbound_proxy", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_config, outbound_proxy), 0,
+ "SIP URL of the outbound proxy (optional)"
+ },
+ {
+ "stun_domain", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_config, stun_domain), 0,
+ "Domain of the STUN server (optional). STUN server will be resolved "
+ "using DNS SRV resolution only when nameserver is configured. "
+ "Alternatively, if DNS SRV resolution for STUN is not desired, "
+ "application can specify the STUN server hostname or IP address "
+ "in stun_host attribute."
+ },
+ {
+ "stun_host", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_config, stun_host), 0,
+ "Hostname or IP address of the STUN server (optional)."
+ },
+ {
+ "stun_relay_host", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_config, stun_relay_host), 0,
+ "Hostname or IP address of the TURN server (optional)."
+ },
+ {
+ "cb", T_OBJECT_EX, offsetof(PyObj_pjsua_config, cb), 0,
+ "Application callback."
+ },
+ {
+ "user_agent", T_OBJECT_EX, offsetof(PyObj_pjsua_config, user_agent), 0,
+ "User agent string (default empty)"
+ },
+ {NULL} /* Sentinel */
+};
+
+
+/*
+ * PyTyp_pjsua_config
+ * type wrapper for config class
+ */
+static PyTypeObject PyTyp_pjsua_config =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "py_pjsua.Config", /*tp_name*/
+ sizeof(PyObj_pjsua_config),/*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor)PyObj_pjsua_config_delete,/*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "Config object", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ PyObj_pjsua_config_members,/* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ PyObj_pjsua_config_new, /* tp_new */
+
+};
+
+//////////////////////////////////////////////////////////////////////////////
+/*
+ * PyObj_pjsua_logging_config
+ * configuration class for logging_config object
+ */
+typedef struct
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+ int msg_logging;
+ unsigned level;
+ unsigned console_level;
+ unsigned decor;
+ PyObject *log_filename;
+ PyObject *cb;
+} PyObj_pjsua_logging_config;
+
+
+/*
+ * PyObj_pjsua_logging_config_delete
+ * deletes a logging config from memory
+ */
+static void PyObj_pjsua_logging_config_delete(PyObj_pjsua_logging_config* self)
+{
+ Py_XDECREF(self->log_filename);
+ Py_XDECREF(self->cb);
+ self->ob_type->tp_free((PyObject*)self);
+}
+
+
+static void PyObj_pjsua_logging_config_import(PyObj_pjsua_logging_config *obj,
+ const pjsua_logging_config *cfg)
+{
+ obj->msg_logging = cfg->msg_logging;
+ obj->level = cfg->level;
+ obj->console_level = cfg->console_level;
+ obj->decor = cfg->decor;
+}
+
+static void PyObj_pjsua_logging_config_export(pjsua_logging_config *cfg,
+ PyObj_pjsua_logging_config *obj)
+{
+ cfg->msg_logging = obj->msg_logging;
+ cfg->level = obj->level;
+ cfg->console_level = obj->console_level;
+ cfg->decor = obj->decor;
+ cfg->log_filename = PyString_to_pj_str(obj->log_filename);
+}
+
+
+/*
+ * PyObj_pjsua_logging_config_new
+ * constructor for logging_config object
+ */
+static PyObject * PyObj_pjsua_logging_config_new(PyTypeObject *type,
+ PyObject *args,
+ PyObject *kwds)
+{
+ PyObj_pjsua_logging_config *self;
+
+ PJ_UNUSED_ARG(args);
+ PJ_UNUSED_ARG(kwds);
+
+ self = (PyObj_pjsua_logging_config *)type->tp_alloc(type, 0);
+ if (self != NULL)
+ {
+ self->log_filename = PyString_FromString("");
+ if (self->log_filename == NULL)
+ {
+ Py_DECREF(self);
+ return NULL;
+ }
+ Py_INCREF(Py_None);
+ self->cb = Py_None;
+ if (self->cb == NULL)
+ {
+ Py_DECREF(Py_None);
+ return NULL;
+ }
+ }
+
+ return (PyObject *)self;
+}
+
+
+/*
+ * PyObj_pjsua_logging_config_members
+ */
+static PyMemberDef PyObj_pjsua_logging_config_members[] =
+{
+ {
+ "msg_logging", T_INT,
+ offsetof(PyObj_pjsua_logging_config, msg_logging), 0,
+ "Log incoming and outgoing SIP message? Yes!"
+ },
+ {
+ "level", T_INT,
+ offsetof(PyObj_pjsua_logging_config, level), 0,
+ "Input verbosity level. Value 5 is reasonable."
+ },
+ {
+ "console_level", T_INT,
+ offsetof(PyObj_pjsua_logging_config, console_level),
+ 0, "Verbosity level for console. Value 4 is reasonable."
+ },
+ {
+ "decor", T_INT,
+ offsetof(PyObj_pjsua_logging_config, decor), 0,
+ "Log decoration"
+ },
+ {
+ "log_filename", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_logging_config, log_filename), 0,
+ "Optional log filename"
+ },
+ {
+ "cb", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_logging_config, cb), 0,
+ "Optional callback function to be called to write log to application "
+ "specific device. This function will be called forlog messages on "
+ "input verbosity level."
+ },
+ {NULL} /* Sentinel */
+};
+
+
+
+
+/*
+ * PyTyp_pjsua_logging_config
+ */
+static PyTypeObject PyTyp_pjsua_logging_config =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "py_pjsua.Logging_Config", /*tp_name*/
+ sizeof(PyObj_pjsua_logging_config), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor)PyObj_pjsua_logging_config_delete,/*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "Logging Config objects", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ PyObj_pjsua_logging_config_members,/* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ PyObj_pjsua_logging_config_new, /* tp_new */
+
+};
+
+
+//////////////////////////////////////////////////////////////////////////////
+/*
+ * PyObj_pjsua_msg_data
+ * typewrapper for MessageData class
+ * !modified @ 061206
+ */
+typedef struct
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+ PyObject * hdr_list;
+ PyObject * content_type;
+ PyObject * msg_body;
+} PyObj_pjsua_msg_data;
+
+
+/*
+ * PyObj_pjsua_msg_data_delete
+ * deletes a msg_data
+ * !modified @ 061206
+ */
+static void PyObj_pjsua_msg_data_delete(PyObj_pjsua_msg_data* self)
+{
+ Py_XDECREF(self->hdr_list);
+ Py_XDECREF(self->content_type);
+ Py_XDECREF(self->msg_body);
+ self->ob_type->tp_free((PyObject*)self);
+}
+
+
+/*
+ * PyObj_pjsua_msg_data_new
+ * constructor for msg_data object
+ * !modified @ 061206
+ */
+static PyObject * PyObj_pjsua_msg_data_new(PyTypeObject *type,
+ PyObject *args,
+ PyObject *kwds)
+{
+ PyObj_pjsua_msg_data *self;
+
+ PJ_UNUSED_ARG(args);
+ PJ_UNUSED_ARG(kwds);
+
+ self = (PyObj_pjsua_msg_data *)type->tp_alloc(type, 0);
+ if (self != NULL)
+ {
+ Py_INCREF(Py_None);
+ self->hdr_list = Py_None;
+ if (self->hdr_list == NULL) {
+ Py_DECREF(self);
+ return NULL;
+ }
+ self->content_type = PyString_FromString("");
+ if (self->content_type == NULL) {
+ Py_DECREF(self);
+ return NULL;
+ }
+ self->msg_body = PyString_FromString("");
+ if (self->msg_body == NULL) {
+ Py_DECREF(self);
+ return NULL;
+ }
+ }
+
+ return (PyObject *)self;
+}
+
+
+/*
+ * PyObj_pjsua_msg_data_members
+ * !modified @ 061206
+ */
+static PyMemberDef PyObj_pjsua_msg_data_members[] =
+{
+ {
+ "hdr_list", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_msg_data, hdr_list), 0,
+ "Additional message headers as linked list of strings."
+ },
+ {
+ "content_type", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_msg_data, content_type), 0,
+ "MIME type of optional message body."
+ },
+ {
+ "msg_body", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_msg_data, msg_body), 0,
+ "Optional message body."
+ },
+ {NULL} /* Sentinel */
+};
+
+
+/*
+ * PyTyp_pjsua_msg_data
+ */
+static PyTypeObject PyTyp_pjsua_msg_data =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "py_pjsua.Msg_Data", /*tp_name*/
+ sizeof(PyObj_pjsua_msg_data), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor)PyObj_pjsua_msg_data_delete,/*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "msg_data objects", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ PyObj_pjsua_msg_data_members, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ PyObj_pjsua_msg_data_new, /* tp_new */
+
+};
+
+
+//////////////////////////////////////////////////////////////////////////////
+/*
+ * PyObj_pjsua_transport_config
+ * Transport configuration for creating UDP transports for both SIP
+ * and media.
+ */
+typedef struct
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+ unsigned port;
+ PyObject *public_addr;
+ PyObject *bound_addr;
+} PyObj_pjsua_transport_config;
+
+
+/*
+ * PyObj_pjsua_transport_config_delete
+ * deletes a transport config from memory
+ */
+static void PyObj_pjsua_transport_config_delete(PyObj_pjsua_transport_config* self)
+{
+ Py_XDECREF(self->public_addr);
+ Py_XDECREF(self->bound_addr);
+ self->ob_type->tp_free((PyObject*)self);
+}
+
+
+static void PyObj_pjsua_transport_config_export(pjsua_transport_config *cfg,
+ PyObj_pjsua_transport_config *obj)
+{
+ cfg->public_addr = PyString_to_pj_str(obj->public_addr);
+ cfg->bound_addr = PyString_to_pj_str(obj->bound_addr);
+ cfg->port = obj->port;
+
+}
+
+static void PyObj_pjsua_transport_config_import(PyObj_pjsua_transport_config *obj,
+ const pjsua_transport_config *cfg)
+{
+ Py_XDECREF(obj->public_addr);
+ obj->public_addr = PyString_FromStringAndSize(cfg->public_addr.ptr,
+ cfg->public_addr.slen);
+
+ Py_XDECREF(obj->bound_addr);
+ obj->bound_addr = PyString_FromStringAndSize(cfg->bound_addr.ptr,
+ cfg->bound_addr.slen);
+
+ obj->port = cfg->port;
+}
+
+
+/*
+ * PyObj_pjsua_transport_config_new
+ * constructor for transport_config object
+ */
+static PyObject * PyObj_pjsua_transport_config_new(PyTypeObject *type,
+ PyObject *args,
+ PyObject *kwds)
+{
+ PyObj_pjsua_transport_config *self;
+
+ PJ_UNUSED_ARG(args);
+ PJ_UNUSED_ARG(kwds);
+
+ self = (PyObj_pjsua_transport_config *)type->tp_alloc(type, 0);
+ if (self != NULL) {
+ self->public_addr = PyString_FromString("");
+ if (self->public_addr == NULL) {
+ Py_DECREF(self);
+ return NULL;
+ }
+ self->bound_addr = PyString_FromString("");
+ if (self->bound_addr == NULL) {
+ Py_DECREF(self);
+ return NULL;
+ }
+ }
+
+ return (PyObject *)self;
+}
+
+
+/*
+ * PyObj_pjsua_transport_config_members
+ */
+static PyMemberDef PyObj_pjsua_transport_config_members[] =
+{
+ {
+ "port", T_INT,
+ offsetof(PyObj_pjsua_transport_config, port), 0,
+ "UDP port number to bind locally. This setting MUST be specified "
+ "even when default port is desired. If the value is zero, the "
+ "transport will be bound to any available port, and application "
+ "can query the port by querying the transport info."
+ },
+ {
+ "public_addr", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_transport_config, public_addr), 0,
+ "Optional address to advertise as the address of this transport. "
+ "Application can specify any address or hostname for this field, "
+ "for example it can point to one of the interface address in the "
+ "system, or it can point to the public address of a NAT router "
+ "where port mappings have been configured for the application."
+ },
+ {
+ "bound_addr", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_transport_config, bound_addr), 0,
+ "Optional address where the socket should be bound to. This option "
+ "SHOULD only be used to selectively bind the socket to particular "
+ "interface (instead of 0.0.0.0), and SHOULD NOT be used to set the "
+ "published address of a transport (the public_addr field should be "
+ "used for that purpose)."
+ },
+ {NULL} /* Sentinel */
+};
+
+
+
+
+/*
+ * PyTyp_pjsua_transport_config
+ */
+static PyTypeObject PyTyp_pjsua_transport_config =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "py_pjsua.Transport_Config", /*tp_name*/
+ sizeof(PyObj_pjsua_transport_config), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor)PyObj_pjsua_transport_config_delete,/*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "Transport setting", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ PyObj_pjsua_transport_config_members,/* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ PyObj_pjsua_transport_config_new,/* tp_new */
+};
+
+
+//////////////////////////////////////////////////////////////////////////////
+/*
+ * PyObj_pjsua_transport_info
+ * Transport info
+ */
+typedef struct
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+ int id;
+ int type;
+ PyObject *type_name;
+ PyObject *info;
+ unsigned flag;
+ PyObject *addr;
+ unsigned port;
+ unsigned usage_count;
+} PyObj_pjsua_transport_info;
+
+
+/*
+ * PyObj_pjsua_transport_info_delete
+ * deletes a transport info from memory
+ */
+static void PyObj_pjsua_transport_info_delete(PyObj_pjsua_transport_info* self)
+{
+ Py_XDECREF(self->type_name);
+ Py_XDECREF(self->info);
+ Py_XDECREF(self->addr);
+ self->ob_type->tp_free((PyObject*)self);
+}
+
+
+static void PyObj_pjsua_transport_info_import(PyObj_pjsua_transport_info *obj,
+ const pjsua_transport_info *info)
+{
+ obj->id = info->id;
+ obj->type = info->type;
+ obj->type_name = PyString_FromStringAndSize(info->type_name.ptr,
+ info->type_name.slen);
+ obj->info = PyString_FromStringAndSize(info->info.ptr,
+ info->info.slen);
+ obj->flag = info->flag;
+ obj->addr = PyString_FromStringAndSize(info->local_name.host.ptr,
+ info->local_name.host.slen);
+ obj->port = info->local_name.port;
+ obj->usage_count= info->usage_count;
+}
+
+/*
+ * PyObj_pjsua_transport_info_new
+ * constructor for transport_info object
+ */
+static PyObject * PyObj_pjsua_transport_info_new(PyTypeObject *type,
+ PyObject *args,
+ PyObject *kwds)
+{
+ PyObj_pjsua_transport_info *self;
+
+ PJ_UNUSED_ARG(args);
+ PJ_UNUSED_ARG(kwds);
+
+ self = (PyObj_pjsua_transport_info *)type->tp_alloc(type, 0);
+ if (self != NULL)
+ {
+ self->type_name = PyString_FromString("");
+ if (self->type_name == NULL) {
+ Py_DECREF(self);
+ return NULL;
+ }
+ self->info = PyString_FromString("");
+ if (self->info == NULL) {
+ Py_DECREF(self);
+ return NULL;
+ }
+ self->addr = PyString_FromString("");
+ if (self->addr == NULL) {
+ Py_DECREF(self);
+ return NULL;
+ }
+ }
+
+ return (PyObject *)self;
+}
+
+
+/*
+ * PyObj_pjsua_transport_info_members
+ */
+static PyMemberDef PyObj_pjsua_transport_info_members[] =
+{
+ {
+ "id", T_INT,
+ offsetof(PyObj_pjsua_transport_info, id), 0,
+ "PJSUA transport identification."
+ },
+ {
+ "type", T_INT,
+ offsetof(PyObj_pjsua_transport_info, id), 0,
+ "Transport type."
+ },
+ {
+ "type_name", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_transport_info, type_name), 0,
+ "Transport type name."
+ },
+ {
+ "info", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_transport_info, info), 0,
+ "Transport string info/description."
+ },
+ {
+ "flag", T_INT,
+ offsetof(PyObj_pjsua_transport_info, flag), 0,
+ "Transport flag (see ##pjsip_transport_flags_e)."
+ },
+ {
+ "addr", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_transport_info, addr), 0,
+ "Published address (or transport address name)."
+ },
+ {
+ "port", T_INT,
+ offsetof(PyObj_pjsua_transport_info, port), 0,
+ "Published port number."
+ },
+ {
+ "usage_count", T_INT,
+ offsetof(PyObj_pjsua_transport_info, usage_count), 0,
+ "Current number of objects currently referencing this transport."
+ },
+ {NULL} /* Sentinel */
+};
+
+
+/*
+ * PyTyp_pjsua_transport_info
+ */
+static PyTypeObject PyTyp_pjsua_transport_info =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "py_pjsua.Transport_Info", /*tp_name*/
+ sizeof(PyObj_pjsua_transport_info), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor)PyObj_pjsua_transport_info_delete,/*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "Transport Info objects", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ PyObj_pjsua_transport_info_members, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ PyObj_pjsua_transport_info_new, /* tp_new */
+
+};
+
+
+//////////////////////////////////////////////////////////////////////////////
+
+/*
+ * PyObj_pjsua_acc_config
+ * Acc Config
+ */
+typedef struct
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+ int priority;
+ PyObject *id;
+ PyObject *reg_uri;
+ int publish_enabled;
+ PyObject *force_contact;
+ /*pj_str_t proxy[8];*/
+ PyListObject *proxy;
+ unsigned reg_timeout;
+ /*pjsip_cred_info cred_info[8];*/
+ PyListObject *cred_info;
+ int transport_id;
+} PyObj_pjsua_acc_config;
+
+
+/*
+ * PyObj_pjsua_acc_config_delete
+ * deletes a acc_config from memory
+ */
+static void PyObj_pjsua_acc_config_delete(PyObj_pjsua_acc_config* self)
+{
+ Py_XDECREF(self->id);
+ Py_XDECREF(self->reg_uri);
+ Py_XDECREF(self->force_contact);
+ Py_XDECREF(self->proxy);
+ Py_XDECREF(self->cred_info);
+ self->ob_type->tp_free((PyObject*)self);
+}
+
+
+static void PyObj_pjsua_acc_config_import(PyObj_pjsua_acc_config *obj,
+ const pjsua_acc_config *cfg)
+{
+ unsigned i;
+
+ obj->priority = cfg->priority;
+ Py_XDECREF(obj->id);
+ obj->id = PyString_FromStringAndSize(cfg->id.ptr, cfg->id.slen);
+ Py_XDECREF(obj->reg_uri);
+ obj->reg_uri = PyString_FromStringAndSize(cfg->reg_uri.ptr,
+ cfg->reg_uri.slen);
+ obj->publish_enabled = cfg->publish_enabled;
+ Py_XDECREF(obj->force_contact);
+ obj->force_contact = PyString_FromStringAndSize(cfg->force_contact.ptr,
+ cfg->force_contact.slen);
+ Py_XDECREF(obj->proxy);
+ obj->proxy = (PyListObject *)PyList_New(0);
+ for (i=0; i<cfg->proxy_cnt; ++i) {
+ PyObject * str;
+ str = PyString_FromStringAndSize(cfg->proxy[i].ptr,
+ cfg->proxy[i].slen);
+ PyList_Append((PyObject *)obj->proxy, str);
+ }
+
+ obj->reg_timeout = cfg->reg_timeout;
+
+ Py_XDECREF(obj->cred_info);
+ obj->cred_info = (PyListObject *)PyList_New(0);
+ for (i=0; i<cfg->cred_count; ++i) {
+ PyObj_pjsip_cred_info * ci;
+
+ ci = (PyObj_pjsip_cred_info *)
+ PyObj_pjsip_cred_info_new(&PyTyp_pjsip_cred_info,NULL,NULL);
+ PyObj_pjsip_cred_info_import(ci, &cfg->cred_info[i]);
+ PyList_Append((PyObject *)obj->cred_info, (PyObject *)ci);
+ }
+
+ obj->transport_id = cfg->transport_id;
+}
+
+static void PyObj_pjsua_acc_config_export(pjsua_acc_config *cfg,
+ PyObj_pjsua_acc_config *obj)
+{
+ unsigned i;
+
+ cfg->priority = obj->priority;
+ cfg->id = PyString_to_pj_str(obj->id);
+ cfg->reg_uri = PyString_to_pj_str(obj->reg_uri);
+ cfg->publish_enabled = obj->publish_enabled;
+ cfg->force_contact = PyString_to_pj_str(obj->force_contact);
+
+ cfg->proxy_cnt = PyList_Size((PyObject*)obj->proxy);
+ for (i = 0; i < cfg->proxy_cnt; i++) {
+ /*cfg.proxy[i] = ac->proxy[i];*/
+ cfg->proxy[i] = PyString_to_pj_str(PyList_GetItem((PyObject *)obj->proxy,i));
+ }
+
+ cfg->reg_timeout = obj->reg_timeout;
+
+ cfg->cred_count = PyList_Size((PyObject*)obj->cred_info);
+ for (i = 0; i < cfg->cred_count; i++) {
+ /*cfg.cred_info[i] = ac->cred_info[i];*/
+ PyObj_pjsip_cred_info *ci;
+ ci = (PyObj_pjsip_cred_info*)
+ PyList_GetItem((PyObject *)obj->cred_info,i);
+ PyObj_pjsip_cred_info_export(&cfg->cred_info[i], ci);
+ }
+
+ cfg->transport_id = obj->transport_id;
+}
+
+
+/*
+ * PyObj_pjsua_acc_config_new
+ * constructor for acc_config object
+ */
+static PyObject * PyObj_pjsua_acc_config_new(PyTypeObject *type,
+ PyObject *args,
+ PyObject *kwds)
+{
+ PyObj_pjsua_acc_config *self;
+
+ PJ_UNUSED_ARG(args);
+ PJ_UNUSED_ARG(kwds);
+
+ self = (PyObj_pjsua_acc_config *)type->tp_alloc(type, 0);
+ if (self != NULL) {
+ self->id = PyString_FromString("");
+ if (self->id == NULL) {
+ Py_DECREF(self);
+ return NULL;
+ }
+ self->reg_uri = PyString_FromString("");
+ if (self->reg_uri == NULL) {
+ Py_DECREF(self);
+ return NULL;
+ }
+ self->force_contact = PyString_FromString("");
+ if (self->force_contact == NULL) {
+ Py_DECREF(self);
+ return NULL;
+ }
+ self->proxy = (PyListObject *)PyList_New(0);
+ if (self->proxy == NULL) {
+ Py_DECREF(self);
+ return NULL;
+ }
+ self->cred_info = (PyListObject *)PyList_New(0);
+ if (self->cred_info == NULL) {
+ Py_DECREF(self);
+ return NULL;
+ }
+ }
+
+ return (PyObject *)self;
+}
+
+
+
+/*
+ * PyObj_pjsua_acc_config_members
+ */
+static PyMemberDef PyObj_pjsua_acc_config_members[] =
+{
+ {
+ "priority", T_INT, offsetof(PyObj_pjsua_acc_config, priority), 0,
+ "Account priority, which is used to control the order of matching "
+ "incoming/outgoing requests. The higher the number means the higher "
+ "the priority is, and the account will be matched first. "
+ },
+ {
+ "id", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_acc_config, id), 0,
+ "The full SIP URL for the account. "
+ "The value can take name address or URL format, "
+ "and will look something like 'sip:account@serviceprovider'. "
+ "This field is mandatory."
+ },
+ {
+ "reg_uri", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_acc_config, reg_uri), 0,
+ "This is the URL to be put in the request URI for the registration, "
+ "and will look something like 'sip:serviceprovider'. "
+ "This field should be specified if registration is desired. "
+ "If the value is empty, no account registration will be performed. "
+ },
+ {
+ "publish_enabled", T_INT,
+ offsetof(PyObj_pjsua_acc_config, publish_enabled), 0,
+ "Publish presence? "
+ },
+ {
+ "force_contact", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_acc_config, force_contact), 0,
+ "Optional URI to be put as Contact for this account. "
+ "It is recommended that this field is left empty, "
+ "so that the value will be calculated automatically "
+ "based on the transport address. "
+ },
+ {
+ "proxy", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_acc_config, proxy), 0,
+ "Optional URI of the proxies to be visited for all outgoing requests "
+ "that are using this account (REGISTER, INVITE, etc). Application need "
+ "to specify these proxies if the service provider requires "
+ "that requests destined towards its network should go through certain "
+ "proxies first (for example, border controllers)."
+ },
+ {
+ "reg_timeout", T_INT, offsetof(PyObj_pjsua_acc_config, reg_timeout), 0,
+ "Optional interval for registration, in seconds. "
+ "If the value is zero, default interval will be used "
+ "(PJSUA_REG_INTERVAL, 55 seconds). "
+ },
+ {
+ "cred_info", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_acc_config, cred_info), 0,
+ "Array of credentials. If registration is desired, normally there "
+ "should be at least one credential specified, to successfully "
+ "authenticate against the service provider. More credentials can "
+ "be specified, for example when the requests are expected to be "
+ "challenged by the proxies in the route set."
+ },
+ {
+ "transport_id", T_INT,
+ offsetof(PyObj_pjsua_acc_config, transport_id), 0,
+ "Optionally bind this account to specific transport. This normally is"
+ " not a good idea, as account should be able to send requests using"
+ " any available transports according to the destination. But some"
+ " application may want to have explicit control over the transport to"
+ " use, so in that case it can set this field."
+ },
+ {NULL} /* Sentinel */
+};
+
+
+
+
+/*
+ * PyTyp_pjsua_acc_config
+ */
+static PyTypeObject PyTyp_pjsua_acc_config =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "py_pjsua.Acc_Config", /*tp_name*/
+ sizeof(PyObj_pjsua_acc_config), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor)PyObj_pjsua_acc_config_delete,/*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "Acc Config objects", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0/*acc_config_methods*/, /* tp_methods */
+ PyObj_pjsua_acc_config_members, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ PyObj_pjsua_acc_config_new, /* tp_new */
+
+};
+
+
+//////////////////////////////////////////////////////////////////////////////
+/*
+ * PyObj_pjsua_acc_info
+ * Acc Info
+ */
+typedef struct
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+ int id;
+ int is_default;
+ PyObject *acc_uri;
+ int has_registration;
+ int expires;
+ int status;
+ PyObject *status_text;
+ int online_status;
+ PyObject *online_status_text;
+} PyObj_pjsua_acc_info;
+
+
+/*
+ * PyObj_pjsua_acc_info_delete
+ * deletes a acc_info from memory
+ */
+static void PyObj_pjsua_acc_info_delete(PyObj_pjsua_acc_info* self)
+{
+ Py_XDECREF(self->acc_uri);
+ Py_XDECREF(self->status_text);
+ Py_XDECREF(self->online_status_text);
+ self->ob_type->tp_free((PyObject*)self);
+}
+
+
+static void PyObj_pjsua_acc_info_import(PyObj_pjsua_acc_info *obj,
+ const pjsua_acc_info *info)
+{
+ obj->id = info->id;
+ obj->is_default = info->is_default;
+ obj->acc_uri = PyString_FromStringAndSize(info->acc_uri.ptr,
+ info->acc_uri.slen);
+ obj->has_registration = info->has_registration;
+ obj->expires = info->expires;
+ obj->status = info->status;
+ obj->status_text= PyString_FromStringAndSize(info->status_text.ptr,
+ info->status_text.slen);
+ obj->online_status = info->online_status;
+ obj->online_status_text = PyString_FromStringAndSize(info->online_status_text.ptr,
+ info->online_status_text.slen);
+}
+
+
+/*
+ * PyObj_pjsua_acc_info_new
+ * constructor for acc_info object
+ */
+static PyObject * PyObj_pjsua_acc_info_new(PyTypeObject *type,
+ PyObject *args,
+ PyObject *kwds)
+{
+ PyObj_pjsua_acc_info *self;
+
+ PJ_UNUSED_ARG(args);
+ PJ_UNUSED_ARG(kwds);
+
+ self = (PyObj_pjsua_acc_info *)type->tp_alloc(type, 0);
+ if (self != NULL) {
+ self->acc_uri = PyString_FromString("");
+ if (self->acc_uri == NULL) {
+ Py_DECREF(self);
+ return NULL;
+ }
+ self->status_text = PyString_FromString("");
+ if (self->status_text == NULL) {
+ Py_DECREF(self);
+ return NULL;
+ }
+ self->online_status_text = PyString_FromString("");
+ if (self->online_status_text == NULL) {
+ Py_DECREF(self);
+ return NULL;
+ }
+ }
+
+ return (PyObject *)self;
+}
+
+/*
+ * acc_info_members
+ */
+static PyMemberDef acc_info_members[] =
+{
+ {
+ "id", T_INT,
+ offsetof(PyObj_pjsua_acc_info, id), 0,
+ "The account ID."
+ },
+ {
+ "is_default", T_INT,
+ offsetof(PyObj_pjsua_acc_info, is_default), 0,
+ "Flag to indicate whether this is the default account. "
+ },
+ {
+ "acc_uri", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_acc_info, acc_uri), 0,
+ "Account URI"
+ },
+ {
+ "has_registration", T_INT,
+ offsetof(PyObj_pjsua_acc_info, has_registration), 0,
+ "Flag to tell whether this account has registration setting "
+ "(reg_uri is not empty)."
+ },
+ {
+ "expires", T_INT,
+ offsetof(PyObj_pjsua_acc_info, expires), 0,
+ "An up to date expiration interval for account registration session."
+ },
+ {
+ "status", T_INT,
+ offsetof(PyObj_pjsua_acc_info, status), 0,
+ "Last registration status code. If status code is zero, "
+ "the account is currently not registered. Any other value indicates "
+ "the SIP status code of the registration. "
+ },
+ {
+ "status_text", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_acc_info, status_text), 0,
+ "String describing the registration status."
+ },
+ {
+ "online_status", T_INT,
+ offsetof(PyObj_pjsua_acc_info, online_status), 0,
+ "Presence online status for this account. "
+ },
+ {
+ "online_status_text", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_acc_info, online_status_text), 0,
+ "Presence online status text."
+ },
+ {NULL} /* Sentinel */
+};
+
+
+
+
+/*
+ * PyTyp_pjsua_acc_info
+ */
+static PyTypeObject PyTyp_pjsua_acc_info =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "py_pjsua.Acc_Info", /*tp_name*/
+ sizeof(PyObj_pjsua_acc_info), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor)PyObj_pjsua_acc_info_delete,/*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "Acc Info objects", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ NULL, /* tp_methods */
+ acc_info_members, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ PyObj_pjsua_acc_info_new, /* tp_new */
+
+};
+
+
+//////////////////////////////////////////////////////////////////////////////
+
+/*
+ * PyObj_pjsua_buddy_config
+ * Buddy Config
+ */
+typedef struct
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+ PyObject *uri;
+ int subscribe;
+} PyObj_pjsua_buddy_config;
+
+
+/*
+ * PyObj_pjsua_buddy_config_delete
+ * deletes a buddy_config from memory
+ */
+static void PyObj_pjsua_buddy_config_delete(PyObj_pjsua_buddy_config* self)
+{
+ Py_XDECREF(self->uri);
+ self->ob_type->tp_free((PyObject*)self);
+}
+
+
+static void PyObj_pjsua_buddy_config_import(PyObj_pjsua_buddy_config *obj,
+ const pjsua_buddy_config *cfg)
+{
+ Py_XDECREF(obj->uri);
+ obj->uri = PyString_FromStringAndSize(cfg->uri.ptr, cfg->uri.slen);
+ obj->subscribe = cfg->subscribe;
+}
+
+
+static void PyObj_pjsua_buddy_config_export(pjsua_buddy_config *cfg,
+ PyObj_pjsua_buddy_config *obj)
+{
+ cfg->uri = PyString_to_pj_str(obj->uri);
+ cfg->subscribe = obj->subscribe;
+}
+
+
+
+/*
+ * PyObj_pjsua_buddy_config_new
+ * constructor for buddy_config object
+ */
+static PyObject *PyObj_pjsua_buddy_config_new(PyTypeObject *type,
+ PyObject *args,
+ PyObject *kwds)
+{
+ PyObj_pjsua_buddy_config *self;
+
+ PJ_UNUSED_ARG(args);
+ PJ_UNUSED_ARG(kwds);
+
+ self = (PyObj_pjsua_buddy_config *)type->tp_alloc(type, 0);
+ if (self != NULL) {
+ self->uri = PyString_FromString("");
+ if (self->uri == NULL) {
+ Py_DECREF(self);
+ return NULL;
+ }
+ }
+ return (PyObject *)self;
+}
+
+/*
+ * PyObj_pjsua_buddy_config_members
+ */
+static PyMemberDef PyObj_pjsua_buddy_config_members[] =
+{
+
+ {
+ "uri", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_buddy_config, uri), 0,
+ "TBuddy URL or name address."
+ },
+
+ {
+ "subscribe", T_INT,
+ offsetof(PyObj_pjsua_buddy_config, subscribe), 0,
+ "Specify whether presence subscription should start immediately. "
+ },
+
+ {NULL} /* Sentinel */
+};
+
+
+
+
+/*
+ * PyTyp_pjsua_buddy_config
+ */
+static PyTypeObject PyTyp_pjsua_buddy_config =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "py_pjsua.Buddy_Config", /*tp_name*/
+ sizeof(PyObj_pjsua_buddy_config),/*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor)PyObj_pjsua_buddy_config_delete,/*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "Buddy Config objects", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ PyObj_pjsua_buddy_config_members, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ PyObj_pjsua_buddy_config_new, /* tp_new */
+
+};
+
+//////////////////////////////////////////////////////////////////////////////
+/*
+ * PyObj_pjsua_buddy_info
+ * Buddy Info
+ */
+typedef struct
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+ int id;
+ PyObject *uri;
+ PyObject *contact;
+ int status;
+ PyObject *status_text;
+ int monitor_pres;
+} PyObj_pjsua_buddy_info;
+
+
+/*
+ * PyObj_pjsua_buddy_info_delete
+ * deletes a buddy_info from memory
+ * !modified @ 071206
+ */
+static void PyObj_pjsua_buddy_info_delete(PyObj_pjsua_buddy_info* self)
+{
+ Py_XDECREF(self->uri);
+ Py_XDECREF(self->contact);
+ Py_XDECREF(self->status_text);
+
+ self->ob_type->tp_free((PyObject*)self);
+}
+
+
+static void PyObj_pjsua_buddy_info_import(PyObj_pjsua_buddy_info *obj,
+ const pjsua_buddy_info *info)
+{
+ obj->id = info->id;
+ Py_XDECREF(obj->uri);
+ obj->uri = PyString_FromStringAndSize(info->uri.ptr, info->uri.slen);
+ Py_XDECREF(obj->contact);
+ obj->contact = PyString_FromStringAndSize(info->contact.ptr, info->contact.slen);
+ obj->status = info->status;
+ Py_XDECREF(obj->status_text);
+ obj->status_text = PyString_FromStringAndSize(info->status_text.ptr,
+ info->status_text.slen);
+ obj->monitor_pres = info->monitor_pres;
+}
+
+
+/*
+ * PyObj_pjsua_buddy_info_new
+ * constructor for buddy_info object
+ * !modified @ 071206
+ */
+static PyObject * PyObj_pjsua_buddy_info_new(PyTypeObject *type,
+ PyObject *args,
+ PyObject *kwds)
+{
+ PyObj_pjsua_buddy_info *self;
+
+ PJ_UNUSED_ARG(args);
+ PJ_UNUSED_ARG(kwds);
+
+ self = (PyObj_pjsua_buddy_info *)type->tp_alloc(type, 0);
+ if (self != NULL) {
+ self->uri = PyString_FromString("");
+ if (self->uri == NULL) {
+ Py_DECREF(self);
+ return NULL;
+ }
+ self->contact = PyString_FromString("");
+ if (self->contact == NULL) {
+ Py_DECREF(self);
+ return NULL;
+ }
+ self->status_text = PyString_FromString("");
+ if (self->status_text == NULL) {
+ Py_DECREF(self);
+ return NULL;
+ }
+
+ }
+ return (PyObject *)self;
+}
+
+/*
+ * PyObj_pjsua_buddy_info_members
+ * !modified @ 071206
+ */
+static PyMemberDef PyObj_pjsua_buddy_info_members[] =
+{
+ {
+ "id", T_INT,
+ offsetof(PyObj_pjsua_buddy_info, id), 0,
+ "The buddy ID."
+ },
+ {
+ "uri", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_buddy_info, uri), 0,
+ "The full URI of the buddy, as specified in the configuration. "
+ },
+ {
+ "contact", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_buddy_info, contact), 0,
+ "Buddy's Contact, only available when presence subscription "
+ "has been established to the buddy."
+ },
+ {
+ "status", T_INT,
+ offsetof(PyObj_pjsua_buddy_info, status), 0,
+ "Buddy's online status. "
+ },
+ {
+ "status_text", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_buddy_info, status_text), 0,
+ "Text to describe buddy's online status."
+ },
+ {
+ "monitor_pres", T_INT,
+ offsetof(PyObj_pjsua_buddy_info, monitor_pres), 0,
+ "Flag to indicate that we should monitor the presence information "
+ "for this buddy (normally yes, unless explicitly disabled). "
+ },
+
+
+ {NULL} /* Sentinel */
+};
+
+
+
+
+/*
+ * PyTyp_pjsua_buddy_info
+ */
+static PyTypeObject PyTyp_pjsua_buddy_info =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "py_pjsua.Buddy_Info", /*tp_name*/
+ sizeof(PyObj_pjsua_buddy_info), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor)PyObj_pjsua_buddy_info_delete,/*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "Buddy Info objects", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ PyObj_pjsua_buddy_info_members, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ PyObj_pjsua_buddy_info_new, /* tp_new */
+
+};
+
+
+
+
+
+#endif /* __PY_PJSUA_H__ */
+
diff --git a/pjsip-apps/src/py_pjsua/setup.py b/pjsip-apps/src/py_pjsua/setup.py
new file mode 100644
index 0000000..2db59c2
--- /dev/null
+++ b/pjsip-apps/src/py_pjsua/setup.py
@@ -0,0 +1,44 @@
+from distutils.core import setup, Extension
+import os
+import sys
+
+# Fill in pj_inc_dirs
+pj_inc_dirs = []
+f = os.popen("make -f helper.mak inc_dir")
+for line in f:
+ pj_inc_dirs.append(line.rstrip("\r\n"))
+f.close()
+
+# Fill in pj_lib_dirs
+pj_lib_dirs = []
+f = os.popen("make -f helper.mak lib_dir")
+for line in f:
+ pj_lib_dirs.append(line.rstrip("\r\n"))
+f.close()
+
+# Fill in pj_libs
+pj_libs = []
+f = os.popen("make -f helper.mak libs")
+for line in f:
+ pj_libs.append(line.rstrip("\r\n"))
+f.close()
+
+# Mac OS X depedencies
+if sys.platform == 'darwin':
+ extra_link_args = ["-framework", "CoreFoundation",
+ "-framework", "AudioToolbox"]
+else:
+ extra_link_args = []
+
+
+setup(name="py_pjsua", version="0.8",
+ ext_modules = [
+ Extension("py_pjsua",
+ ["py_pjsua.c"],
+ define_macros=[('PJ_AUTOCONF', '1'),],
+ include_dirs=pj_inc_dirs,
+ library_dirs=pj_lib_dirs,
+ libraries=pj_libs,
+ extra_link_args=extra_link_args),
+ ])
+
diff --git a/pjsip-apps/src/python/Makefile b/pjsip-apps/src/python/Makefile
new file mode 100644
index 0000000..19a7e81
--- /dev/null
+++ b/pjsip-apps/src/python/Makefile
@@ -0,0 +1,12 @@
+all:
+ python setup.py build
+
+clean distclean realclean:
+ python setup.py clean
+ rm -rf ./build
+
+install:
+ python setup.py $@
+
+dep doc:
+
diff --git a/pjsip-apps/src/python/_pjsua.c b/pjsip-apps/src/python/_pjsua.c
new file mode 100644
index 0000000..bc00189
--- /dev/null
+++ b/pjsip-apps/src/python/_pjsua.c
@@ -0,0 +1,4605 @@
+/* $Id: _pjsua.c 3999 2012-03-30 07:10:13Z bennylp $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include "_pjsua.h"
+
+#define THIS_FILE "main.c"
+#define POOL_SIZE 512
+#define SND_DEV_NUM 64
+#define SND_NAME_LEN 64
+
+/* LIB BASE */
+
+static PyObject* g_obj_log_cb;
+static long g_thread_id;
+static struct py_thread_desc
+{
+ struct py_thread_desc *next;
+ pj_thread_desc desc;
+} *py_thread_desc;
+
+/*
+ * The global callback object.
+ */
+static PyObj_pjsua_callback * g_obj_callback;
+
+/* Set this to 1 if all threads are created by Python */
+#define NO_PJSIP_THREAD 1
+
+#if NO_PJSIP_THREAD
+# define ENTER_PYTHON()
+# define LEAVE_PYTHON()
+#else
+# define ENTER_PYTHON() PyGILState_STATE state = PyGILState_Ensure()
+# define LEAVE_PYTHON() PyGILState_Release(state)
+#endif
+
+
+static void clear_py_thread_desc(void)
+{
+ while (py_thread_desc) {
+ struct py_thread_desc *next = py_thread_desc->next;
+ free(py_thread_desc);
+ py_thread_desc = next;
+ }
+}
+
+
+/*
+ * cb_log_cb
+ * declares method for reconfiguring logging process for callback struct
+ */
+static void cb_log_cb(int level, const char *data, int len)
+{
+
+ /* Ignore if this callback is called from alien thread context,
+ * or otherwise it will crash Python.
+ */
+ if (pj_thread_local_get(g_thread_id) == 0)
+ return;
+
+ if (PyCallable_Check(g_obj_log_cb)) {
+ PyObject *param_data;
+
+ ENTER_PYTHON();
+
+ param_data = PyString_FromStringAndSize(data, len);
+
+ PyObject_CallFunction(
+ g_obj_log_cb,
+ "iOi",
+ level,
+ param_data,
+ len,
+ NULL
+ );
+
+ Py_DECREF(param_data);
+
+ LEAVE_PYTHON();
+ }
+}
+
+/*
+ * cb_on_call_state
+ * declares method on_call_state for callback struct
+ */
+static void cb_on_call_state(pjsua_call_id call_id, pjsip_event *e)
+{
+ PJ_UNUSED_ARG(e);
+
+ if (PyCallable_Check(g_obj_callback->on_call_state)) {
+ PyObject * obj;
+
+ ENTER_PYTHON();
+
+ obj = Py_BuildValue("");
+
+ PyObject_CallFunction(
+ g_obj_callback->on_call_state,
+ "iO",
+ call_id,
+ obj,
+ NULL
+ );
+
+ Py_DECREF(obj);
+
+ LEAVE_PYTHON();
+ }
+}
+
+
+/*
+ * cb_on_incoming_call
+ * declares method on_incoming_call for callback struct
+ */
+static void cb_on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id,
+ pjsip_rx_data *rdata)
+{
+ PJ_UNUSED_ARG(rdata);
+
+ if (PyCallable_Check(g_obj_callback->on_incoming_call)) {
+ PyObject *obj;
+
+ ENTER_PYTHON();
+
+ obj = Py_BuildValue("");
+
+ PyObject_CallFunction(
+ g_obj_callback->on_incoming_call,
+ "iiO",
+ acc_id,
+ call_id,
+ obj,
+ NULL
+ );
+
+ Py_DECREF(obj);
+
+ LEAVE_PYTHON();
+ }
+}
+
+
+/*
+ * cb_on_call_media_state
+ * declares method on_call_media_state for callback struct
+ */
+static void cb_on_call_media_state(pjsua_call_id call_id)
+{
+ if (PyCallable_Check(g_obj_callback->on_call_media_state)) {
+
+ ENTER_PYTHON();
+
+ PyObject_CallFunction(
+ g_obj_callback->on_call_media_state,
+ "i",
+ call_id,
+ NULL
+ );
+
+ LEAVE_PYTHON();
+ }
+}
+
+
+/*
+ * cb_on_dtmf_digit()
+ * Callback from PJSUA-LIB on receiving DTMF digit
+ */
+static void cb_on_dtmf_digit(pjsua_call_id call_id, int digit)
+{
+ if (PyCallable_Check(g_obj_callback->on_dtmf_digit)) {
+ char digit_str[10];
+
+ PyGILState_STATE state = PyGILState_Ensure();
+
+ pj_ansi_snprintf(digit_str, sizeof(digit_str), "%c", digit);
+
+ PyObject_CallFunction(
+ g_obj_callback->on_dtmf_digit,
+ "is",
+ call_id,
+ digit_str,
+ NULL
+ );
+
+ PyGILState_Release(state);
+ }
+}
+
+
+/*
+ * Notify application on call being transfered.
+ * !modified @061206
+ */
+static void cb_on_call_transfer_request(pjsua_call_id call_id,
+ const pj_str_t *dst,
+ pjsip_status_code *code)
+{
+ if (PyCallable_Check(g_obj_callback->on_call_transfer_request)) {
+ PyObject *ret, *param_dst;
+ int cd;
+
+ ENTER_PYTHON();
+
+ param_dst = PyString_FromPJ(dst);
+
+ ret = PyObject_CallFunction(
+ g_obj_callback->on_call_transfer_request,
+ "iOi",
+ call_id,
+ param_dst,
+ *code,
+ NULL
+ );
+
+ Py_DECREF(param_dst);
+
+ if (ret != NULL) {
+ if (ret != Py_None) {
+ if (PyArg_Parse(ret,"i",&cd)) {
+ *code = cd;
+ }
+ }
+ Py_DECREF(ret);
+ }
+
+ LEAVE_PYTHON();
+ }
+}
+
+
+/*
+ * Notify application of the status of previously sent call
+ * transfer request. Application can monitor the status of the
+ * call transfer request, for example to decide whether to
+ * terminate existing call.
+ * !modified @061206
+ */
+static void cb_on_call_transfer_status( pjsua_call_id call_id,
+ int status_code,
+ const pj_str_t *status_text,
+ pj_bool_t final,
+ pj_bool_t *p_cont)
+{
+ if (PyCallable_Check(g_obj_callback->on_call_transfer_status)) {
+ PyObject *ret, *param_reason;
+
+ ENTER_PYTHON();
+
+ param_reason = PyString_FromPJ(status_text);
+
+ ret = PyObject_CallFunction(
+ g_obj_callback->on_call_transfer_status,
+ "iiOii",
+ call_id,
+ status_code,
+ param_reason,
+ final,
+ *p_cont,
+ NULL
+ );
+
+ Py_DECREF(param_reason);
+
+ if (ret != NULL) {
+ if (ret != Py_None) {
+ int cnt;
+ if (PyArg_Parse(ret,"i",&cnt)) {
+ *p_cont = cnt;
+ }
+ }
+ Py_DECREF(ret);
+ }
+
+ LEAVE_PYTHON();
+ }
+}
+
+
+/*
+ * Notify application about incoming INVITE with Replaces header.
+ * Application may reject the request by setting non-2xx code.
+ * !modified @061206
+ */
+static void cb_on_call_replace_request( pjsua_call_id call_id,
+ pjsip_rx_data *rdata,
+ int *st_code,
+ pj_str_t *st_text)
+{
+ PJ_UNUSED_ARG(rdata);
+
+ if (PyCallable_Check(g_obj_callback->on_call_replace_request)) {
+ PyObject *ret, *param_reason, *param_rdata;
+ int cd;
+
+ ENTER_PYTHON();
+
+ param_reason = PyString_FromPJ(st_text);
+ param_rdata = Py_BuildValue("");
+
+ ret = PyObject_CallFunction(
+ g_obj_callback->on_call_replace_request,
+ "iOiO",
+ call_id,
+ param_rdata,
+ *st_code,
+ param_reason,
+ NULL
+ );
+
+ Py_DECREF(param_rdata);
+ Py_DECREF(param_reason);
+
+ if (ret != NULL) {
+ if (ret != Py_None) {
+ PyObject * txt;
+ if (PyArg_ParseTuple(ret,"iO",&cd, &txt)) {
+ *st_code = cd;
+ *st_text = PyString_ToPJ(txt);
+ }
+ }
+ Py_DECREF(ret);
+ }
+
+ LEAVE_PYTHON();
+ }
+}
+
+
+/*
+ * Notify application that an existing call has been replaced with
+ * a new call. This happens when PJSUA-API receives incoming INVITE
+ * request with Replaces header.
+ */
+static void cb_on_call_replaced(pjsua_call_id old_call_id,
+ pjsua_call_id new_call_id)
+{
+ if (PyCallable_Check(g_obj_callback->on_call_replaced)) {
+ ENTER_PYTHON();
+
+ PyObject_CallFunction(
+ g_obj_callback->on_call_replaced,
+ "ii",
+ old_call_id,
+ new_call_id,
+ NULL
+ );
+
+ LEAVE_PYTHON();
+ }
+}
+
+
+/*
+ * cb_on_reg_state
+ * declares method on_reg_state for callback struct
+ */
+static void cb_on_reg_state(pjsua_acc_id acc_id)
+{
+ if (PyCallable_Check(g_obj_callback->on_reg_state)) {
+ ENTER_PYTHON();
+
+ PyObject_CallFunction(
+ g_obj_callback->on_reg_state,
+ "i",
+ acc_id,
+ NULL
+ );
+
+ LEAVE_PYTHON();
+ }
+}
+
+/*
+ * cb_on_incoming_subscribe
+ */
+static void cb_on_incoming_subscribe( pjsua_acc_id acc_id,
+ pjsua_srv_pres *srv_pres,
+ pjsua_buddy_id buddy_id,
+ const pj_str_t *from,
+ pjsip_rx_data *rdata,
+ pjsip_status_code *code,
+ pj_str_t *reason,
+ pjsua_msg_data *msg_data)
+{
+ static char reason_buf[64];
+
+ PJ_UNUSED_ARG(rdata);
+ PJ_UNUSED_ARG(msg_data);
+
+ if (PyCallable_Check(g_obj_callback->on_incoming_subscribe)) {
+ PyObject *ret, *param_from, *param_contact, *param_srv_pres;
+ pjsip_contact_hdr *contact_hdr;
+ pj_pool_t *pool = NULL;
+
+ ENTER_PYTHON();
+
+ param_from = PyString_FromPJ(from);
+ param_srv_pres = PyLong_FromLong((long)srv_pres);
+
+ contact_hdr = (pjsip_contact_hdr*)
+ pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT,
+ NULL);
+ if (contact_hdr) {
+ char *contact;
+ int len;
+
+ pool = pjsua_pool_create("pytmp", 512, 512);
+ contact = (char*) pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE+1);
+ len = pjsip_uri_print(PJSIP_URI_IN_CONTACT_HDR, contact_hdr->uri,
+ contact, PJSIP_MAX_URL_SIZE);
+ if (len < 1)
+ len = 0;
+ contact[len] = '\0';
+
+ param_contact = PyString_FromStringAndSize(contact, len);
+ } else {
+ param_contact = Py_BuildValue("");
+ }
+
+ ret = PyObject_CallFunction(
+ g_obj_callback->on_incoming_subscribe,
+ "iiOOO",
+ acc_id,
+ buddy_id,
+ param_from,
+ param_contact,
+ param_srv_pres,
+ NULL
+ );
+
+ if (pool)
+ pj_pool_release(pool);
+
+ Py_DECREF(param_from);
+ Py_DECREF(param_contact);
+ Py_DECREF(param_srv_pres);
+
+ if (ret && PyTuple_Check(ret)) {
+ if (PyTuple_Size(ret) >= 1)
+ *code = (int)PyInt_AsLong(PyTuple_GetItem(ret, 0));
+ if (PyTuple_Size(ret) >= 2) {
+ if (PyTuple_GetItem(ret, 1) != Py_None) {
+ pj_str_t tmp;
+ tmp = PyString_ToPJ(PyTuple_GetItem(ret, 1));
+ reason->ptr = reason_buf;
+ pj_strncpy(reason, &tmp, sizeof(reason_buf));
+ } else {
+ reason->slen = 0;
+ }
+ }
+ Py_XDECREF(ret);
+ } else if (ret) {
+ Py_XDECREF(ret);
+ }
+
+ LEAVE_PYTHON();
+ }
+}
+
+/*
+ * cb_on_buddy_state
+ * declares method on_buddy state for callback struct
+ */
+static void cb_on_buddy_state(pjsua_buddy_id buddy_id)
+{
+ if (PyCallable_Check(g_obj_callback->on_buddy_state)) {
+ ENTER_PYTHON();
+
+ PyObject_CallFunction(
+ g_obj_callback->on_buddy_state,
+ "i",
+ buddy_id,
+ NULL
+ );
+
+ LEAVE_PYTHON();
+ }
+}
+
+/*
+ * cb_on_pager
+ * declares method on_pager for callback struct
+ */
+static void cb_on_pager(pjsua_call_id call_id, const pj_str_t *from,
+ const pj_str_t *to, const pj_str_t *contact,
+ const pj_str_t *mime_type, const pj_str_t *body,
+ pjsip_rx_data *rdata, pjsua_acc_id acc_id)
+{
+ PJ_UNUSED_ARG(rdata);
+
+ if (PyCallable_Check(g_obj_callback->on_pager)) {
+ PyObject *param_from, *param_to, *param_contact, *param_mime_type,
+ *param_body;
+
+ ENTER_PYTHON();
+
+ param_from = PyString_FromPJ(from);
+ param_to = PyString_FromPJ(to);
+ param_contact = PyString_FromPJ(contact);
+ param_mime_type = PyString_FromPJ(mime_type);
+ param_body = PyString_FromPJ(body);
+
+ PyObject_CallFunction(
+ g_obj_callback->on_pager,
+ "iOOOOOi",
+ call_id,
+ param_from,
+ param_to,
+ param_contact,
+ param_mime_type,
+ param_body,
+ acc_id,
+ NULL
+ );
+
+ Py_DECREF(param_body);
+ Py_DECREF(param_mime_type);
+ Py_DECREF(param_contact);
+ Py_DECREF(param_to);
+ Py_DECREF(param_from);
+
+ LEAVE_PYTHON();
+ }
+}
+
+
+/*
+ * cb_on_pager_status
+ * declares method on_pager_status for callback struct
+ */
+static void cb_on_pager_status(pjsua_call_id call_id, const pj_str_t *to,
+ const pj_str_t *body, void *user_data,
+ pjsip_status_code status,
+ const pj_str_t *reason,
+ pjsip_tx_data *tdata,
+ pjsip_rx_data *rdata,
+ pjsua_acc_id acc_id)
+{
+ if (PyCallable_Check(g_obj_callback->on_pager)) {
+ PyObject *param_call_id, *param_to, *param_body,
+ *param_user_data, *param_status, *param_reason,
+ *param_acc_id;
+
+ ENTER_PYTHON();
+
+ PJ_UNUSED_ARG(tdata);
+ PJ_UNUSED_ARG(rdata);
+
+ PyObject_CallFunctionObjArgs(
+ g_obj_callback->on_pager_status,
+ param_call_id = Py_BuildValue("i",call_id),
+ param_to = PyString_FromPJ(to),
+ param_body = PyString_FromPJ(body),
+ param_user_data = Py_BuildValue("i", user_data),
+ param_status = Py_BuildValue("i",status),
+ param_reason = PyString_FromPJ(reason),
+ param_acc_id = Py_BuildValue("i",acc_id),
+ NULL
+ );
+
+ Py_DECREF(param_call_id);
+ Py_DECREF(param_to);
+ Py_DECREF(param_body);
+ Py_DECREF(param_user_data);
+ Py_DECREF(param_status);
+ Py_DECREF(param_reason);
+ Py_DECREF(param_acc_id);
+
+ LEAVE_PYTHON();
+ }
+}
+
+
+/*
+ * cb_on_typing
+ * declares method on_typing for callback struct
+ */
+static void cb_on_typing(pjsua_call_id call_id, const pj_str_t *from,
+ const pj_str_t *to, const pj_str_t *contact,
+ pj_bool_t is_typing, pjsip_rx_data *rdata,
+ pjsua_acc_id acc_id)
+{
+ if (PyCallable_Check(g_obj_callback->on_typing)) {
+ PyObject *param_call_id, *param_from, *param_to, *param_contact,
+ *param_is_typing, *param_acc_id;
+
+ ENTER_PYTHON();
+
+ PJ_UNUSED_ARG(rdata);
+
+ PyObject_CallFunctionObjArgs(
+ g_obj_callback->on_typing,
+ param_call_id = Py_BuildValue("i",call_id),
+ param_from = PyString_FromPJ(from),
+ param_to = PyString_FromPJ(to),
+ param_contact = PyString_FromPJ(contact),
+ param_is_typing = Py_BuildValue("i",is_typing),
+ param_acc_id = Py_BuildValue("i",acc_id),
+ NULL
+ );
+
+ Py_DECREF(param_call_id);
+ Py_DECREF(param_from);
+ Py_DECREF(param_to);
+ Py_DECREF(param_contact);
+ Py_DECREF(param_is_typing);
+ Py_DECREF(param_acc_id);
+
+ LEAVE_PYTHON();
+ }
+}
+
+
+/*
+ * on_mwi_info
+ */
+static void cb_on_mwi_info(pjsua_acc_id acc_id, pjsua_mwi_info *mwi_info)
+{
+ if (PyCallable_Check(g_obj_callback->on_mwi_info)) {
+ PyObject *param_acc_id, *param_body;
+ pj_str_t body;
+
+ ENTER_PYTHON();
+
+ body.ptr = mwi_info->rdata->msg_info.msg->body->data;
+ body.slen = mwi_info->rdata->msg_info.msg->body->len;
+
+ PyObject_CallFunctionObjArgs(
+ g_obj_callback->on_mwi_info,
+ param_acc_id = Py_BuildValue("i",acc_id),
+ param_body = PyString_FromPJ(&body),
+ NULL
+ );
+
+ Py_DECREF(param_acc_id);
+ Py_DECREF(param_body);
+
+ LEAVE_PYTHON();
+ }
+}
+
+/*
+ * translate_hdr
+ * internal function
+ * translate from hdr_list to pjsip_generic_string_hdr
+ */
+void translate_hdr(pj_pool_t *pool, pjsip_hdr *hdr, PyObject *py_hdr_list)
+{
+ pj_list_init(hdr);
+
+ if (PyList_Check(py_hdr_list)) {
+ int i;
+
+ for (i=0; i<PyList_Size(py_hdr_list); ++i) {
+ pj_str_t hname, hvalue;
+ pjsip_generic_string_hdr * new_hdr;
+ PyObject * tuple = PyList_GetItem(py_hdr_list, i);
+
+ if (PyTuple_Check(tuple)) {
+ if (PyTuple_Size(tuple) >= 1)
+ hname = PyString_ToPJ(PyTuple_GetItem(tuple,0));
+ else
+ hname.slen = 0;
+ if (PyTuple_Size(tuple) >= 2)
+ hvalue = PyString_ToPJ(PyTuple_GetItem(tuple,1));
+ else
+ hvalue.slen = 0;
+ } else {
+ hname.ptr = "";
+ hname.slen = 0;
+ hvalue.ptr = "";
+ hvalue.slen = 0;
+ }
+ new_hdr = pjsip_generic_string_hdr_create(pool, &hname, &hvalue);
+ pj_list_push_back((pj_list_type *)hdr, (pj_list_type *)new_hdr);
+ }
+ }
+}
+
+/*
+ * py_pjsua_thread_register
+ */
+static PyObject *py_pjsua_thread_register(PyObject *pSelf, PyObject *pArgs)
+{
+ pj_status_t status;
+ const char *name;
+ PyObject *py_desc;
+ pj_thread_t *thread;
+ struct py_thread_desc *thread_desc;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "sO", &name, &py_desc)) {
+ return NULL;
+ }
+ thread_desc = (struct py_thread_desc*)
+ malloc(sizeof(struct py_thread_desc));
+ thread_desc->next = py_thread_desc;
+ py_thread_desc = thread_desc;
+
+ status = pj_thread_register(name, thread_desc->desc, &thread);
+
+ if (status == PJ_SUCCESS)
+ status = pj_thread_local_set(g_thread_id, (void*)1);
+
+ return Py_BuildValue("i",status);
+}
+
+/*
+ * py_pjsua_logging_config_default
+ */
+static PyObject *py_pjsua_logging_config_default(PyObject *pSelf,
+ PyObject *pArgs)
+{
+ PyObj_pjsua_logging_config *obj;
+ pjsua_logging_config cfg;
+
+ PJ_UNUSED_ARG(pSelf);
+ PJ_UNUSED_ARG(pArgs);
+
+ pjsua_logging_config_default(&cfg);
+ obj = (PyObj_pjsua_logging_config*)
+ PyObj_pjsua_logging_config_new(&PyTyp_pjsua_logging_config,
+ NULL, NULL);
+ PyObj_pjsua_logging_config_import(obj, &cfg);
+
+ return (PyObject*)obj;
+}
+
+
+/*
+ * py_pjsua_config_default
+ */
+static PyObject *py_pjsua_config_default(PyObject *pSelf, PyObject *pArgs)
+{
+ PyObj_pjsua_config *obj;
+ pjsua_config cfg;
+
+ PJ_UNUSED_ARG(pSelf);
+ PJ_UNUSED_ARG(pArgs);
+
+ pjsua_config_default(&cfg);
+ obj = (PyObj_pjsua_config *) PyObj_pjsua_config_new(&PyTyp_pjsua_config,
+ NULL, NULL);
+ PyObj_pjsua_config_import(obj, &cfg);
+
+ return (PyObject*)obj;
+}
+
+
+/*
+ * py_pjsua_media_config_default
+ */
+static PyObject * py_pjsua_media_config_default(PyObject *pSelf,
+ PyObject *pArgs)
+{
+ PyObj_pjsua_media_config *obj;
+ pjsua_media_config cfg;
+
+ PJ_UNUSED_ARG(pSelf);
+ PJ_UNUSED_ARG(pArgs);
+
+ pjsua_media_config_default(&cfg);
+ obj = (PyObj_pjsua_media_config *)
+ PyType_GenericNew(&PyTyp_pjsua_media_config, NULL, NULL);
+ PyObj_pjsua_media_config_import(obj, &cfg);
+
+ return (PyObject *)obj;
+}
+
+
+/*
+ * py_pjsua_msg_data_init
+ */
+static PyObject *py_pjsua_msg_data_init(PyObject *pSelf, PyObject *pArgs)
+{
+ PJ_UNUSED_ARG(pSelf);
+ PJ_UNUSED_ARG(pArgs);
+
+ return (PyObject *)PyObj_pjsua_msg_data_new(&PyTyp_pjsua_msg_data,
+ NULL, NULL);
+}
+
+
+/*
+ * py_pjsua_reconfigure_logging
+ */
+static PyObject *py_pjsua_reconfigure_logging(PyObject *pSelf,
+ PyObject *pArgs)
+{
+ PyObject *logObj;
+ pj_status_t status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "O", &logObj)) {
+ return NULL;
+ }
+
+ if (logObj != Py_None) {
+ PyObj_pjsua_logging_config *log;
+ pjsua_logging_config cfg;
+
+ log = (PyObj_pjsua_logging_config*)logObj;
+ cfg.msg_logging = log->msg_logging;
+ cfg.level = log->level;
+ cfg.console_level = log->console_level;
+ cfg.decor = log->decor;
+ cfg.log_filename = PyString_ToPJ(log->log_filename);
+ Py_XDECREF(g_obj_log_cb);
+ g_obj_log_cb = log->cb;
+ Py_INCREF(g_obj_log_cb);
+ cfg.cb = &cb_log_cb;
+ status = pjsua_reconfigure_logging(&cfg);
+ } else {
+ status = pjsua_reconfigure_logging(NULL);
+ }
+
+ return Py_BuildValue("i",status);
+}
+
+
+/*
+ * py_pjsua_perror
+ */
+static PyObject *py_pjsua_perror(PyObject *pSelf, PyObject *pArgs)
+{
+ const char *sender;
+ const char *title;
+ pj_status_t status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "ssi", &sender, &title, &status)) {
+ return NULL;
+ }
+
+ pjsua_perror(sender, title, status);
+
+ return Py_BuildValue("");
+}
+
+
+/*
+ * py_pjsua_create
+ */
+static PyObject *py_pjsua_create(PyObject *pSelf, PyObject *pArgs)
+{
+ pj_status_t status;
+
+ PJ_UNUSED_ARG(pSelf);
+ PJ_UNUSED_ARG(pArgs);
+
+ status = pjsua_create();
+
+ if (status == PJ_SUCCESS) {
+ status = pj_thread_local_alloc(&g_thread_id);
+ if (status == PJ_SUCCESS)
+ status = pj_thread_local_set(g_thread_id, (void*)1);
+
+ pj_atexit(&clear_py_thread_desc);
+ }
+
+ return Py_BuildValue("i",status);
+}
+
+
+/*
+ * py_pjsua_init
+ */
+static PyObject *py_pjsua_init(PyObject *pSelf, PyObject *pArgs)
+{
+ pj_status_t status;
+ PyObject *o_ua_cfg, *o_log_cfg, *o_media_cfg;
+ pjsua_config cfg_ua, *p_cfg_ua;
+ pjsua_logging_config cfg_log, *p_cfg_log;
+ pjsua_media_config cfg_media, *p_cfg_media;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "OOO", &o_ua_cfg, &o_log_cfg, &o_media_cfg)) {
+ return NULL;
+ }
+
+ pjsua_config_default(&cfg_ua);
+ pjsua_logging_config_default(&cfg_log);
+ pjsua_media_config_default(&cfg_media);
+
+ if (o_ua_cfg != Py_None) {
+ PyObj_pjsua_config *obj_ua_cfg = (PyObj_pjsua_config*)o_ua_cfg;
+
+ PyObj_pjsua_config_export(&cfg_ua, obj_ua_cfg);
+
+ Py_XDECREF(g_obj_callback);
+ g_obj_callback = obj_ua_cfg->cb;
+ Py_INCREF(g_obj_callback);
+
+ cfg_ua.cb.on_call_state = &cb_on_call_state;
+ cfg_ua.cb.on_incoming_call = &cb_on_incoming_call;
+ cfg_ua.cb.on_call_media_state = &cb_on_call_media_state;
+ cfg_ua.cb.on_dtmf_digit = &cb_on_dtmf_digit;
+ cfg_ua.cb.on_call_transfer_request = &cb_on_call_transfer_request;
+ cfg_ua.cb.on_call_transfer_status = &cb_on_call_transfer_status;
+ cfg_ua.cb.on_call_replace_request = &cb_on_call_replace_request;
+ cfg_ua.cb.on_call_replaced = &cb_on_call_replaced;
+ cfg_ua.cb.on_reg_state = &cb_on_reg_state;
+ cfg_ua.cb.on_incoming_subscribe = &cb_on_incoming_subscribe;
+ cfg_ua.cb.on_buddy_state = &cb_on_buddy_state;
+ cfg_ua.cb.on_pager2 = &cb_on_pager;
+ cfg_ua.cb.on_pager_status2 = &cb_on_pager_status;
+ cfg_ua.cb.on_typing2 = &cb_on_typing;
+ cfg_ua.cb.on_mwi_info = &cb_on_mwi_info;
+
+ p_cfg_ua = &cfg_ua;
+
+ } else {
+ p_cfg_ua = NULL;
+ }
+
+ if (o_log_cfg != Py_None) {
+ PyObj_pjsua_logging_config * obj_log;
+
+ obj_log = (PyObj_pjsua_logging_config *)o_log_cfg;
+
+ PyObj_pjsua_logging_config_export(&cfg_log, obj_log);
+
+ Py_XDECREF(g_obj_log_cb);
+ g_obj_log_cb = obj_log->cb;
+ Py_INCREF(g_obj_log_cb);
+
+ cfg_log.cb = &cb_log_cb;
+ p_cfg_log = &cfg_log;
+
+ } else {
+ p_cfg_log = NULL;
+ }
+
+ if (o_media_cfg != Py_None) {
+ PyObj_pjsua_media_config_export(&cfg_media,
+ (PyObj_pjsua_media_config*)o_media_cfg);
+ p_cfg_media = &cfg_media;
+
+ } else {
+ p_cfg_media = NULL;
+ }
+
+ status = pjsua_init(p_cfg_ua, p_cfg_log, p_cfg_media);
+
+ return Py_BuildValue("i", status);
+}
+
+
+/*
+ * py_pjsua_start
+ */
+static PyObject *py_pjsua_start(PyObject *pSelf, PyObject *pArgs)
+{
+ pj_status_t status;
+
+ PJ_UNUSED_ARG(pSelf);
+ PJ_UNUSED_ARG(pArgs);
+
+ status = pjsua_start();
+
+ return Py_BuildValue("i", status);
+}
+
+
+/*
+ * py_pjsua_destroy
+ */
+static PyObject *py_pjsua_destroy(PyObject *pSelf, PyObject *pArgs)
+{
+ pj_status_t status;
+
+ PJ_UNUSED_ARG(pSelf);
+ PJ_UNUSED_ARG(pArgs);
+
+ status = pjsua_destroy();
+
+ return Py_BuildValue("i", status);
+}
+
+
+/*
+ * py_pjsua_handle_events
+ */
+static PyObject *py_pjsua_handle_events(PyObject *pSelf, PyObject *pArgs)
+{
+ int ret;
+ int msec;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &msec)) {
+ return NULL;
+ }
+
+ if (msec < 0)
+ msec = 0;
+
+#if !NO_PJSIP_THREAD
+ /* Since handle_events() will block, we must wrap it with ALLOW_THREADS
+ * construct, or otherwise many Python blocking functions (such as
+ * time.sleep(), readline(), etc.) may hang/block indefinitely.
+ * See http://www.python.org/doc/current/api/threads.html for more info.
+ */
+ Py_BEGIN_ALLOW_THREADS
+#endif
+
+ ret = pjsua_handle_events(msec);
+
+#if !NO_PJSIP_THREAD
+ Py_END_ALLOW_THREADS
+#endif
+
+ return Py_BuildValue("i", ret);
+}
+
+
+/*
+ * py_pjsua_verify_sip_url
+ */
+static PyObject *py_pjsua_verify_sip_url(PyObject *pSelf, PyObject *pArgs)
+{
+ pj_status_t status;
+ const char *url;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "s", &url)) {
+ return NULL;
+ }
+
+ status = pjsua_verify_sip_url(url);
+
+ return Py_BuildValue("i", status);
+}
+
+
+/*
+ * function doc
+ */
+
+static char pjsua_thread_register_doc[] =
+ "int _pjsua.thread_register(string name, int[] desc)";
+static char pjsua_perror_doc[] =
+ "void _pjsua.perror (string sender, string title, int status) "
+ "Display error message for the specified error code. Parameters: "
+ "sender: The log sender field; "
+ "title: Message title for the error; "
+ "status: Status code.";
+
+static char pjsua_create_doc[] =
+ "int _pjsua.create (void) "
+ "Instantiate pjsua application. Application "
+ "must call this function before calling any other functions, to make sure "
+ "that the underlying libraries are properly initialized. Once this "
+ "function has returned success, application must call pjsua_destroy() "
+ "before quitting.";
+
+static char pjsua_init_doc[] =
+ "int _pjsua.init (_pjsua.Config obj_ua_cfg, "
+ "_pjsua.Logging_Config log_cfg, _pjsua.Media_Config media_cfg) "
+ "Initialize pjsua with the specified settings. All the settings are "
+ "optional, and the default values will be used when the config is not "
+ "specified. Parameters: "
+ "obj_ua_cfg : User agent configuration; "
+ "log_cfg : Optional logging configuration; "
+ "media_cfg : Optional media configuration.";
+
+static char pjsua_start_doc[] =
+ "int _pjsua.start (void) "
+ "Application is recommended to call this function after all "
+ "initialization is done, so that the library can do additional checking "
+ "set up additional";
+
+static char pjsua_destroy_doc[] =
+ "int _pjsua.destroy (void) "
+ "Destroy pjsua This function must be called once PJSUA is created. To "
+ "make it easier for application, application may call this function "
+ "several times with no danger.";
+
+static char pjsua_handle_events_doc[] =
+ "int _pjsua.handle_events (int msec_timeout) "
+ "Poll pjsua for events, and if necessary block the caller thread for the "
+ "specified maximum interval (in miliseconds) Parameters: "
+ "msec_timeout: Maximum time to wait, in miliseconds. "
+ "Returns: The number of events that have been handled during the poll. "
+ "Negative value indicates error, and application can retrieve the error "
+ "as (err = -return_value).";
+
+static char pjsua_verify_sip_url_doc[] =
+ "int _pjsua.verify_sip_url (string c_url) "
+ "Verify that valid SIP url is given Parameters: "
+ "c_url: The URL, as NULL terminated string.";
+
+static char pjsua_reconfigure_logging_doc[] =
+ "int _pjsua.reconfigure_logging (_pjsua.Logging_Config c) "
+ "Application can call this function at any time (after pjsua_create(), of "
+ "course) to change logging settings. Parameters: "
+ "c: Logging configuration.";
+
+static char pjsua_logging_config_default_doc[] =
+ "_pjsua.Logging_Config _pjsua.logging_config_default () "
+ "Use this function to initialize logging config.";
+
+static char pjsua_config_default_doc[] =
+ "_pjsua.Config _pjsua.config_default (). Use this function to "
+ "initialize pjsua config. ";
+
+static char pjsua_media_config_default_doc[] =
+ "_pjsua.Media_Config _pjsua.media_config_default (). "
+ "Use this function to initialize media config.";
+
+static char pjsua_msg_data_init_doc[] =
+ "_pjsua.Msg_Data void _pjsua.msg_data_init () "
+ "Initialize message data ";
+
+
+/* END OF LIB BASE */
+
+/* LIB TRANSPORT */
+
+/*
+ * py_pjsua_transport_config_default
+ */
+static PyObject *py_pjsua_transport_config_default(PyObject *pSelf,
+ PyObject *pArgs)
+{
+ PyObj_pjsua_transport_config *obj;
+ pjsua_transport_config cfg;
+
+ PJ_UNUSED_ARG(pSelf);
+ PJ_UNUSED_ARG(pArgs);
+
+ pjsua_transport_config_default(&cfg);
+ obj = (PyObj_pjsua_transport_config*)
+ PyObj_pjsua_transport_config_new(&PyTyp_pjsua_transport_config,
+ NULL, NULL);
+ PyObj_pjsua_transport_config_import(obj, &cfg);
+
+ return (PyObject *)obj;
+}
+
+/*
+ * py_pjsua_transport_create
+ */
+static PyObject *py_pjsua_transport_create(PyObject *pSelf, PyObject *pArgs)
+{
+ pj_status_t status;
+ int type;
+ PyObject *pCfg;
+ pjsua_transport_config cfg;
+ pjsua_transport_id id;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "iO", &type, &pCfg)) {
+ return NULL;
+ }
+
+ if (pCfg != Py_None) {
+ PyObj_pjsua_transport_config *obj;
+
+ obj = (PyObj_pjsua_transport_config*)pCfg;
+ PyObj_pjsua_transport_config_export(&cfg, obj);
+ status = pjsua_transport_create(type, &cfg, &id);
+ } else {
+ status = pjsua_transport_create(type, NULL, &id);
+ }
+
+
+ return Py_BuildValue("ii", status, id);
+}
+
+/*
+ * py_pjsua_enum_transports
+ */
+static PyObject *py_pjsua_enum_transports(PyObject *pSelf, PyObject *pArgs)
+{
+ pj_status_t status;
+ PyObject *list;
+ pjsua_transport_id id[PJSIP_MAX_TRANSPORTS];
+ unsigned c, i;
+
+ PJ_UNUSED_ARG(pSelf);
+ PJ_UNUSED_ARG(pArgs);
+
+ c = PJ_ARRAY_SIZE(id);
+ status = pjsua_enum_transports(id, &c);
+
+ list = PyList_New(c);
+ for (i = 0; i < c; i++) {
+ PyList_SetItem(list, i, Py_BuildValue("i", id[i]));
+ }
+
+ return (PyObject*)list;
+}
+
+/*
+ * py_pjsua_transport_get_info
+ * !modified @ 051206
+ */
+static PyObject *py_pjsua_transport_get_info(PyObject *pSelf, PyObject *pArgs)
+{
+ pj_status_t status;
+ int id;
+ pjsua_transport_info info;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &id)) {
+ return NULL;
+ }
+
+ status = pjsua_transport_get_info(id, &info);
+ if (status == PJ_SUCCESS) {
+ PyObj_pjsua_transport_info *obj;
+ obj = (PyObj_pjsua_transport_info *)
+ PyObj_pjsua_transport_info_new(&PyTyp_pjsua_transport_info,
+ NULL, NULL);
+ PyObj_pjsua_transport_info_import(obj, &info);
+ return (PyObject*)obj;
+ } else {
+ return Py_BuildValue("");
+ }
+}
+
+/*
+ * py_pjsua_transport_set_enable
+ */
+static PyObject *py_pjsua_transport_set_enable(PyObject *pSelf,
+ PyObject *pArgs)
+{
+ pj_status_t status;
+ int id;
+ int enabled;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "ii", &id, &enabled)) {
+ return NULL;
+ }
+ status = pjsua_transport_set_enable(id, enabled);
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_transport_close
+ */
+static PyObject *py_pjsua_transport_close(PyObject *pSelf, PyObject *pArgs)
+{
+ pj_status_t status;
+ int id;
+ int force;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "ii", &id, &force)) {
+ return NULL;
+ }
+ status = pjsua_transport_close(id, force);
+
+ return Py_BuildValue("i", status);
+}
+
+static char pjsua_transport_config_default_doc[] =
+ "_pjsua.Transport_Config _pjsua.transport_config_default () "
+ "Call this function to initialize UDP config with default values.";
+static char pjsua_transport_create_doc[] =
+ "int, int _pjsua.transport_create (int type, "
+ "_pjsua.Transport_Config cfg) "
+ "Create SIP transport.";
+static char pjsua_enum_transports_doc[] =
+ "int[] _pjsua.enum_transports () "
+ "Enumerate all transports currently created in the system.";
+static char pjsua_transport_get_info_doc[] =
+ "void _pjsua.transport_get_info "
+ "(_pjsua.Transport_ID id, _pjsua.Transport_Info info) "
+ "Get information about transports.";
+static char pjsua_transport_set_enable_doc[] =
+ "void _pjsua.transport_set_enable "
+ "(_pjsua.Transport_ID id, int enabled) "
+ "Disable a transport or re-enable it. "
+ "By default transport is always enabled after it is created. "
+ "Disabling a transport does not necessarily close the socket, "
+ "it will only discard incoming messages and prevent the transport "
+ "from being used to send outgoing messages.";
+static char pjsua_transport_close_doc[] =
+ "void _pjsua.transport_close (_pjsua.Transport_ID id, int force) "
+ "Close the transport. If transport is forcefully closed, "
+ "it will be immediately closed, and any pending transactions "
+ "that are using the transport may not terminate properly. "
+ "Otherwise, the system will wait until all transactions are closed "
+ "while preventing new users from using the transport, and will close "
+ "the transport when it is safe to do so.";
+
+/* END OF LIB TRANSPORT */
+
+/* LIB ACCOUNT */
+
+
+/*
+ * py_pjsua_acc_config_default
+ */
+static PyObject *py_pjsua_acc_config_default(PyObject *pSelf, PyObject *pArgs)
+{
+ PyObj_pjsua_acc_config *obj;
+ pjsua_acc_config cfg;
+
+ PJ_UNUSED_ARG(pSelf);
+ PJ_UNUSED_ARG(pArgs);
+
+ if (!PyArg_ParseTuple(pArgs, "")) {
+ return NULL;
+ }
+
+ pjsua_acc_config_default(&cfg);
+ obj = (PyObj_pjsua_acc_config *)
+ PyObj_pjsua_acc_config_new(&PyTyp_pjsua_acc_config,
+ NULL, NULL);
+ PyObj_pjsua_acc_config_import(obj, &cfg);
+ return (PyObject *)obj;
+}
+
+/*
+ * py_pjsua_acc_get_count
+ */
+static PyObject *py_pjsua_acc_get_count(PyObject *pSelf, PyObject *pArgs)
+{
+ int count;
+
+ PJ_UNUSED_ARG(pSelf);
+ PJ_UNUSED_ARG(pArgs);
+
+ count = pjsua_acc_get_count();
+ return Py_BuildValue("i", count);
+}
+
+/*
+ * py_pjsua_acc_is_valid
+ */
+static PyObject *py_pjsua_acc_is_valid(PyObject *pSelf, PyObject *pArgs)
+{
+ int id;
+ int is_valid;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &id)) {
+ return NULL;
+ }
+
+ is_valid = pjsua_acc_is_valid(id);
+ return Py_BuildValue("i", is_valid);
+}
+
+/*
+ * py_pjsua_acc_set_default
+ */
+static PyObject *py_pjsua_acc_set_default(PyObject *pSelf, PyObject *pArgs)
+{
+ int id;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &id)) {
+ return NULL;
+ }
+ status = pjsua_acc_set_default(id);
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_acc_get_default
+ */
+static PyObject *py_pjsua_acc_get_default(PyObject *pSelf, PyObject *pArgs)
+{
+ int id;
+
+ PJ_UNUSED_ARG(pSelf);
+ PJ_UNUSED_ARG(pArgs);
+
+ id = pjsua_acc_get_default();
+
+ return Py_BuildValue("i", id);
+}
+
+/*
+ * py_pjsua_acc_add
+ */
+static PyObject *py_pjsua_acc_add(PyObject *pSelf, PyObject *pArgs)
+{
+ int is_default;
+ PyObject *pCfg;
+ int acc_id;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "Oi", &pCfg, &is_default)) {
+ return NULL;
+ }
+
+ if (pCfg != Py_None) {
+ pjsua_acc_config cfg;
+ PyObj_pjsua_acc_config *ac;
+
+ pjsua_acc_config_default(&cfg);
+ ac = (PyObj_pjsua_acc_config *)pCfg;
+ PyObj_pjsua_acc_config_export(&cfg, ac);
+ status = pjsua_acc_add(&cfg, is_default, &acc_id);
+ } else {
+ status = PJ_EINVAL;
+ acc_id = PJSUA_INVALID_ID;
+ }
+
+ return Py_BuildValue("ii", status, acc_id);
+}
+
+/*
+ * py_pjsua_acc_add_local
+ */
+static PyObject *py_pjsua_acc_add_local(PyObject *pSelf, PyObject *pArgs)
+{
+ int is_default;
+ int tid;
+ int acc_id;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "ii", &tid, &is_default)) {
+ return NULL;
+ }
+
+ status = pjsua_acc_add_local(tid, is_default, &acc_id);
+
+ return Py_BuildValue("ii", status, acc_id);
+}
+
+/*
+ * py_pjsua_acc_set_user_data
+ */
+static PyObject *py_pjsua_acc_set_user_data(PyObject *pSelf, PyObject *pArgs)
+{
+ int acc_id;
+ PyObject *pUserData, *old_user_data;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "iO", &acc_id, &pUserData)) {
+ return NULL;
+ }
+
+ old_user_data = (PyObject*) pjsua_acc_get_user_data(acc_id);
+
+ status = pjsua_acc_set_user_data(acc_id, (void*)pUserData);
+
+ if (status == PJ_SUCCESS) {
+ Py_XINCREF(pUserData);
+ Py_XDECREF(old_user_data);
+ }
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_acc_get_user_data
+ */
+static PyObject *py_pjsua_acc_get_user_data(PyObject *pSelf, PyObject *pArgs)
+{
+ int acc_id;
+ PyObject *user_data;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &acc_id)) {
+ return NULL;
+ }
+
+ user_data = (PyObject*) pjsua_acc_get_user_data(acc_id);
+
+ return user_data ? Py_BuildValue("O", user_data) : Py_BuildValue("");
+}
+
+/*
+ * py_pjsua_acc_del
+ */
+static PyObject *py_pjsua_acc_del(PyObject *pSelf, PyObject *pArgs)
+{
+ int acc_id;
+ PyObject *user_data;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &acc_id)) {
+ return NULL;
+ }
+
+ user_data = (PyObject*) pjsua_acc_get_user_data(acc_id);
+ Py_XDECREF(user_data);
+
+ status = pjsua_acc_del(acc_id);
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_acc_modify
+ */
+static PyObject *py_pjsua_acc_modify(PyObject *pSelf, PyObject *pArgs)
+{
+ PyObject *pCfg;
+ PyObj_pjsua_acc_config * ac;
+ int acc_id;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "iO", &acc_id, &pCfg)) {
+ return NULL;
+ }
+
+ if (pCfg != Py_None) {
+ pjsua_acc_config cfg;
+
+ pjsua_acc_config_default(&cfg);
+ ac = (PyObj_pjsua_acc_config*)pCfg;
+ PyObj_pjsua_acc_config_export(&cfg, ac);
+
+ status = pjsua_acc_modify(acc_id, &cfg);
+ } else {
+ status = PJ_EINVAL;
+ }
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_acc_set_online_status
+ */
+static PyObject *py_pjsua_acc_set_online_status(PyObject *pSelf,
+ PyObject *pArgs)
+{
+ int is_online;
+ int acc_id;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "ii", &acc_id, &is_online)) {
+ return NULL;
+ }
+
+ status = pjsua_acc_set_online_status(acc_id, is_online);
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_acc_set_online_status2
+ */
+static PyObject *py_pjsua_acc_set_online_status2(PyObject *pSelf,
+ PyObject *pArgs)
+{
+ int is_online;
+ int acc_id;
+ int activity_id;
+ const char *activity_text = NULL;
+ const char *rpid_id = NULL;
+ pjrpid_element rpid;
+ pj_status_t status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "iiiss", &acc_id, &is_online,
+ &activity_id, &activity_text, &rpid_id))
+ {
+ return NULL;
+ }
+
+ pj_bzero(&rpid, sizeof(rpid));
+ rpid.type = PJRPID_ELEMENT_TYPE_PERSON;
+ rpid.activity = activity_id;
+ if (activity_text)
+ rpid.note = pj_str((char*)activity_text);
+
+ if (rpid_id)
+ rpid.id = pj_str((char*)rpid_id);
+
+ status = pjsua_acc_set_online_status2(acc_id, is_online, &rpid);
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_acc_set_registration
+ */
+static PyObject *py_pjsua_acc_set_registration(PyObject *pSelf,
+ PyObject *pArgs)
+{
+ int renew;
+ int acc_id;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "ii", &acc_id, &renew)) {
+ return NULL;
+ }
+
+ status = pjsua_acc_set_registration(acc_id, renew);
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_acc_get_info
+ */
+static PyObject *py_pjsua_acc_get_info(PyObject *pSelf, PyObject *pArgs)
+{
+ int acc_id;
+ PyObj_pjsua_acc_info * obj;
+ pjsua_acc_info info;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &acc_id)) {
+ return NULL;
+ }
+
+ status = pjsua_acc_get_info(acc_id, &info);
+ if (status == PJ_SUCCESS) {
+ obj = (PyObj_pjsua_acc_info*)
+ PyObj_pjsua_acc_info_new(&PyTyp_pjsua_acc_info, NULL, NULL);
+ PyObj_pjsua_acc_info_import(obj, &info);
+ return (PyObject*)obj;
+ } else {
+ return Py_BuildValue("");
+ }
+}
+
+/*
+ * py_pjsua_enum_accs
+ */
+static PyObject *py_pjsua_enum_accs(PyObject *pSelf, PyObject *pArgs)
+{
+ pj_status_t status;
+ PyObject *list;
+ pjsua_acc_id id[PJSUA_MAX_ACC];
+ unsigned c, i;
+
+ PJ_UNUSED_ARG(pSelf);
+ PJ_UNUSED_ARG(pArgs);
+
+ c = PJ_ARRAY_SIZE(id);
+ status = pjsua_enum_accs(id, &c);
+ if (status != PJ_SUCCESS)
+ c = 0;
+
+ list = PyList_New(c);
+ for (i = 0; i < c; i++) {
+ PyList_SetItem(list, i, Py_BuildValue("i", id[i]));
+ }
+
+ return (PyObject*)list;
+}
+
+/*
+ * py_pjsua_acc_enum_info
+ */
+static PyObject *py_pjsua_acc_enum_info(PyObject *pSelf, PyObject *pArgs)
+{
+ pj_status_t status;
+ PyObject *list;
+ pjsua_acc_info info[PJSUA_MAX_ACC];
+ unsigned c, i;
+
+ PJ_UNUSED_ARG(pSelf);
+ PJ_UNUSED_ARG(pArgs);
+
+ if (!PyArg_ParseTuple(pArgs, "")) {
+ return NULL;
+ }
+
+ c = PJ_ARRAY_SIZE(info);
+ status = pjsua_acc_enum_info(info, &c);
+ if (status != PJ_SUCCESS)
+ c = 0;
+
+ list = PyList_New(c);
+ for (i = 0; i < c; i++) {
+ PyObj_pjsua_acc_info *obj;
+ obj = (PyObj_pjsua_acc_info *)
+ PyObj_pjsua_acc_info_new(&PyTyp_pjsua_acc_info, NULL, NULL);
+
+ PyObj_pjsua_acc_info_import(obj, &info[i]);
+
+ PyList_SetItem(list, i, (PyObject*)obj);
+ }
+
+ return (PyObject*)list;
+}
+
+/*
+ * py_pjsua_acc_set_transport
+ */
+static PyObject *py_pjsua_acc_set_transport(PyObject *pSelf, PyObject *pArgs)
+{
+ int acc_id, transport_id;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "ii", &acc_id, &transport_id)) {
+ return NULL;
+ }
+
+ status = pjsua_acc_set_transport(acc_id, transport_id);
+
+
+ return Py_BuildValue("i", status);
+}
+
+
+/*
+ * py_pjsua_acc_pres_notify
+ */
+static PyObject *py_pjsua_acc_pres_notify(PyObject *pSelf,
+ PyObject *pArgs)
+{
+ int acc_id, state;
+ PyObject *arg_pres, *arg_msg_data, *arg_reason;
+ void *srv_pres;
+ pjsua_msg_data msg_data;
+ pj_str_t reason;
+ pj_bool_t with_body;
+ pj_pool_t *pool = NULL;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "iOiOO", &acc_id, &arg_pres,
+ &state, &arg_reason, &arg_msg_data))
+ {
+ return NULL;
+ }
+
+ srv_pres = (void*) PyLong_AsLong(arg_pres);
+ with_body = (state != PJSIP_EVSUB_STATE_TERMINATED);
+
+ if (arg_reason && PyString_Check(arg_reason)) {
+ reason = PyString_ToPJ(arg_reason);
+ } else {
+ reason = pj_str("");
+ }
+
+ pjsua_msg_data_init(&msg_data);
+ if (arg_msg_data && arg_msg_data != Py_None) {
+ PyObj_pjsua_msg_data *omd = (PyObj_pjsua_msg_data *)arg_msg_data;
+ msg_data.content_type = PyString_ToPJ(omd->content_type);
+ msg_data.msg_body = PyString_ToPJ(omd->msg_body);
+ pool = pjsua_pool_create("pytmp", POOL_SIZE, POOL_SIZE);
+ translate_hdr(pool, &msg_data.hdr_list, omd->hdr_list);
+ }
+
+ status = pjsua_pres_notify(acc_id, (pjsua_srv_pres*)srv_pres,
+ (pjsip_evsub_state)state, NULL,
+ &reason, with_body, &msg_data);
+
+ if (pool) {
+ pj_pool_release(pool);
+ }
+
+ return Py_BuildValue("i", status);
+}
+
+static char pjsua_acc_config_default_doc[] =
+ "_pjsua.Acc_Config _pjsua.acc_config_default () "
+ "Call this function to initialize account config with default values.";
+static char pjsua_acc_get_count_doc[] =
+ "int _pjsua.acc_get_count () "
+ "Get number of current accounts.";
+static char pjsua_acc_is_valid_doc[] =
+ "int _pjsua.acc_is_valid (int acc_id) "
+ "Check if the specified account ID is valid.";
+static char pjsua_acc_set_default_doc[] =
+ "int _pjsua.acc_set_default (int acc_id) "
+ "Set default account to be used when incoming "
+ "and outgoing requests doesn't match any accounts.";
+static char pjsua_acc_get_default_doc[] =
+ "int _pjsua.acc_get_default () "
+ "Get default account.";
+static char pjsua_acc_add_doc[] =
+ "int, int _pjsua.acc_add (_pjsua.Acc_Config cfg, "
+ "int is_default) "
+ "Add a new account to pjsua. PJSUA must have been initialized "
+ "(with pjsua_init()) before calling this function.";
+static char pjsua_acc_add_local_doc[] =
+ "int,int _pjsua.acc_add_local (int tid, "
+ "int is_default) "
+ "Add a local account. A local account is used to identify "
+ "local endpoint instead of a specific user, and for this reason, "
+ "a transport ID is needed to obtain the local address information.";
+static char pjsua_acc_del_doc[] =
+ "int _pjsua.acc_del (int acc_id) "
+ "Delete account.";
+static char pjsua_acc_modify_doc[] =
+ "int _pjsua.acc_modify (int acc_id, _pjsua.Acc_Config cfg) "
+ "Modify account information.";
+static char pjsua_acc_set_online_status_doc[] =
+ "int _pjsua.acc_set_online_status2(int acc_id, int is_online) "
+ "Modify account's presence status to be advertised "
+ "to remote/presence subscribers.";
+static char pjsua_acc_set_online_status2_doc[] =
+ "int _pjsua.acc_set_online_status (int acc_id, int is_online, "
+ "int activity_id, string activity_text) "
+ "Modify account's presence status to be advertised "
+ "to remote/presence subscribers.";
+static char pjsua_acc_set_registration_doc[] =
+ "int _pjsua.acc_set_registration (int acc_id, int renew) "
+ "Update registration or perform unregistration.";
+static char pjsua_acc_get_info_doc[] =
+ "_pjsua.Acc_Info _pjsua.acc_get_info (int acc_id) "
+ "Get account information.";
+static char pjsua_enum_accs_doc[] =
+ "int[] _pjsua.enum_accs () "
+ "Enum accounts all account ids.";
+static char pjsua_acc_enum_info_doc[] =
+ "_pjsua.Acc_Info[] _pjsua.acc_enum_info () "
+ "Enum accounts info.";
+
+/* END OF LIB ACCOUNT */
+
+/* LIB BUDDY */
+
+
+
+/*
+ * py_pjsua_buddy_config_default
+ */
+static PyObject *py_pjsua_buddy_config_default(PyObject *pSelf,
+ PyObject *pArgs)
+{
+ PyObj_pjsua_buddy_config *obj;
+ pjsua_buddy_config cfg;
+
+ PJ_UNUSED_ARG(pSelf);
+ PJ_UNUSED_ARG(pArgs);
+
+ pjsua_buddy_config_default(&cfg);
+ obj = (PyObj_pjsua_buddy_config *)
+ PyObj_pjsua_buddy_config_new(&PyTyp_pjsua_buddy_config, NULL, NULL);
+ PyObj_pjsua_buddy_config_import(obj, &cfg);
+
+ return (PyObject *)obj;
+}
+
+/*
+ * py_pjsua_get_buddy_count
+ */
+static PyObject *py_pjsua_get_buddy_count(PyObject *pSelf, PyObject *pArgs)
+{
+ PJ_UNUSED_ARG(pSelf);
+ PJ_UNUSED_ARG(pArgs);
+
+ return Py_BuildValue("i", pjsua_get_buddy_count());
+}
+
+/*
+ * py_pjsua_buddy_is_valid
+ */
+static PyObject *py_pjsua_buddy_is_valid(PyObject *pSelf, PyObject *pArgs)
+{
+ int id;
+ int is_valid;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &id)) {
+ return NULL;
+ }
+ is_valid = pjsua_buddy_is_valid(id);
+
+ return Py_BuildValue("i", is_valid);
+}
+
+/*
+ * py_pjsua_enum_buddies
+ */
+static PyObject *py_pjsua_enum_buddies(PyObject *pSelf, PyObject *pArgs)
+{
+ pj_status_t status;
+ PyObject *list;
+ pjsua_buddy_id id[PJSUA_MAX_BUDDIES];
+ unsigned c, i;
+
+ PJ_UNUSED_ARG(pSelf);
+ PJ_UNUSED_ARG(pArgs);
+
+ c = PJ_ARRAY_SIZE(id);
+ status = pjsua_enum_buddies(id, &c);
+ if (status != PJ_SUCCESS)
+ c = 0;
+
+ list = PyList_New(c);
+ for (i = 0; i < c; i++) {
+ PyList_SetItem(list, i, Py_BuildValue("i", id[i]));
+ }
+
+ return (PyObject*)list;
+}
+
+/*
+ * py_pjsua_buddy_find
+ */
+static PyObject *py_pjsua_buddy_find(PyObject *pSelf, PyObject *pArgs)
+{
+ PyObject *pURI;
+ pj_str_t uri;
+ pjsua_buddy_id buddy_id;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "O", &pURI)) {
+ return NULL;
+ }
+
+ if (!PyString_Check(pURI))
+ return Py_BuildValue("i", PJSUA_INVALID_ID);
+
+ uri = PyString_ToPJ(pURI);
+ buddy_id = pjsua_buddy_find(&uri);
+
+ return Py_BuildValue("i", buddy_id);
+}
+
+/*
+ * py_pjsua_buddy_get_info
+ */
+static PyObject *py_pjsua_buddy_get_info(PyObject *pSelf, PyObject *pArgs)
+{
+ int buddy_id;
+ pjsua_buddy_info info;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &buddy_id)) {
+ return NULL;
+ }
+
+ status = pjsua_buddy_get_info(buddy_id, &info);
+ if (status == PJ_SUCCESS) {
+ PyObj_pjsua_buddy_info *obj;
+
+ obj = (PyObj_pjsua_buddy_info *)
+ PyObj_pjsua_buddy_config_new(&PyTyp_pjsua_buddy_info,
+ NULL, NULL);
+ PyObj_pjsua_buddy_info_import(obj, &info);
+ return (PyObject*)obj;
+ } else {
+ return Py_BuildValue("");
+ }
+}
+
+/*
+ * py_pjsua_buddy_add
+ */
+static PyObject *py_pjsua_buddy_add(PyObject *pSelf, PyObject *pArgs)
+{
+ PyObject *pCfg;
+ int buddy_id;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "O", &pCfg)) {
+ return NULL;
+ }
+
+ if (pCfg != Py_None) {
+ pjsua_buddy_config cfg;
+ PyObj_pjsua_buddy_config *bc;
+
+ bc = (PyObj_pjsua_buddy_config *)pCfg;
+
+ pjsua_buddy_config_default(&cfg);
+ PyObj_pjsua_buddy_config_export(&cfg, bc);
+
+ status = pjsua_buddy_add(&cfg, &buddy_id);
+
+ } else {
+ status = PJ_EINVAL;
+ buddy_id = PJSUA_INVALID_ID;
+ }
+ return Py_BuildValue("ii", status, buddy_id);
+}
+
+/*
+ * py_pjsua_buddy_del
+ */
+static PyObject *py_pjsua_buddy_del(PyObject *pSelf, PyObject *pArgs)
+{
+ int buddy_id;
+ int status;
+ PyObject *user_data;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &buddy_id)) {
+ return NULL;
+ }
+
+ user_data = (PyObject*) pjsua_buddy_get_user_data(buddy_id);
+ Py_XDECREF(user_data);
+
+ status = pjsua_buddy_del(buddy_id);
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_buddy_set_user_data
+ */
+static PyObject *py_pjsua_buddy_set_user_data(PyObject *pSelf, PyObject *pArgs)
+{
+ int buddy_id;
+ int status;
+ PyObject *user_data, *old_user_data;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "iO", &buddy_id, &user_data)) {
+ return NULL;
+ }
+
+ if (!pjsua_buddy_is_valid(buddy_id)) {
+ return Py_BuildValue("i", 0);
+ }
+
+ old_user_data = (PyObject*) pjsua_buddy_get_user_data(buddy_id);
+
+ status = pjsua_buddy_set_user_data(buddy_id, (void*)user_data);
+
+ if (status == PJ_SUCCESS) {
+ Py_XINCREF(user_data);
+ Py_XDECREF(old_user_data);
+ }
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_buddy_get_user_data
+ */
+static PyObject *py_pjsua_buddy_get_user_data(PyObject *pSelf, PyObject *pArgs)
+{
+ int buddy_id;
+ PyObject *user_data;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &buddy_id)) {
+ return NULL;
+ }
+
+ user_data = (PyObject*) pjsua_buddy_get_user_data(buddy_id);
+
+ return user_data? Py_BuildValue("O", user_data) : Py_BuildValue("");
+}
+
+/*
+ * py_pjsua_buddy_subscribe_pres
+ */
+static PyObject *py_pjsua_buddy_subscribe_pres(PyObject *pSelf,
+ PyObject *pArgs)
+{
+ int buddy_id;
+ int status;
+ int subscribe;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "ii", &buddy_id, &subscribe)) {
+ return NULL;
+ }
+
+ status = pjsua_buddy_subscribe_pres(buddy_id, subscribe);
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_pres_dump
+ */
+static PyObject *py_pjsua_pres_dump(PyObject *pSelf, PyObject *pArgs)
+{
+ int verbose;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &verbose)) {
+ return NULL;
+ }
+
+ pjsua_pres_dump(verbose);
+
+ return Py_BuildValue("");
+}
+
+/*
+ * py_pjsua_im_send
+ */
+static PyObject *py_pjsua_im_send(PyObject *pSelf, PyObject *pArgs)
+{
+ int status;
+ int acc_id;
+ pj_str_t *mime_type, tmp_mime_type;
+ pj_str_t to, content;
+ PyObject *pTo;
+ PyObject *pMimeType;
+ PyObject *pContent;
+ pjsua_msg_data msg_data;
+ PyObject *pMsgData;
+ int user_data;
+ pj_pool_t *pool = NULL;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "iOOOOi", &acc_id,
+ &pTo, &pMimeType, &pContent, &pMsgData, &user_data))
+ {
+ return NULL;
+ }
+
+ if (pMimeType != Py_None) {
+ mime_type = &tmp_mime_type;
+ tmp_mime_type = PyString_ToPJ(pMimeType);
+ } else {
+ mime_type = NULL;
+ }
+
+ to = PyString_ToPJ(pTo);
+ content = PyString_ToPJ(pContent);
+
+ pjsua_msg_data_init(&msg_data);
+
+ if (pMsgData != Py_None) {
+ PyObj_pjsua_msg_data *omd;
+
+ omd = (PyObj_pjsua_msg_data *)pMsgData;
+ msg_data.content_type = PyString_ToPJ(omd->content_type);
+ msg_data.msg_body = PyString_ToPJ(omd->msg_body);
+ pool = pjsua_pool_create("pytmp", POOL_SIZE, POOL_SIZE);
+ translate_hdr(pool, &msg_data.hdr_list, omd->hdr_list);
+ }
+
+ status = pjsua_im_send(acc_id, &to, mime_type, &content,
+ &msg_data, (void*)(long)user_data);
+ if (pool)
+ pj_pool_release(pool);
+
+ return Py_BuildValue("i",status);
+}
+
+/*
+ * py_pjsua_im_typing
+ */
+static PyObject *py_pjsua_im_typing(PyObject *pSelf, PyObject *pArgs)
+{
+ int status;
+ int acc_id;
+ pj_str_t to;
+ PyObject *pTo;
+ int is_typing;
+ pjsua_msg_data msg_data;
+ PyObject *pMsgData;
+ pj_pool_t *pool = NULL;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "iOiO", &acc_id, &pTo, &is_typing,
+ &pMsgData))
+ {
+ return NULL;
+ }
+
+ to = PyString_ToPJ(pTo);
+
+ pjsua_msg_data_init(&msg_data);
+
+ if (pMsgData != Py_None) {
+ PyObj_pjsua_msg_data *omd;
+
+ omd = (PyObj_pjsua_msg_data *)pMsgData;
+ msg_data.content_type = PyString_ToPJ(omd->content_type);
+ msg_data.msg_body = PyString_ToPJ(omd->msg_body);
+ pool = pjsua_pool_create("pytmp", POOL_SIZE, POOL_SIZE);
+
+ translate_hdr(pool, &msg_data.hdr_list, omd->hdr_list);
+ }
+
+ status = pjsua_im_typing(acc_id, &to, is_typing, &msg_data);
+
+ if (pool)
+ pj_pool_release(pool);
+
+ return Py_BuildValue("i", status);
+}
+
+static char pjsua_buddy_config_default_doc[] =
+ "_pjsua.Buddy_Config _pjsua.buddy_config_default () "
+ "Set default values to the buddy config.";
+static char pjsua_get_buddy_count_doc[] =
+ "int _pjsua.get_buddy_count () "
+ "Get total number of buddies.";
+static char pjsua_buddy_is_valid_doc[] =
+ "int _pjsua.buddy_is_valid (int buddy_id) "
+ "Check if buddy ID is valid.";
+static char pjsua_enum_buddies_doc[] =
+ "int[] _pjsua.enum_buddies () "
+ "Enum buddy IDs.";
+static char pjsua_buddy_get_info_doc[] =
+ "_pjsua.Buddy_Info _pjsua.buddy_get_info (int buddy_id) "
+ "Get detailed buddy info.";
+static char pjsua_buddy_add_doc[] =
+ "int,int _pjsua.buddy_add (_pjsua.Buddy_Config cfg) "
+ "Add new buddy.";
+static char pjsua_buddy_del_doc[] =
+ "int _pjsua.buddy_del (int buddy_id) "
+ "Delete buddy.";
+static char pjsua_buddy_subscribe_pres_doc[] =
+ "int _pjsua.buddy_subscribe_pres (int buddy_id, int subscribe) "
+ "Enable/disable buddy's presence monitoring.";
+static char pjsua_pres_dump_doc[] =
+ "void _pjsua.pres_dump (int verbose) "
+ "Dump presence subscriptions to log file.";
+static char pjsua_im_send_doc[] =
+ "int _pjsua.im_send (int acc_id, string to, string mime_type, "
+ "string content, _pjsua.Msg_Data msg_data, int user_data) "
+ "Send instant messaging outside dialog, using the specified account "
+ "for route set and authentication.";
+static char pjsua_im_typing_doc[] =
+ "int _pjsua.im_typing (int acc_id, string to, int is_typing, "
+ "_pjsua.Msg_Data msg_data) "
+ "Send typing indication outside dialog.";
+
+/* END OF LIB BUDDY */
+
+/* LIB MEDIA */
+
+
+/*
+ * py_pjsua_conf_get_max_ports
+ */
+static PyObject *py_pjsua_conf_get_max_ports(PyObject *pSelf, PyObject *pArgs)
+{
+ PJ_UNUSED_ARG(pSelf);
+ PJ_UNUSED_ARG(pArgs);
+
+ return Py_BuildValue("i", pjsua_conf_get_max_ports());
+}
+
+/*
+ * py_pjsua_conf_get_active_ports
+ */
+static PyObject *py_pjsua_conf_get_active_ports(PyObject *pSelf,
+ PyObject *pArgs)
+{
+ PJ_UNUSED_ARG(pSelf);
+ PJ_UNUSED_ARG(pArgs);
+
+ return Py_BuildValue("i", pjsua_conf_get_active_ports());
+}
+
+/*
+ * py_pjsua_enum_conf_ports
+ */
+static PyObject *py_pjsua_enum_conf_ports(PyObject *pSelf, PyObject *pArgs)
+{
+ pj_status_t status;
+ PyObject *list;
+ pjsua_conf_port_id id[PJSUA_MAX_CONF_PORTS];
+ unsigned c, i;
+
+ PJ_UNUSED_ARG(pSelf);
+ PJ_UNUSED_ARG(pArgs);
+
+ c = PJ_ARRAY_SIZE(id);
+ status = pjsua_enum_conf_ports(id, &c);
+ if (status != PJ_SUCCESS)
+ c = 0;
+
+ list = PyList_New(c);
+ for (i = 0; i < c; i++) {
+ PyList_SetItem(list, i, Py_BuildValue("i", id[i]));
+ }
+
+ return (PyObject*)list;
+}
+
+/*
+ * py_pjsua_conf_get_port_info
+ */
+static PyObject *py_pjsua_conf_get_port_info(PyObject *pSelf, PyObject *pArgs)
+{
+ int id;
+ PyObj_pjsua_conf_port_info *ret;
+ pjsua_conf_port_info info;
+ int status;
+ unsigned i;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &id)) {
+ return NULL;
+ }
+
+ status = pjsua_conf_get_port_info(id, &info);
+ ret = (PyObj_pjsua_conf_port_info *)
+ conf_port_info_new(&PyTyp_pjsua_conf_port_info, NULL, NULL);
+ ret->bits_per_sample = info.bits_per_sample;
+ ret->channel_count = info.channel_count;
+ ret->clock_rate = info.clock_rate;
+ ret->name = PyString_FromPJ(&info.name);
+ ret->samples_per_frame = info.samples_per_frame;
+ ret->slot_id = info.slot_id;
+ Py_XDECREF(ret->listeners);
+ ret->listeners = PyList_New(info.listener_cnt);
+ for (i = 0; i < info.listener_cnt; i++) {
+ PyObject *item = Py_BuildValue("i",info.listeners[i]);
+ PyList_SetItem(ret->listeners, i, item);
+ }
+ return (PyObject*)ret;
+}
+
+/*
+ * py_pjsua_conf_remove_port
+ */
+static PyObject *py_pjsua_conf_remove_port(PyObject *pSelf, PyObject *pArgs)
+{
+ int id;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &id)) {
+ return NULL;
+ }
+
+ status = pjsua_conf_remove_port(id);
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_conf_connect
+ */
+static PyObject *py_pjsua_conf_connect(PyObject *pSelf, PyObject *pArgs)
+{
+ int source, sink;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "ii", &source, &sink)) {
+ return NULL;
+ }
+
+ status = pjsua_conf_connect(source, sink);
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_conf_disconnect
+ */
+static PyObject *py_pjsua_conf_disconnect(PyObject *pSelf, PyObject *pArgs)
+{
+ int source, sink;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "ii", &source, &sink)) {
+ return NULL;
+ }
+
+ status = pjsua_conf_disconnect(source, sink);
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_conf_set_tx_level
+ */
+static PyObject *py_pjsua_conf_set_tx_level(PyObject *pSelf, PyObject *pArgs)
+{
+ int slot;
+ float level;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "if", &slot, &level)) {
+ return NULL;
+ }
+
+ status = pjsua_conf_adjust_tx_level(slot, level);
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_conf_set_rx_level
+ */
+static PyObject *py_pjsua_conf_set_rx_level(PyObject *pSelf, PyObject *pArgs)
+{
+ int slot;
+ float level;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "if", &slot, &level)) {
+ return NULL;
+ }
+
+ status = pjsua_conf_adjust_rx_level(slot, level);
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_conf_get_signal_level
+ */
+static PyObject *py_pjsua_conf_get_signal_level(PyObject *pSelf,
+ PyObject *pArgs)
+{
+ int slot;
+ unsigned tx_level, rx_level;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &slot)) {
+ return NULL;
+ }
+
+ status = pjsua_conf_get_signal_level(slot, &tx_level, &rx_level);
+
+ return Py_BuildValue("iff", status, (float)(tx_level/255.0),
+ (float)(rx_level/255.0));
+}
+
+/*
+ * py_pjsua_player_create
+ */
+static PyObject *py_pjsua_player_create(PyObject *pSelf, PyObject *pArgs)
+{
+ int id;
+ int options;
+ PyObject *pFilename;
+ pj_str_t filename;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "Oi", &pFilename, &options)) {
+ return NULL;
+ }
+
+ filename = PyString_ToPJ(pFilename);
+ status = pjsua_player_create(&filename, options, &id);
+
+ return Py_BuildValue("ii", status, id);
+}
+
+/*
+ * py_pjsua_playlist_create
+ */
+static PyObject *py_pjsua_playlist_create(PyObject *pSelf, PyObject *pArgs)
+{
+ int id;
+ int options;
+ PyObject *pLabel, *pFileList;
+ pj_str_t label;
+ int count;
+ pj_str_t files[64];
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "OOi", &pLabel, &pFileList, &options)) {
+ return NULL;
+ }
+
+ label = PyString_ToPJ(pLabel);
+ if (!PyList_Check(pFileList))
+ return Py_BuildValue("ii", PJ_EINVAL, PJSUA_INVALID_ID);
+
+ count = 0;
+ for (count=0; count<PyList_Size(pFileList) &&
+ count<PJ_ARRAY_SIZE(files); ++count)
+ {
+ files[count] = PyString_ToPJ(PyList_GetItem(pFileList, count));
+ }
+
+ status = pjsua_playlist_create(files, count, &label, options, &id);
+
+ return Py_BuildValue("ii", status, id);
+}
+
+/*
+ * py_pjsua_player_get_conf_port
+ */
+static PyObject *py_pjsua_player_get_conf_port(PyObject *pSelf,
+ PyObject *pArgs)
+{
+
+ int id, port_id;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &id)) {
+ return NULL;
+ }
+
+ port_id = pjsua_player_get_conf_port(id);
+
+ return Py_BuildValue("i", port_id);
+}
+
+/*
+ * py_pjsua_player_set_pos
+ */
+static PyObject *py_pjsua_player_set_pos(PyObject *pSelf, PyObject *pArgs)
+{
+ int id;
+ int samples;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "ii", &id, &samples)) {
+ return NULL;
+ }
+
+ if (samples < 0)
+ samples = 0;
+
+ status = pjsua_player_set_pos(id, samples);
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_player_destroy
+ */
+static PyObject *py_pjsua_player_destroy(PyObject *pSelf, PyObject *pArgs)
+{
+ int id;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &id)) {
+ return NULL;
+ }
+
+ status = pjsua_player_destroy(id);
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_recorder_create
+ */
+static PyObject *py_pjsua_recorder_create(PyObject *pSelf, PyObject *pArgs)
+{
+ int id, options;
+ int max_size;
+ PyObject *pFilename, *pEncParam;
+ pj_str_t filename;
+ int enc_type;
+
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "OiOii", &pFilename, &enc_type, &pEncParam,
+ &max_size, &options))
+ {
+ return NULL;
+ }
+
+ filename = PyString_ToPJ(pFilename);
+
+ status = pjsua_recorder_create(&filename, enc_type, NULL, max_size,
+ options, &id);
+
+ return Py_BuildValue("ii", status, id);
+}
+
+/*
+ * py_pjsua_recorder_get_conf_port
+ */
+static PyObject *py_pjsua_recorder_get_conf_port(PyObject *pSelf,
+ PyObject *pArgs)
+{
+
+ int id, port_id;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &id)) {
+ return NULL;
+ }
+
+ port_id = pjsua_recorder_get_conf_port(id);
+
+ return Py_BuildValue("i", port_id);
+}
+
+/*
+ * py_pjsua_recorder_destroy
+ */
+static PyObject *py_pjsua_recorder_destroy(PyObject *pSelf, PyObject *pArgs)
+{
+ int id;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &id)) {
+ return NULL;
+ }
+
+ status = pjsua_recorder_destroy(id);
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_enum_snd_devs
+ */
+static PyObject *py_pjsua_enum_snd_devs(PyObject *pSelf, PyObject *pArgs)
+{
+ pj_status_t status;
+ PyObject *ret;
+ pjmedia_snd_dev_info info[SND_DEV_NUM];
+ unsigned c, i;
+
+ PJ_UNUSED_ARG(pSelf);
+ PJ_UNUSED_ARG(pArgs);
+
+ c = PJ_ARRAY_SIZE(info);
+ status = pjsua_enum_snd_devs(info, &c);
+ if (status != PJ_SUCCESS)
+ c = 0;
+
+ ret = PyList_New(c);
+ for (i = 0; i < c; i++) {
+ PyObj_pjmedia_snd_dev_info * obj;
+
+ obj = (PyObj_pjmedia_snd_dev_info *)
+ pjmedia_snd_dev_info_new(&PyTyp_pjmedia_snd_dev_info,
+ NULL, NULL);
+ obj->default_samples_per_sec = info[i].default_samples_per_sec;
+ obj->input_count = info[i].input_count;
+ obj->output_count = info[i].output_count;
+ obj->name = PyString_FromString(info[i].name);
+
+ PyList_SetItem(ret, i, (PyObject *)obj);
+ }
+
+ return (PyObject*)ret;
+}
+
+/*
+ * py_pjsua_get_snd_dev
+ */
+static PyObject *py_pjsua_get_snd_dev(PyObject *pSelf, PyObject *pArgs)
+{
+ int capture_dev, playback_dev;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+ PJ_UNUSED_ARG(pArgs);
+
+ status = pjsua_get_snd_dev(&capture_dev, &playback_dev);
+
+ return Py_BuildValue("ii", capture_dev, playback_dev);
+}
+
+/*
+ * py_pjsua_set_snd_dev
+ */
+static PyObject *py_pjsua_set_snd_dev(PyObject *pSelf, PyObject *pArgs)
+{
+ int capture_dev, playback_dev;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "ii", &capture_dev, &playback_dev)) {
+ return NULL;
+ }
+
+ status = pjsua_set_snd_dev(capture_dev, playback_dev);
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_set_null_snd_dev
+ */
+static PyObject *py_pjsua_set_null_snd_dev(PyObject *pSelf, PyObject *pArgs)
+{
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+ PJ_UNUSED_ARG(pArgs);
+
+ status = pjsua_set_null_snd_dev();
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_set_ec
+ */
+static PyObject *py_pjsua_set_ec(PyObject *pSelf, PyObject *pArgs)
+{
+ int options;
+ int tail_ms;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "ii", &tail_ms, &options)) {
+ return NULL;
+ }
+
+ status = pjsua_set_ec(tail_ms, options);
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_get_ec_tail
+ */
+static PyObject *py_pjsua_get_ec_tail(PyObject *pSelf, PyObject *pArgs)
+{
+ int status;
+ unsigned tail_ms;
+
+ PJ_UNUSED_ARG(pSelf);
+ PJ_UNUSED_ARG(pArgs);
+
+ status = pjsua_get_ec_tail(&tail_ms);
+ if (status != PJ_SUCCESS)
+ tail_ms = 0;
+
+ return Py_BuildValue("i", tail_ms);
+}
+
+/*
+ * py_pjsua_enum_codecs
+ */
+static PyObject *py_pjsua_enum_codecs(PyObject *pSelf, PyObject *pArgs)
+{
+ pj_status_t status;
+ PyObject *ret;
+ pjsua_codec_info info[PJMEDIA_CODEC_MGR_MAX_CODECS];
+ unsigned c, i;
+
+ PJ_UNUSED_ARG(pSelf);
+ PJ_UNUSED_ARG(pArgs);
+
+ c = PJ_ARRAY_SIZE(info);
+ status = pjsua_enum_codecs(info, &c);
+ if (status != PJ_SUCCESS)
+ c = 0;
+
+ ret = PyList_New(c);
+ for (i = 0; i < c; i++) {
+ PyObj_pjsua_codec_info * obj;
+ obj = (PyObj_pjsua_codec_info *)
+ codec_info_new(&PyTyp_pjsua_codec_info, NULL, NULL);
+ obj->codec_id = PyString_FromPJ(&info[i].codec_id);
+ obj->priority = info[i].priority;
+
+ PyList_SetItem(ret, i, (PyObject *)obj);
+ }
+
+ return (PyObject*)ret;
+}
+
+/*
+ * py_pjsua_codec_set_priority
+ */
+static PyObject *py_pjsua_codec_set_priority(PyObject *pSelf, PyObject *pArgs)
+{
+ int status;
+ PyObject *pCodecId;
+ pj_str_t codec_id;
+ int priority;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "Oi", &pCodecId, &priority)) {
+ return NULL;
+ }
+
+ codec_id = PyString_ToPJ(pCodecId);
+ if (priority < 0)
+ priority = 0;
+ if (priority > 255)
+ priority = 255;
+
+ status = pjsua_codec_set_priority(&codec_id, (pj_uint8_t)priority);
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_codec_get_param
+ */
+static PyObject *py_pjsua_codec_get_param(PyObject *pSelf, PyObject *pArgs)
+{
+ int status;
+ PyObject *pCodecId;
+ pj_str_t codec_id;
+ pjmedia_codec_param param;
+ PyObj_pjmedia_codec_param *ret;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "O", &pCodecId)) {
+ return NULL;
+ }
+
+ codec_id = PyString_ToPJ(pCodecId);
+
+ status = pjsua_codec_get_param(&codec_id, &param);
+ if (status != PJ_SUCCESS)
+ return Py_BuildValue("");
+
+ ret = (PyObj_pjmedia_codec_param *)
+ pjmedia_codec_param_new(&PyTyp_pjmedia_codec_param, NULL, NULL);
+
+ ret->info->avg_bps = param.info.avg_bps;
+ ret->info->channel_cnt = param.info.channel_cnt;
+ ret->info->clock_rate = param.info.clock_rate;
+ ret->info->frm_ptime = param.info.frm_ptime;
+ ret->info->pcm_bits_per_sample = param.info.pcm_bits_per_sample;
+ ret->info->pt = param.info.pt;
+ ret->setting->cng = param.setting.cng;
+ //ret->setting->dec_fmtp_mode = param.setting.dec_fmtp_mode;
+ //ret->setting->enc_fmtp_mode = param.setting.enc_fmtp_mode;
+ ret->setting->frm_per_pkt = param.setting.frm_per_pkt;
+ ret->setting->penh = param.setting.penh;
+ ret->setting->plc = param.setting.plc;
+ ret->setting->vad = param.setting.vad;
+
+ return (PyObject*)ret;
+}
+
+
+/*
+ * py_pjsua_codec_set_param
+ */
+static PyObject *py_pjsua_codec_set_param(PyObject *pSelf, PyObject *pArgs)
+{
+ int status;
+ PyObject *pCodecId, *pCodecParam;
+ pj_str_t codec_id;
+ pjmedia_codec_param param;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "OO", &pCodecId, &pCodecParam)) {
+ return NULL;
+ }
+
+ codec_id = PyString_ToPJ(pCodecId);
+
+ if (pCodecParam != Py_None) {
+ PyObj_pjmedia_codec_param *obj;
+
+ obj = (PyObj_pjmedia_codec_param *)pCodecParam;
+
+ param.info.avg_bps = obj->info->avg_bps;
+ param.info.channel_cnt = obj->info->channel_cnt;
+ param.info.clock_rate = obj->info->clock_rate;
+ param.info.frm_ptime = obj->info->frm_ptime;
+ param.info.pcm_bits_per_sample = obj->info->pcm_bits_per_sample;
+ param.info.pt = obj->info->pt;
+ param.setting.cng = obj->setting->cng;
+ //param.setting.dec_fmtp_mode = obj->setting->dec_fmtp_mode;
+ //param.setting.enc_fmtp_mode = obj->setting->enc_fmtp_mode;
+ param.setting.frm_per_pkt = obj->setting->frm_per_pkt;
+ param.setting.penh = obj->setting->penh;
+ param.setting.plc = obj->setting->plc;
+ param.setting.vad = obj->setting->vad;
+ status = pjsua_codec_set_param(&codec_id, &param);
+
+ } else {
+ status = pjsua_codec_set_param(&codec_id, NULL);
+ }
+
+ return Py_BuildValue("i", status);
+}
+
+static char pjsua_conf_get_max_ports_doc[] =
+ "int _pjsua.conf_get_max_ports () "
+ "Get maxinum number of conference ports.";
+static char pjsua_conf_get_active_ports_doc[] =
+ "int _pjsua.conf_get_active_ports () "
+ "Get current number of active ports in the bridge.";
+static char pjsua_enum_conf_ports_doc[] =
+ "int[] _pjsua.enum_conf_ports () "
+ "Enumerate all conference ports.";
+static char pjsua_conf_get_port_info_doc[] =
+ "_pjsua.Conf_Port_Info _pjsua.conf_get_port_info (int id) "
+ "Get information about the specified conference port";
+static char pjsua_conf_remove_port_doc[] =
+ "int _pjsua.conf_remove_port (int id) "
+ "Remove arbitrary slot from the conference bridge. "
+ "Application should only call this function "
+ "if it registered the port manually.";
+static char pjsua_conf_connect_doc[] =
+ "int _pjsua.conf_connect (int source, int sink) "
+ "Establish unidirectional media flow from souce to sink. "
+ "One source may transmit to multiple destinations/sink. "
+ "And if multiple sources are transmitting to the same sink, "
+ "the media will be mixed together. Source and sink may refer "
+ "to the same ID, effectively looping the media. "
+ "If bidirectional media flow is desired, application "
+ "needs to call this function twice, with the second "
+ "one having the arguments reversed.";
+static char pjsua_conf_disconnect_doc[] =
+ "int _pjsua.conf_disconnect (int source, int sink) "
+ "Disconnect media flow from the source to destination port.";
+static char pjsua_player_create_doc[] =
+ "int, int _pjsua.player_create (string filename, int options) "
+ "Create a file player, and automatically connect "
+ "this player to the conference bridge.";
+static char pjsua_player_get_conf_port_doc[] =
+ "int _pjsua.player_get_conf_port (int) "
+ "Get conference port ID associated with player.";
+static char pjsua_player_set_pos_doc[] =
+ "int _pjsua.player_set_pos (int id, int samples) "
+ "Set playback position.";
+static char pjsua_player_destroy_doc[] =
+ "int _pjsua.player_destroy (int id) "
+ "Close the file, remove the player from the bridge, "
+ "and free resources associated with the file player.";
+static char pjsua_recorder_create_doc[] =
+ "int, int _pjsua.recorder_create (string filename, "
+ "int enc_type, int enc_param, int max_size, int options) "
+ "Create a file recorder, and automatically connect this recorder "
+ "to the conference bridge. The recorder currently supports recording "
+ "WAV file, and on Windows, MP3 file. The type of the recorder to use "
+ "is determined by the extension of the file (e.g. '.wav' or '.mp3').";
+static char pjsua_recorder_get_conf_port_doc[] =
+ "int _pjsua.recorder_get_conf_port (int id) "
+ "Get conference port associated with recorder.";
+static char pjsua_recorder_destroy_doc[] =
+ "int _pjsua.recorder_destroy (int id) "
+ "Destroy recorder (this will complete recording).";
+static char pjsua_enum_snd_devs_doc[] =
+ "_pjsua.PJMedia_Snd_Dev_Info[] _pjsua.enum_snd_devs (int count) "
+ "Enum sound devices.";
+static char pjsua_get_snd_dev_doc[] =
+ "int, int _pjsua.get_snd_dev () "
+ "Get currently active sound devices. "
+ "If sound devices has not been created "
+ "(for example when pjsua_start() is not called), "
+ "it is possible that the function returns "
+ "PJ_SUCCESS with -1 as device IDs.";
+static char pjsua_set_snd_dev_doc[] =
+ "int _pjsua.set_snd_dev (int capture_dev, int playback_dev) "
+ "Select or change sound device. Application may call this function "
+ "at any time to replace current sound device.";
+static char pjsua_set_null_snd_dev_doc[] =
+ "int _pjsua.set_null_snd_dev () "
+ "Set pjsua to use null sound device. The null sound device only "
+ "provides the timing needed by the conference bridge, and will not "
+ "interract with any hardware.";
+static char pjsua_set_ec_doc[] =
+ "int _pjsua.set_ec (int tail_ms, int options) "
+ "Configure the echo canceller tail length of the sound port.";
+static char pjsua_get_ec_tail_doc[] =
+ "int _pjsua.get_ec_tail () "
+ "Get current echo canceller tail length.";
+static char pjsua_enum_codecs_doc[] =
+ "_pjsua.Codec_Info[] _pjsua.enum_codecs () "
+ "Enum all supported codecs in the system.";
+static char pjsua_codec_set_priority_doc[] =
+ "int _pjsua.codec_set_priority (string id, int priority) "
+ "Change codec priority.";
+static char pjsua_codec_get_param_doc[] =
+ "_pjsua.PJMedia_Codec_Param _pjsua.codec_get_param (string id) "
+ "Get codec parameters";
+static char pjsua_codec_set_param_doc[] =
+ "int _pjsua.codec_set_param (string id, "
+ "_pjsua.PJMedia_Codec_Param param) "
+ "Set codec parameters.";
+
+/* END OF LIB MEDIA */
+
+/* LIB CALL */
+
+/*
+ * py_pjsua_call_get_max_count
+ */
+static PyObject *py_pjsua_call_get_max_count(PyObject *pSelf, PyObject *pArgs)
+{
+ int count;
+
+ PJ_UNUSED_ARG(pSelf);
+ PJ_UNUSED_ARG(pArgs);
+
+ count = pjsua_call_get_max_count();
+
+ return Py_BuildValue("i", count);
+}
+
+/*
+ * py_pjsua_call_get_count
+ */
+static PyObject *py_pjsua_call_get_count(PyObject *pSelf, PyObject *pArgs)
+{
+ int count;
+
+ PJ_UNUSED_ARG(pSelf);
+ PJ_UNUSED_ARG(pArgs);
+
+ count = pjsua_call_get_count();
+
+ return Py_BuildValue("i", count);
+}
+
+/*
+ * py_pjsua_enum_calls
+ */
+static PyObject *py_pjsua_enum_calls(PyObject *pSelf, PyObject *pArgs)
+{
+ pj_status_t status;
+ PyObject *ret;
+ pjsua_transport_id id[PJSUA_MAX_CALLS];
+ unsigned c, i;
+
+ PJ_UNUSED_ARG(pSelf);
+ PJ_UNUSED_ARG(pArgs);
+
+ c = PJ_ARRAY_SIZE(id);
+ status = pjsua_enum_calls(id, &c);
+ if (status != PJ_SUCCESS)
+ c = 0;
+
+ ret = PyList_New(c);
+ for (i = 0; i < c; i++) {
+ PyList_SetItem(ret, i, Py_BuildValue("i", id[i]));
+ }
+
+ return (PyObject*)ret;
+}
+
+/*
+ * py_pjsua_call_make_call
+ */
+static PyObject *py_pjsua_call_make_call(PyObject *pSelf, PyObject *pArgs)
+{
+ int status;
+ int acc_id;
+ pj_str_t dst_uri;
+ PyObject *pDstUri, *pMsgData, *pUserData;
+ unsigned options;
+ pjsua_msg_data msg_data;
+ int call_id;
+ pj_pool_t *pool = NULL;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "iOIOO", &acc_id, &pDstUri, &options,
+ &pUserData, &pMsgData))
+ {
+ return NULL;
+ }
+
+ dst_uri = PyString_ToPJ(pDstUri);
+ pjsua_msg_data_init(&msg_data);
+
+ if (pMsgData != Py_None) {
+ PyObj_pjsua_msg_data * omd;
+
+ omd = (PyObj_pjsua_msg_data *)pMsgData;
+
+ msg_data.content_type = PyString_ToPJ(omd->content_type);
+ msg_data.msg_body = PyString_ToPJ(omd->msg_body);
+ pool = pjsua_pool_create("pytmp", POOL_SIZE, POOL_SIZE);
+ translate_hdr(pool, &msg_data.hdr_list, omd->hdr_list);
+ }
+
+ Py_XINCREF(pUserData);
+
+ status = pjsua_call_make_call(acc_id, &dst_uri,
+ options, (void*)pUserData,
+ &msg_data, &call_id);
+ if (pool != NULL)
+ pj_pool_release(pool);
+
+ if (status != PJ_SUCCESS) {
+ Py_XDECREF(pUserData);
+ }
+
+ return Py_BuildValue("ii", status, call_id);
+}
+
+/*
+ * py_pjsua_call_is_active
+ */
+static PyObject *py_pjsua_call_is_active(PyObject *pSelf, PyObject *pArgs)
+{
+ int call_id;
+ int is_active;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &call_id)) {
+ return NULL;
+ }
+
+ is_active = pjsua_call_is_active(call_id);
+
+ return Py_BuildValue("i", is_active);
+}
+
+/*
+ * py_pjsua_call_has_media
+ */
+static PyObject *py_pjsua_call_has_media(PyObject *pSelf, PyObject *pArgs)
+{
+ int call_id;
+ int has_media;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &call_id)) {
+ return NULL;
+ }
+
+ has_media = pjsua_call_has_media(call_id);
+
+ return Py_BuildValue("i", has_media);
+}
+
+/*
+ * py_pjsua_call_get_conf_port
+ */
+static PyObject* py_pjsua_call_get_conf_port(PyObject *pSelf, PyObject *pArgs)
+{
+ int call_id;
+ int port_id;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &call_id)) {
+ return NULL;
+ }
+
+ port_id = pjsua_call_get_conf_port(call_id);
+
+ return Py_BuildValue("i", port_id);
+}
+
+/*
+ * py_pjsua_call_get_info
+ */
+static PyObject* py_pjsua_call_get_info(PyObject *pSelf, PyObject *pArgs)
+{
+ int call_id;
+ int status;
+ PyObj_pjsua_call_info *ret;
+ pjsua_call_info info;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &call_id)) {
+ return NULL;
+ }
+
+ status = pjsua_call_get_info(call_id, &info);
+ if (status != PJ_SUCCESS)
+ return Py_BuildValue("");
+
+ ret = (PyObj_pjsua_call_info *)call_info_new(&PyTyp_pjsua_call_info,
+ NULL, NULL);
+ ret->acc_id = info.acc_id;
+ Py_XDECREF(ret->call_id);
+ ret->call_id = PyString_FromPJ(&info.call_id);
+ ret->conf_slot = info.conf_slot;
+ ret->connect_duration = info.connect_duration.sec * 1000 +
+ info.connect_duration.msec;
+ ret->total_duration = info.total_duration.sec * 1000 +
+ info.total_duration.msec;
+ ret->id = info.id;
+ ret->last_status = info.last_status;
+ Py_XDECREF(ret->last_status_text);
+ ret->last_status_text = PyString_FromPJ(&info.last_status_text);
+ Py_XDECREF(ret->local_contact);
+ ret->local_contact = PyString_FromPJ(&info.local_contact);
+ Py_XDECREF(ret->local_info);
+ ret->local_info = PyString_FromPJ(&info.local_info);
+ Py_XDECREF(ret->remote_contact);
+ ret->remote_contact = PyString_FromPJ(&info.remote_contact);
+ Py_XDECREF(ret->remote_info);
+ ret->remote_info = PyString_FromPJ(&info.remote_info);
+ ret->media_dir = info.media_dir;
+ ret->media_status = info.media_status;
+ ret->role = info.role;
+ ret->state = info.state;
+ Py_XDECREF(ret->state_text);
+ ret->state_text = PyString_FromPJ(&info.state_text);
+
+ return (PyObject*)ret;
+}
+
+/*
+ * py_pjsua_call_set_user_data
+ */
+static PyObject *py_pjsua_call_set_user_data(PyObject *pSelf, PyObject *pArgs)
+{
+ int call_id;
+ PyObject *pUserData, *old_user_data;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "iO", &call_id, &pUserData)) {
+ return NULL;
+ }
+
+ old_user_data = (PyObject*) pjsua_call_get_user_data(call_id);
+
+ if (old_user_data == pUserData) {
+ return Py_BuildValue("i", PJ_SUCCESS);
+ }
+
+ Py_XINCREF(pUserData);
+ Py_XDECREF(old_user_data);
+
+ status = pjsua_call_set_user_data(call_id, (void*)pUserData);
+
+ if (status != PJ_SUCCESS) {
+ Py_XDECREF(pUserData);
+ }
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_call_get_user_data
+ */
+static PyObject *py_pjsua_call_get_user_data(PyObject *pSelf, PyObject *pArgs)
+{
+ int call_id;
+ PyObject *user_data;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &call_id)) {
+ return NULL;
+ }
+
+ user_data = (PyObject*)pjsua_call_get_user_data(call_id);
+ return user_data ? Py_BuildValue("O", user_data) : Py_BuildValue("");
+}
+
+/*
+ * py_pjsua_call_answer
+ */
+static PyObject *py_pjsua_call_answer(PyObject *pSelf, PyObject *pArgs)
+{
+ int status;
+ int call_id;
+ pj_str_t * reason, tmp_reason;
+ PyObject *pReason;
+ unsigned code;
+ pjsua_msg_data msg_data;
+ PyObject * omdObj;
+ pj_pool_t * pool = NULL;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "iIOO", &call_id, &code, &pReason, &omdObj)) {
+ return NULL;
+ }
+
+ if (pReason == Py_None) {
+ reason = NULL;
+ } else {
+ reason = &tmp_reason;
+ tmp_reason = PyString_ToPJ(pReason);
+ }
+
+ pjsua_msg_data_init(&msg_data);
+ if (omdObj != Py_None) {
+ PyObj_pjsua_msg_data *omd;
+
+ omd = (PyObj_pjsua_msg_data *)omdObj;
+ msg_data.content_type = PyString_ToPJ(omd->content_type);
+ msg_data.msg_body = PyString_ToPJ(omd->msg_body);
+ pool = pjsua_pool_create("pytmp", POOL_SIZE, POOL_SIZE);
+ translate_hdr(pool, &msg_data.hdr_list, omd->hdr_list);
+ }
+
+ status = pjsua_call_answer(call_id, code, reason, &msg_data);
+
+ if (pool)
+ pj_pool_release(pool);
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_call_hangup
+ */
+static PyObject *py_pjsua_call_hangup(PyObject *pSelf, PyObject *pArgs)
+{
+ int status;
+ int call_id;
+ pj_str_t *reason, tmp_reason;
+ PyObject *pReason;
+ unsigned code;
+ pjsua_msg_data msg_data;
+ PyObject *omdObj;
+ pj_pool_t *pool = NULL;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "iIOO", &call_id, &code, &pReason,
+ &omdObj))
+ {
+ return NULL;
+ }
+
+ if (pReason == Py_None) {
+ reason = NULL;
+ } else {
+ reason = &tmp_reason;
+ tmp_reason = PyString_ToPJ(pReason);
+ }
+
+ pjsua_msg_data_init(&msg_data);
+ if (omdObj != Py_None) {
+ PyObj_pjsua_msg_data *omd;
+
+ omd = (PyObj_pjsua_msg_data *)omdObj;
+ msg_data.content_type = PyString_ToPJ(omd->content_type);
+ msg_data.msg_body = PyString_ToPJ(omd->msg_body);
+ pool = pjsua_pool_create("pytmp", POOL_SIZE, POOL_SIZE);
+ translate_hdr(pool, &msg_data.hdr_list, omd->hdr_list);
+ }
+
+ status = pjsua_call_hangup(call_id, code, reason, &msg_data);
+ if (pool)
+ pj_pool_release(pool);
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_call_set_hold
+ */
+static PyObject *py_pjsua_call_set_hold(PyObject *pSelf, PyObject *pArgs)
+{
+ int status;
+ int call_id;
+ pjsua_msg_data msg_data;
+ PyObject *omdObj;
+ pj_pool_t *pool = NULL;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "iO", &call_id, &omdObj)) {
+ return NULL;
+ }
+
+ pjsua_msg_data_init(&msg_data);
+ if (omdObj != Py_None) {
+ PyObj_pjsua_msg_data *omd;
+
+ omd = (PyObj_pjsua_msg_data *)omdObj;
+ msg_data.content_type = PyString_ToPJ(omd->content_type);
+ msg_data.msg_body = PyString_ToPJ(omd->msg_body);
+ pool = pjsua_pool_create("pytmp", POOL_SIZE, POOL_SIZE);
+ translate_hdr(pool, &msg_data.hdr_list, omd->hdr_list);
+ }
+
+ status = pjsua_call_set_hold(call_id, &msg_data);
+
+ if (pool)
+ pj_pool_release(pool);
+
+ return Py_BuildValue("i",status);
+}
+
+/*
+ * py_pjsua_call_reinvite
+ */
+static PyObject *py_pjsua_call_reinvite(PyObject *pSelf, PyObject *pArgs)
+{
+ int status;
+ int call_id;
+ int unhold;
+ pjsua_msg_data msg_data;
+ PyObject *omdObj;
+ pj_pool_t *pool = NULL;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "iiO", &call_id, &unhold, &omdObj)) {
+ return NULL;
+ }
+
+ pjsua_msg_data_init(&msg_data);
+ if (omdObj != Py_None) {
+ PyObj_pjsua_msg_data *omd;
+
+ omd = (PyObj_pjsua_msg_data *)omdObj;
+ msg_data.content_type = PyString_ToPJ(omd->content_type);
+ msg_data.msg_body = PyString_ToPJ(omd->msg_body);
+ pool = pjsua_pool_create("pytmp", POOL_SIZE, POOL_SIZE);
+ translate_hdr(pool, &msg_data.hdr_list, omd->hdr_list);
+ }
+
+ status = pjsua_call_reinvite(call_id, unhold, &msg_data);
+
+ if (pool)
+ pj_pool_release(pool);
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_call_update
+ */
+static PyObject *py_pjsua_call_update(PyObject *pSelf, PyObject *pArgs)
+{
+ int status;
+ int call_id;
+ int option;
+ pjsua_msg_data msg_data;
+ PyObject *omdObj;
+ pj_pool_t *pool = NULL;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "iiO", &call_id, &option, &omdObj)) {
+ return NULL;
+ }
+
+ pjsua_msg_data_init(&msg_data);
+ if (omdObj != Py_None) {
+ PyObj_pjsua_msg_data *omd;
+
+ omd = (PyObj_pjsua_msg_data *)omdObj;
+ msg_data.content_type = PyString_ToPJ(omd->content_type);
+ msg_data.msg_body = PyString_ToPJ(omd->msg_body);
+ pool = pjsua_pool_create("pytmp", POOL_SIZE, POOL_SIZE);
+ translate_hdr(pool, &msg_data.hdr_list, omd->hdr_list);
+ }
+
+ status = pjsua_call_update(call_id, option, &msg_data);
+
+ if (pool)
+ pj_pool_release(pool);
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_call_send_request
+ */
+static PyObject *py_pjsua_call_send_request(PyObject *pSelf, PyObject *pArgs)
+{
+ int status;
+ int call_id;
+ PyObject *pMethod;
+ pj_str_t method;
+ pjsua_msg_data msg_data;
+ PyObject *omdObj;
+ pj_pool_t *pool = NULL;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "iOO", &call_id, &pMethod, &omdObj)) {
+ return NULL;
+ }
+
+ if (!PyString_Check(pMethod)) {
+ return NULL;
+ }
+
+ method = PyString_ToPJ(pMethod);
+ pjsua_msg_data_init(&msg_data);
+
+ if (omdObj != Py_None) {
+ PyObj_pjsua_msg_data *omd;
+
+ omd = (PyObj_pjsua_msg_data *)omdObj;
+ msg_data.content_type = PyString_ToPJ(omd->content_type);
+ msg_data.msg_body = PyString_ToPJ(omd->msg_body);
+ pool = pjsua_pool_create("pytmp", POOL_SIZE, POOL_SIZE);
+ translate_hdr(pool, &msg_data.hdr_list, omd->hdr_list);
+ }
+
+ status = pjsua_call_send_request(call_id, &method, &msg_data);
+
+ if (pool)
+ pj_pool_release(pool);
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_call_xfer
+ */
+static PyObject *py_pjsua_call_xfer(PyObject *pSelf, PyObject *pArgs)
+{
+ int status;
+ int call_id;
+ pj_str_t dest;
+ PyObject *pDstUri;
+ pjsua_msg_data msg_data;
+ PyObject *omdObj;
+ pj_pool_t *pool = NULL;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "iOO", &call_id, &pDstUri, &omdObj)) {
+ return NULL;
+ }
+
+ if (!PyString_Check(pDstUri))
+ return NULL;
+
+ dest = PyString_ToPJ(pDstUri);
+ pjsua_msg_data_init(&msg_data);
+
+ if (omdObj != Py_None) {
+ PyObj_pjsua_msg_data *omd;
+
+ omd = (PyObj_pjsua_msg_data *)omdObj;
+ msg_data.content_type = PyString_ToPJ(omd->content_type);
+ msg_data.msg_body = PyString_ToPJ(omd->msg_body);
+ pool = pjsua_pool_create("pytmp", POOL_SIZE, POOL_SIZE);
+ translate_hdr(pool, &msg_data.hdr_list, omd->hdr_list);
+ }
+
+ status = pjsua_call_xfer(call_id, &dest, &msg_data);
+
+ if (pool)
+ pj_pool_release(pool);
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_call_xfer_replaces
+ */
+static PyObject *py_pjsua_call_xfer_replaces(PyObject *pSelf, PyObject *pArgs)
+{
+ int status;
+ int call_id;
+ int dest_call_id;
+ unsigned options;
+ pjsua_msg_data msg_data;
+ PyObject *omdObj;
+ pj_pool_t *pool = NULL;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "iiIO", &call_id, &dest_call_id,
+ &options, &omdObj))
+ {
+ return NULL;
+ }
+
+ pjsua_msg_data_init(&msg_data);
+
+ if (omdObj != Py_None) {
+ PyObj_pjsua_msg_data *omd;
+
+ omd = (PyObj_pjsua_msg_data *)omdObj;
+ msg_data.content_type = PyString_ToPJ(omd->content_type);
+ msg_data.msg_body = PyString_ToPJ(omd->msg_body);
+ pool = pjsua_pool_create("pytmp", POOL_SIZE, POOL_SIZE);
+ translate_hdr(pool, &msg_data.hdr_list, omd->hdr_list);
+ }
+
+ status = pjsua_call_xfer_replaces(call_id, dest_call_id, options,
+ &msg_data);
+
+ if (pool)
+ pj_pool_release(pool);
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_call_dial_dtmf
+ */
+static PyObject *py_pjsua_call_dial_dtmf(PyObject *pSelf, PyObject *pArgs)
+{
+ int call_id;
+ PyObject *pDigits;
+ pj_str_t digits;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "iO", &call_id, &pDigits)) {
+ return NULL;
+ }
+
+ if (!PyString_Check(pDigits))
+ return Py_BuildValue("i", PJ_EINVAL);
+
+ digits = PyString_ToPJ(pDigits);
+ status = pjsua_call_dial_dtmf(call_id, &digits);
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_call_send_im
+ */
+static PyObject *py_pjsua_call_send_im(PyObject *pSelf, PyObject *pArgs)
+{
+ int status;
+ int call_id;
+ pj_str_t content;
+ pj_str_t * mime_type, tmp_mime_type;
+ PyObject *pMimeType, *pContent, *omdObj;
+ pjsua_msg_data msg_data;
+ int user_data;
+ pj_pool_t *pool = NULL;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "iOOOi", &call_id, &pMimeType, &pContent,
+ &omdObj, &user_data))
+ {
+ return NULL;
+ }
+
+ if (!PyString_Check(pContent))
+ return Py_BuildValue("i", PJ_EINVAL);
+
+ content = PyString_ToPJ(pContent);
+
+ if (PyString_Check(pMimeType)) {
+ mime_type = &tmp_mime_type;
+ tmp_mime_type = PyString_ToPJ(pMimeType);
+ } else {
+ mime_type = NULL;
+ }
+
+ pjsua_msg_data_init(&msg_data);
+ if (omdObj != Py_None) {
+ PyObj_pjsua_msg_data * omd;
+
+ omd = (PyObj_pjsua_msg_data *)omdObj;
+ msg_data.content_type = PyString_ToPJ(omd->content_type);
+ msg_data.msg_body = PyString_ToPJ(omd->msg_body);
+ pool = pjsua_pool_create("pytmp", POOL_SIZE, POOL_SIZE);
+ translate_hdr(pool, &msg_data.hdr_list, omd->hdr_list);
+ }
+
+ status = pjsua_call_send_im(call_id, mime_type, &content,
+ &msg_data, (void*)(long)user_data);
+
+ if (pool)
+ pj_pool_release(pool);
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_call_send_typing_ind
+ */
+static PyObject *py_pjsua_call_send_typing_ind(PyObject *pSelf,
+ PyObject *pArgs)
+{
+ int status;
+ int call_id;
+ int is_typing;
+ pjsua_msg_data msg_data;
+ PyObject *omdObj;
+ pj_pool_t *pool = NULL;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "iiO", &call_id, &is_typing, &omdObj)) {
+ return NULL;
+ }
+
+ pjsua_msg_data_init(&msg_data);
+ if (omdObj != Py_None) {
+ PyObj_pjsua_msg_data *omd;
+
+ omd = (PyObj_pjsua_msg_data *)omdObj;
+ msg_data.content_type = PyString_ToPJ(omd->content_type);
+ msg_data.msg_body = PyString_ToPJ(omd->msg_body);
+ pool = pjsua_pool_create("pytmp", POOL_SIZE, POOL_SIZE);
+ translate_hdr(pool, &msg_data.hdr_list, omd->hdr_list);
+ }
+
+ status = pjsua_call_send_typing_ind(call_id, is_typing, &msg_data);
+
+ if (pool)
+ pj_pool_release(pool);
+
+ return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_call_hangup_all
+ */
+static PyObject *py_pjsua_call_hangup_all(PyObject *pSelf, PyObject *pArgs)
+{
+ PJ_UNUSED_ARG(pSelf);
+ PJ_UNUSED_ARG(pArgs);
+
+ pjsua_call_hangup_all();
+
+ return Py_BuildValue("");
+}
+
+/*
+ * py_pjsua_call_dump
+ */
+static PyObject *py_pjsua_call_dump(PyObject *pSelf, PyObject *pArgs)
+{
+ int call_id;
+ int with_media;
+ PyObject *ret;
+ PyObject *pIndent;
+ char *buffer;
+ char *indent;
+ unsigned maxlen;
+ int status;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "iiIO", &call_id, &with_media,
+ &maxlen, &pIndent))
+ {
+ return NULL;
+ }
+
+ buffer = (char*) malloc(maxlen * sizeof(char));
+ indent = PyString_AsString(pIndent);
+
+ status = pjsua_call_dump(call_id, with_media, buffer, maxlen, indent);
+ if (status != PJ_SUCCESS) {
+ free(buffer);
+ return PyString_FromString("");
+ }
+
+ ret = PyString_FromString(buffer);
+ free(buffer);
+ return (PyObject*)ret;
+}
+
+
+/*
+ * py_pjsua_dump
+ * Dump application states.
+ */
+static PyObject *py_pjsua_dump(PyObject *pSelf, PyObject *pArgs)
+{
+ int detail;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &detail)) {
+ return NULL;
+ }
+
+ pjsua_dump(detail);
+
+ return Py_BuildValue("");
+}
+
+
+/*
+ * py_pj_strerror
+ */
+static PyObject *py_pj_strerror(PyObject *pSelf, PyObject *pArgs)
+{
+ int err;
+ char err_msg[PJ_ERR_MSG_SIZE];
+ pj_str_t ret;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "i", &err)) {
+ return NULL;
+ }
+
+ ret = pj_strerror(err, err_msg, sizeof(err_msg));
+
+ return PyString_FromStringAndSize(err_msg, ret.slen);
+}
+
+
+/*
+ * py_pj_parse_simple_sip
+ */
+static PyObject *py_pj_parse_simple_sip(PyObject *pSelf, PyObject *pArgs)
+{
+ const char *arg_uri;
+ pj_pool_t *pool;
+ char tmp[PJSIP_MAX_URL_SIZE];
+ pjsip_uri *uri;
+ pjsip_sip_uri *sip_uri;
+ PyObject *ret, *item;
+
+ PJ_UNUSED_ARG(pSelf);
+
+ if (!PyArg_ParseTuple(pArgs, "s", &arg_uri)) {
+ return NULL;
+ }
+
+ strncpy(tmp, arg_uri, sizeof(tmp));
+ tmp[sizeof(tmp)-1] = '\0';
+
+ pool = pjsua_pool_create("py_pj_parse_simple_sip", 512, 512);
+ uri = pjsip_parse_uri(pool, tmp, strlen(tmp), 0);
+
+ if (uri == NULL || (!PJSIP_URI_SCHEME_IS_SIP(uri) &&
+ !PJSIP_URI_SCHEME_IS_SIPS(uri))) {
+ pj_pool_release(pool);
+ return Py_BuildValue("");
+ }
+
+ ret = PyTuple_New(5);
+ sip_uri = (pjsip_sip_uri*) pjsip_uri_get_uri(uri);
+
+ /* Scheme */
+ item = PyString_FromPJ(pjsip_uri_get_scheme(uri));
+ PyTuple_SetItem(ret, 0, item);
+
+ /* Username */
+ item = PyString_FromPJ(&sip_uri->user);
+ PyTuple_SetItem(ret, 1, item);
+
+ /* Host */
+ item = PyString_FromPJ(&sip_uri->host);
+ PyTuple_SetItem(ret, 2, item);
+
+ /* Port */
+ if (sip_uri->port == 5060) {
+ sip_uri->port = 0;
+ }
+ item = Py_BuildValue("i", sip_uri->port);
+ PyTuple_SetItem(ret, 3, item);
+
+ /* Transport */
+ if (pj_stricmp2(&sip_uri->transport_param, "udp")) {
+ sip_uri->transport_param.ptr = "";
+ sip_uri->transport_param.slen = 0;
+ }
+ item = PyString_FromPJ(&sip_uri->transport_param);
+ PyTuple_SetItem(ret, 4, item);
+
+ pj_pool_release(pool);
+ return ret;
+}
+
+
+static char pjsua_call_get_max_count_doc[] =
+ "int _pjsua.call_get_max_count () "
+ "Get maximum number of calls configured in pjsua.";
+static char pjsua_call_get_count_doc[] =
+ "int _pjsua.call_get_count () "
+ "Get number of currently active calls.";
+static char pjsua_enum_calls_doc[] =
+ "int[] _pjsua.enum_calls () "
+ "Get maximum number of calls configured in pjsua.";
+static char pjsua_call_make_call_doc[] =
+ "int,int _pjsua.call_make_call (int acc_id, string dst_uri, int options,"
+ "int user_data, _pjsua.Msg_Data msg_data) "
+ "Make outgoing call to the specified URI using the specified account.";
+static char pjsua_call_is_active_doc[] =
+ "int _pjsua.call_is_active (int call_id) "
+ "Check if the specified call has active INVITE session and the INVITE "
+ "session has not been disconnected.";
+static char pjsua_call_has_media_doc[] =
+ "int _pjsua.call_has_media (int call_id) "
+ "Check if call has an active media session.";
+static char pjsua_call_get_conf_port_doc[] =
+ "int _pjsua.call_get_conf_port (int call_id) "
+ "Get the conference port identification associated with the call.";
+static char pjsua_call_get_info_doc[] =
+ "_pjsua.Call_Info _pjsua.call_get_info (int call_id) "
+ "Obtain detail information about the specified call.";
+static char pjsua_call_set_user_data_doc[] =
+ "int _pjsua.call_set_user_data (int call_id, int user_data) "
+ "Attach application specific data to the call.";
+static char pjsua_call_get_user_data_doc[] =
+ "int _pjsua.call_get_user_data (int call_id) "
+ "Get user data attached to the call.";
+static char pjsua_call_answer_doc[] =
+ "int _pjsua.call_answer (int call_id, int code, string reason, "
+ "_pjsua.Msg_Data msg_data) "
+ "Send response to incoming INVITE request.";
+static char pjsua_call_hangup_doc[] =
+ "int _pjsua.call_hangup (int call_id, int code, string reason, "
+ "_pjsua.Msg_Data msg_data) "
+ "Hangup call by using method that is appropriate according "
+ "to the call state.";
+static char pjsua_call_set_hold_doc[] =
+ "int _pjsua.call_set_hold (int call_id, _pjsua.Msg_Data msg_data) "
+ "Put the specified call on hold.";
+static char pjsua_call_reinvite_doc[] =
+ "int _pjsua.call_reinvite (int call_id, int unhold, "
+ "_pjsua.Msg_Data msg_data) "
+ "Send re-INVITE (to release hold).";
+static char pjsua_call_xfer_doc[] =
+ "int _pjsua.call_xfer (int call_id, string dest, "
+ "_pjsua.Msg_Data msg_data) "
+ "Initiate call transfer to the specified address. "
+ "This function will send REFER request to instruct remote call party "
+ "to initiate a new INVITE session to the specified destination/target.";
+static char pjsua_call_xfer_replaces_doc[] =
+ "int _pjsua.call_xfer_replaces (int call_id, int dest_call_id, "
+ "int options, _pjsua.Msg_Data msg_data) "
+ "Initiate attended call transfer. This function will send REFER request "
+ "to instruct remote call party to initiate new INVITE session to the URL "
+ "of dest_call_id. The party at dest_call_id then should 'replace' the call"
+ "with us with the new call from the REFER recipient.";
+static char pjsua_call_dial_dtmf_doc[] =
+ "int _pjsua.call_dial_dtmf (int call_id, string digits) "
+ "Send DTMF digits to remote using RFC 2833 payload formats.";
+static char pjsua_call_send_im_doc[] =
+ "int _pjsua.call_send_im (int call_id, string mime_type, string content,"
+ "_pjsua.Msg_Data msg_data, int user_data) "
+ "Send instant messaging inside INVITE session.";
+static char pjsua_call_send_typing_ind_doc[] =
+ "int _pjsua.call_send_typing_ind (int call_id, int is_typing, "
+ "_pjsua.Msg_Data msg_data) "
+ "Send IM typing indication inside INVITE session.";
+static char pjsua_call_hangup_all_doc[] =
+ "void _pjsua.call_hangup_all () "
+ "Terminate all calls.";
+static char pjsua_call_dump_doc[] =
+ "int _pjsua.call_dump (int call_id, int with_media, int maxlen, "
+ "string indent) "
+ "Dump call and media statistics to string.";
+
+/* END OF LIB CALL */
+
+/*
+ * Map of function names to functions
+ */
+static PyMethodDef py_pjsua_methods[] =
+{
+ {
+ "thread_register", py_pjsua_thread_register, METH_VARARGS,
+ pjsua_thread_register_doc
+ },
+ {
+ "perror", py_pjsua_perror, METH_VARARGS, pjsua_perror_doc
+ },
+ {
+ "create", py_pjsua_create, METH_VARARGS, pjsua_create_doc
+ },
+ {
+ "init", py_pjsua_init, METH_VARARGS, pjsua_init_doc
+ },
+ {
+ "start", py_pjsua_start, METH_VARARGS, pjsua_start_doc
+ },
+ {
+ "destroy", py_pjsua_destroy, METH_VARARGS, pjsua_destroy_doc
+ },
+ {
+ "handle_events", py_pjsua_handle_events, METH_VARARGS,
+ pjsua_handle_events_doc
+ },
+ {
+ "verify_sip_url", py_pjsua_verify_sip_url, METH_VARARGS,
+ pjsua_verify_sip_url_doc
+ },
+ {
+ "reconfigure_logging", py_pjsua_reconfigure_logging, METH_VARARGS,
+ pjsua_reconfigure_logging_doc
+ },
+ {
+ "logging_config_default", py_pjsua_logging_config_default,
+ METH_VARARGS, pjsua_logging_config_default_doc
+ },
+ {
+ "config_default", py_pjsua_config_default, METH_VARARGS,
+ pjsua_config_default_doc
+ },
+ {
+ "media_config_default", py_pjsua_media_config_default, METH_VARARGS,
+ pjsua_media_config_default_doc
+ },
+
+
+ {
+ "msg_data_init", py_pjsua_msg_data_init, METH_VARARGS,
+ pjsua_msg_data_init_doc
+ },
+ {
+ "transport_config_default", py_pjsua_transport_config_default,
+ METH_VARARGS,pjsua_transport_config_default_doc
+ },
+ {
+ "transport_create", py_pjsua_transport_create, METH_VARARGS,
+ pjsua_transport_create_doc
+ },
+ {
+ "transport_enum_transports", py_pjsua_enum_transports, METH_VARARGS,
+ pjsua_enum_transports_doc
+ },
+ {
+ "transport_get_info", py_pjsua_transport_get_info, METH_VARARGS,
+ pjsua_transport_get_info_doc
+ },
+ {
+ "transport_set_enable", py_pjsua_transport_set_enable, METH_VARARGS,
+ pjsua_transport_set_enable_doc
+ },
+ {
+ "transport_close", py_pjsua_transport_close, METH_VARARGS,
+ pjsua_transport_close_doc
+ },
+ {
+ "acc_config_default", py_pjsua_acc_config_default, METH_VARARGS,
+ pjsua_acc_config_default_doc
+ },
+ {
+ "acc_get_count", py_pjsua_acc_get_count, METH_VARARGS,
+ pjsua_acc_get_count_doc
+ },
+ {
+ "acc_is_valid", py_pjsua_acc_is_valid, METH_VARARGS,
+ pjsua_acc_is_valid_doc
+ },
+ {
+ "acc_set_default", py_pjsua_acc_set_default, METH_VARARGS,
+ pjsua_acc_set_default_doc
+ },
+ {
+ "acc_get_default", py_pjsua_acc_get_default, METH_VARARGS,
+ pjsua_acc_get_default_doc
+ },
+ {
+ "acc_add", py_pjsua_acc_add, METH_VARARGS,
+ pjsua_acc_add_doc
+ },
+ {
+ "acc_add_local", py_pjsua_acc_add_local, METH_VARARGS,
+ pjsua_acc_add_local_doc
+ },
+ {
+ "acc_del", py_pjsua_acc_del, METH_VARARGS,
+ pjsua_acc_del_doc
+ },
+ {
+ "acc_set_user_data", py_pjsua_acc_set_user_data, METH_VARARGS,
+ "Accociate user data with the account"
+ },
+ {
+ "acc_get_user_data", py_pjsua_acc_get_user_data, METH_VARARGS,
+ "Get account's user data"
+ },
+ {
+ "acc_modify", py_pjsua_acc_modify, METH_VARARGS,
+ pjsua_acc_modify_doc
+ },
+ {
+ "acc_set_online_status", py_pjsua_acc_set_online_status, METH_VARARGS,
+ pjsua_acc_set_online_status_doc
+ },
+ {
+ "acc_set_online_status2", py_pjsua_acc_set_online_status2, METH_VARARGS,
+ pjsua_acc_set_online_status2_doc
+ },
+ {
+ "acc_set_registration", py_pjsua_acc_set_registration, METH_VARARGS,
+ pjsua_acc_set_registration_doc
+ },
+ {
+ "acc_get_info", py_pjsua_acc_get_info, METH_VARARGS,
+ pjsua_acc_get_info_doc
+ },
+ {
+ "acc_pres_notify", py_pjsua_acc_pres_notify, METH_VARARGS,
+ "Accept or reject subscription request"
+ },
+ {
+ "enum_accs", py_pjsua_enum_accs, METH_VARARGS,
+ pjsua_enum_accs_doc
+ },
+ {
+ "acc_enum_info", py_pjsua_acc_enum_info, METH_VARARGS,
+ pjsua_acc_enum_info_doc
+ },
+ {
+ "acc_set_transport", py_pjsua_acc_set_transport, METH_VARARGS,
+ "Lock transport to use the specified transport"
+ },
+ {
+ "buddy_config_default", py_pjsua_buddy_config_default, METH_VARARGS,
+ pjsua_buddy_config_default_doc
+ },
+ {
+ "get_buddy_count", py_pjsua_get_buddy_count, METH_VARARGS,
+ pjsua_get_buddy_count_doc
+ },
+ {
+ "buddy_is_valid", py_pjsua_buddy_is_valid, METH_VARARGS,
+ pjsua_buddy_is_valid_doc
+ },
+ {
+ "enum_buddies", py_pjsua_enum_buddies, METH_VARARGS,
+ pjsua_enum_buddies_doc
+ },
+ {
+ "buddy_find", py_pjsua_buddy_find, METH_VARARGS,
+ "Find buddy with the specified URI"
+ },
+ {
+ "buddy_get_info", py_pjsua_buddy_get_info, METH_VARARGS,
+ pjsua_buddy_get_info_doc
+ },
+ {
+ "buddy_add", py_pjsua_buddy_add, METH_VARARGS,
+ pjsua_buddy_add_doc
+ },
+ {
+ "buddy_del", py_pjsua_buddy_del, METH_VARARGS,
+ pjsua_buddy_del_doc
+ },
+ {
+ "buddy_set_user_data", py_pjsua_buddy_set_user_data, METH_VARARGS,
+ "Associate user data to the buddy object"
+ },
+ {
+ "buddy_get_user_data", py_pjsua_buddy_get_user_data, METH_VARARGS,
+ "Get buddy user data"
+ },
+ {
+ "buddy_subscribe_pres", py_pjsua_buddy_subscribe_pres, METH_VARARGS,
+ pjsua_buddy_subscribe_pres_doc
+ },
+ {
+ "pres_dump", py_pjsua_pres_dump, METH_VARARGS,
+ pjsua_pres_dump_doc
+ },
+ {
+ "im_send", py_pjsua_im_send, METH_VARARGS,
+ pjsua_im_send_doc
+ },
+ {
+ "im_typing", py_pjsua_im_typing, METH_VARARGS,
+ pjsua_im_typing_doc
+ },
+ {
+ "conf_get_max_ports", py_pjsua_conf_get_max_ports, METH_VARARGS,
+ pjsua_conf_get_max_ports_doc
+ },
+ {
+ "conf_get_active_ports", py_pjsua_conf_get_active_ports, METH_VARARGS,
+ pjsua_conf_get_active_ports_doc
+ },
+ {
+ "enum_conf_ports", py_pjsua_enum_conf_ports, METH_VARARGS,
+ pjsua_enum_conf_ports_doc
+ },
+ {
+ "conf_get_port_info", py_pjsua_conf_get_port_info, METH_VARARGS,
+ pjsua_conf_get_port_info_doc
+ },
+ {
+ "conf_remove_port", py_pjsua_conf_remove_port, METH_VARARGS,
+ pjsua_conf_remove_port_doc
+ },
+ {
+ "conf_connect", py_pjsua_conf_connect, METH_VARARGS,
+ pjsua_conf_connect_doc
+ },
+ {
+ "conf_disconnect", py_pjsua_conf_disconnect, METH_VARARGS,
+ pjsua_conf_disconnect_doc
+ },
+ {
+ "conf_set_tx_level", py_pjsua_conf_set_tx_level, METH_VARARGS,
+ "Adjust the signal level to be transmitted from the bridge to the"
+ " specified port by making it louder or quieter"
+ },
+ {
+ "conf_set_rx_level", py_pjsua_conf_set_rx_level, METH_VARARGS,
+ "Adjust the signal level to be received from the specified port (to"
+ " the bridge) by making it louder or quieter"
+ },
+ {
+ "conf_get_signal_level", py_pjsua_conf_get_signal_level, METH_VARARGS,
+ "Get last signal level transmitted to or received from the specified port"
+ },
+ {
+ "player_create", py_pjsua_player_create, METH_VARARGS,
+ pjsua_player_create_doc
+ },
+ {
+ "playlist_create", py_pjsua_playlist_create, METH_VARARGS,
+ "Create WAV playlist"
+ },
+ {
+ "player_get_conf_port", py_pjsua_player_get_conf_port, METH_VARARGS,
+ pjsua_player_get_conf_port_doc
+ },
+ {
+ "player_set_pos", py_pjsua_player_set_pos, METH_VARARGS,
+ pjsua_player_set_pos_doc
+ },
+ {
+ "player_destroy", py_pjsua_player_destroy, METH_VARARGS,
+ pjsua_player_destroy_doc
+ },
+ {
+ "recorder_create", py_pjsua_recorder_create, METH_VARARGS,
+ pjsua_recorder_create_doc
+ },
+ {
+ "recorder_get_conf_port", py_pjsua_recorder_get_conf_port, METH_VARARGS,
+ pjsua_recorder_get_conf_port_doc
+ },
+ {
+ "recorder_destroy", py_pjsua_recorder_destroy, METH_VARARGS,
+ pjsua_recorder_destroy_doc
+ },
+ {
+ "enum_snd_devs", py_pjsua_enum_snd_devs, METH_VARARGS,
+ pjsua_enum_snd_devs_doc
+ },
+ {
+ "get_snd_dev", py_pjsua_get_snd_dev, METH_VARARGS,
+ pjsua_get_snd_dev_doc
+ },
+ {
+ "set_snd_dev", py_pjsua_set_snd_dev, METH_VARARGS,
+ pjsua_set_snd_dev_doc
+ },
+ {
+ "set_null_snd_dev", py_pjsua_set_null_snd_dev, METH_VARARGS,
+ pjsua_set_null_snd_dev_doc
+ },
+ {
+ "set_ec", py_pjsua_set_ec, METH_VARARGS,
+ pjsua_set_ec_doc
+ },
+ {
+ "get_ec_tail", py_pjsua_get_ec_tail, METH_VARARGS,
+ pjsua_get_ec_tail_doc
+ },
+ {
+ "enum_codecs", py_pjsua_enum_codecs, METH_VARARGS,
+ pjsua_enum_codecs_doc
+ },
+ {
+ "codec_set_priority", py_pjsua_codec_set_priority, METH_VARARGS,
+ pjsua_codec_set_priority_doc
+ },
+ {
+ "codec_get_param", py_pjsua_codec_get_param, METH_VARARGS,
+ pjsua_codec_get_param_doc
+ },
+ {
+ "codec_set_param", py_pjsua_codec_set_param, METH_VARARGS,
+ pjsua_codec_set_param_doc
+ },
+ {
+ "call_get_max_count", py_pjsua_call_get_max_count, METH_VARARGS,
+ pjsua_call_get_max_count_doc
+ },
+ {
+ "call_get_count", py_pjsua_call_get_count, METH_VARARGS,
+ pjsua_call_get_count_doc
+ },
+ {
+ "enum_calls", py_pjsua_enum_calls, METH_VARARGS,
+ pjsua_enum_calls_doc
+ },
+ {
+ "call_make_call", py_pjsua_call_make_call, METH_VARARGS,
+ pjsua_call_make_call_doc
+ },
+ {
+ "call_is_active", py_pjsua_call_is_active, METH_VARARGS,
+ pjsua_call_is_active_doc
+ },
+ {
+ "call_has_media", py_pjsua_call_has_media, METH_VARARGS,
+ pjsua_call_has_media_doc
+ },
+ {
+ "call_get_conf_port", py_pjsua_call_get_conf_port, METH_VARARGS,
+ pjsua_call_get_conf_port_doc
+ },
+ {
+ "call_get_info", py_pjsua_call_get_info, METH_VARARGS,
+ pjsua_call_get_info_doc
+ },
+ {
+ "call_set_user_data", py_pjsua_call_set_user_data, METH_VARARGS,
+ pjsua_call_set_user_data_doc
+ },
+ {
+ "call_get_user_data", py_pjsua_call_get_user_data, METH_VARARGS,
+ pjsua_call_get_user_data_doc
+ },
+ {
+ "call_answer", py_pjsua_call_answer, METH_VARARGS,
+ pjsua_call_answer_doc
+ },
+ {
+ "call_hangup", py_pjsua_call_hangup, METH_VARARGS,
+ pjsua_call_hangup_doc
+ },
+ {
+ "call_set_hold", py_pjsua_call_set_hold, METH_VARARGS,
+ pjsua_call_set_hold_doc
+ },
+ {
+ "call_reinvite", py_pjsua_call_reinvite, METH_VARARGS,
+ pjsua_call_reinvite_doc
+ },
+ {
+ "call_update", py_pjsua_call_update, METH_VARARGS,
+ "Send UPDATE"
+ },
+ {
+ "call_xfer", py_pjsua_call_xfer, METH_VARARGS,
+ pjsua_call_xfer_doc
+ },
+ {
+ "call_xfer_replaces", py_pjsua_call_xfer_replaces, METH_VARARGS,
+ pjsua_call_xfer_replaces_doc
+ },
+ {
+ "call_dial_dtmf", py_pjsua_call_dial_dtmf, METH_VARARGS,
+ pjsua_call_dial_dtmf_doc
+ },
+ {
+ "call_send_im", py_pjsua_call_send_im, METH_VARARGS,
+ pjsua_call_send_im_doc
+ },
+ {
+ "call_send_typing_ind", py_pjsua_call_send_typing_ind, METH_VARARGS,
+ pjsua_call_send_typing_ind_doc
+ },
+ {
+ "call_hangup_all", py_pjsua_call_hangup_all, METH_VARARGS,
+ pjsua_call_hangup_all_doc
+ },
+ {
+ "call_dump", py_pjsua_call_dump, METH_VARARGS,
+ pjsua_call_dump_doc
+ },
+ {
+ "call_send_request", py_pjsua_call_send_request, METH_VARARGS,
+ "Send arbitrary request"
+ },
+ {
+ "dump", py_pjsua_dump, METH_VARARGS, "Dump application state"
+ },
+ {
+ "strerror", py_pj_strerror, METH_VARARGS, "Get error message"
+ },
+ {
+ "parse_simple_uri", py_pj_parse_simple_sip, METH_VARARGS, "Parse URI"
+ },
+
+
+ {NULL, NULL} /* end of function list */
+};
+
+
+
+/*
+ * Mapping C structs from and to Python objects & initializing object
+ */
+DL_EXPORT(void)
+init_pjsua(void)
+{
+ PyObject* m = NULL;
+#define ADD_CONSTANT(mod,name) PyModule_AddIntConstant(mod,#name,name)
+
+
+ PyEval_InitThreads();
+
+ if (PyType_Ready(&PyTyp_pjsua_callback) < 0)
+ return;
+ if (PyType_Ready(&PyTyp_pjsua_config) < 0)
+ return;
+ if (PyType_Ready(&PyTyp_pjsua_logging_config) < 0)
+ return;
+ if (PyType_Ready(&PyTyp_pjsua_msg_data) < 0)
+ return;
+ PyTyp_pjsua_media_config.tp_new = PyType_GenericNew;
+ if (PyType_Ready(&PyTyp_pjsua_media_config) < 0)
+ return;
+ PyTyp_pjsip_cred_info.tp_new = PyType_GenericNew;
+ if (PyType_Ready(&PyTyp_pjsip_cred_info) < 0)
+ return;
+
+ /* LIB TRANSPORT */
+
+ if (PyType_Ready(&PyTyp_pjsua_transport_config) < 0)
+ return;
+
+ if (PyType_Ready(&PyTyp_pjsua_transport_info) < 0)
+ return;
+
+ /* END OF LIB TRANSPORT */
+
+ /* LIB ACCOUNT */
+
+
+ if (PyType_Ready(&PyTyp_pjsua_acc_config) < 0)
+ return;
+ if (PyType_Ready(&PyTyp_pjsua_acc_info) < 0)
+ return;
+
+ /* END OF LIB ACCOUNT */
+
+ /* LIB BUDDY */
+
+ if (PyType_Ready(&PyTyp_pjsua_buddy_config) < 0)
+ return;
+ if (PyType_Ready(&PyTyp_pjsua_buddy_info) < 0)
+ return;
+
+ /* END OF LIB BUDDY */
+
+ /* LIB MEDIA */
+
+ if (PyType_Ready(&PyTyp_pjsua_codec_info) < 0)
+ return;
+
+ if (PyType_Ready(&PyTyp_pjsua_conf_port_info) < 0)
+ return;
+
+ if (PyType_Ready(&PyTyp_pjmedia_snd_dev_info) < 0)
+ return;
+
+ PyTyp_pjmedia_codec_param_info.tp_new = PyType_GenericNew;
+ if (PyType_Ready(&PyTyp_pjmedia_codec_param_info) < 0)
+ return;
+ PyTyp_pjmedia_codec_param_setting.tp_new = PyType_GenericNew;
+ if (PyType_Ready(&PyTyp_pjmedia_codec_param_setting) < 0)
+ return;
+
+ if (PyType_Ready(&PyTyp_pjmedia_codec_param) < 0)
+ return;
+
+ /* END OF LIB MEDIA */
+
+ /* LIB CALL */
+
+ if (PyType_Ready(&PyTyp_pjsua_call_info) < 0)
+ return;
+
+ /* END OF LIB CALL */
+
+ m = Py_InitModule3(
+ "_pjsua", py_pjsua_methods, "PJSUA-lib module for python"
+ );
+
+ Py_INCREF(&PyTyp_pjsua_callback);
+ PyModule_AddObject(m, "Callback", (PyObject *)&PyTyp_pjsua_callback);
+
+ Py_INCREF(&PyTyp_pjsua_config);
+ PyModule_AddObject(m, "Config", (PyObject *)&PyTyp_pjsua_config);
+
+ Py_INCREF(&PyTyp_pjsua_media_config);
+ PyModule_AddObject(m, "Media_Config", (PyObject *)&PyTyp_pjsua_media_config);
+
+ Py_INCREF(&PyTyp_pjsua_logging_config);
+ PyModule_AddObject(m, "Logging_Config", (PyObject *)&PyTyp_pjsua_logging_config);
+
+ Py_INCREF(&PyTyp_pjsua_msg_data);
+ PyModule_AddObject(m, "Msg_Data", (PyObject *)&PyTyp_pjsua_msg_data);
+
+ Py_INCREF(&PyTyp_pjsip_cred_info);
+ PyModule_AddObject(m, "Pjsip_Cred_Info",
+ (PyObject *)&PyTyp_pjsip_cred_info
+ );
+
+ /* LIB TRANSPORT */
+
+ Py_INCREF(&PyTyp_pjsua_transport_config);
+ PyModule_AddObject
+ (m, "Transport_Config", (PyObject *)&PyTyp_pjsua_transport_config);
+
+ Py_INCREF(&PyTyp_pjsua_transport_info);
+ PyModule_AddObject(m, "Transport_Info", (PyObject *)&PyTyp_pjsua_transport_info);
+
+
+ /* END OF LIB TRANSPORT */
+
+ /* LIB ACCOUNT */
+
+
+ Py_INCREF(&PyTyp_pjsua_acc_config);
+ PyModule_AddObject(m, "Acc_Config", (PyObject *)&PyTyp_pjsua_acc_config);
+ Py_INCREF(&PyTyp_pjsua_acc_info);
+ PyModule_AddObject(m, "Acc_Info", (PyObject *)&PyTyp_pjsua_acc_info);
+
+ /* END OF LIB ACCOUNT */
+
+ /* LIB BUDDY */
+
+ Py_INCREF(&PyTyp_pjsua_buddy_config);
+ PyModule_AddObject(m, "Buddy_Config", (PyObject *)&PyTyp_pjsua_buddy_config);
+ Py_INCREF(&PyTyp_pjsua_buddy_info);
+ PyModule_AddObject(m, "Buddy_Info", (PyObject *)&PyTyp_pjsua_buddy_info);
+
+ /* END OF LIB BUDDY */
+
+ /* LIB MEDIA */
+
+ Py_INCREF(&PyTyp_pjsua_codec_info);
+ PyModule_AddObject(m, "Codec_Info", (PyObject *)&PyTyp_pjsua_codec_info);
+ Py_INCREF(&PyTyp_pjsua_conf_port_info);
+ PyModule_AddObject(m, "Conf_Port_Info", (PyObject *)&PyTyp_pjsua_conf_port_info);
+ Py_INCREF(&PyTyp_pjmedia_snd_dev_info);
+ PyModule_AddObject(m, "PJMedia_Snd_Dev_Info",
+ (PyObject *)&PyTyp_pjmedia_snd_dev_info);
+ Py_INCREF(&PyTyp_pjmedia_codec_param_info);
+ PyModule_AddObject(m, "PJMedia_Codec_Param_Info",
+ (PyObject *)&PyTyp_pjmedia_codec_param_info);
+ Py_INCREF(&PyTyp_pjmedia_codec_param_setting);
+ PyModule_AddObject(m, "PJMedia_Codec_Param_Setting",
+ (PyObject *)&PyTyp_pjmedia_codec_param_setting);
+ Py_INCREF(&PyTyp_pjmedia_codec_param);
+ PyModule_AddObject(m, "PJMedia_Codec_Param",
+ (PyObject *)&PyTyp_pjmedia_codec_param);
+
+ /* END OF LIB MEDIA */
+
+ /* LIB CALL */
+
+ Py_INCREF(&PyTyp_pjsua_call_info);
+ PyModule_AddObject(m, "Call_Info", (PyObject *)&PyTyp_pjsua_call_info);
+
+ /* END OF LIB CALL */
+
+
+ /*
+ * Add various constants.
+ */
+ /* Skip it.. */
+
+#undef ADD_CONSTANT
+}
diff --git a/pjsip-apps/src/python/_pjsua.def b/pjsip-apps/src/python/_pjsua.def
new file mode 100644
index 0000000..9b150a9
--- /dev/null
+++ b/pjsip-apps/src/python/_pjsua.def
@@ -0,0 +1,2 @@
+EXPORTS
+ init_pjsua
diff --git a/pjsip-apps/src/python/_pjsua.h b/pjsip-apps/src/python/_pjsua.h
new file mode 100644
index 0000000..f2ed780
--- /dev/null
+++ b/pjsip-apps/src/python/_pjsua.h
@@ -0,0 +1,3508 @@
+/* $Id: _pjsua.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __PY_PJSUA_H__
+#define __PY_PJSUA_H__
+
+#define _CRT_SECURE_NO_DEPRECATE
+
+#include <Python.h>
+#include <structmember.h>
+#include <pjsua-lib/pjsua.h>
+
+
+PJ_INLINE(pj_str_t) PyString_ToPJ(const PyObject *obj)
+{
+ pj_str_t str;
+
+ if (obj && PyString_Check(obj)) {
+ str.ptr = PyString_AS_STRING(obj);
+ str.slen = PyString_GET_SIZE(obj);
+ } else {
+ str.ptr = NULL;
+ str.slen = 0;
+ }
+
+ return str;
+}
+
+PJ_INLINE(PyObject*) PyString_FromPJ(const pj_str_t *str)
+{
+ return PyString_FromStringAndSize(str->ptr, str->slen);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+/*
+ * PyObj_pjsip_cred_info
+ */
+typedef struct
+{
+ PyObject_HEAD
+
+ /* Type-specific fields go here. */
+ PyObject *realm;
+ PyObject *scheme;
+ PyObject *username;
+ int data_type;
+ PyObject *data;
+
+} PyObj_pjsip_cred_info;
+
+/*
+ * cred_info_dealloc
+ * deletes a cred info from memory
+ */
+static void PyObj_pjsip_cred_info_delete(PyObj_pjsip_cred_info* self)
+{
+ Py_XDECREF(self->realm);
+ Py_XDECREF(self->scheme);
+ Py_XDECREF(self->username);
+ Py_XDECREF(self->data);
+ self->ob_type->tp_free((PyObject*)self);
+}
+
+
+static void PyObj_pjsip_cred_info_import(PyObj_pjsip_cred_info *obj,
+ const pjsip_cred_info *cfg)
+{
+ Py_XDECREF(obj->realm);
+ obj->realm = PyString_FromPJ(&cfg->realm);
+ Py_XDECREF(obj->scheme);
+ obj->scheme = PyString_FromPJ(&cfg->scheme);
+ Py_XDECREF(obj->username);
+ obj->username = PyString_FromPJ(&cfg->username);
+ obj->data_type = cfg->data_type;
+ Py_XDECREF(obj->data);
+ obj->data = PyString_FromPJ(&cfg->data);
+}
+
+static void PyObj_pjsip_cred_info_export(pjsip_cred_info *cfg,
+ PyObj_pjsip_cred_info *obj)
+{
+ cfg->realm = PyString_ToPJ(obj->realm);
+ cfg->scheme = PyString_ToPJ(obj->scheme);
+ cfg->username = PyString_ToPJ(obj->username);
+ cfg->data_type = obj->data_type;
+ cfg->data = PyString_ToPJ(obj->data);
+}
+
+
+/*
+ * cred_info_new
+ * constructor for cred_info object
+ */
+static PyObject * PyObj_pjsip_cred_info_new(PyTypeObject *type,
+ PyObject *args,
+ PyObject *kwds)
+{
+ PyObj_pjsip_cred_info *self;
+
+ PJ_UNUSED_ARG(args);
+ PJ_UNUSED_ARG(kwds);
+
+ self = (PyObj_pjsip_cred_info *)type->tp_alloc(type, 0);
+ if (self != NULL) {
+ self->realm = PyString_FromString("");
+ self->scheme = PyString_FromString("");
+ self->username = PyString_FromString("");
+ self->data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
+ self->data = PyString_FromString("");
+ }
+
+ return (PyObject *)self;
+}
+
+
+/*
+ * PyObj_pjsip_cred_info_members
+ */
+static PyMemberDef PyObj_pjsip_cred_info_members[] =
+{
+ {
+ "realm", T_OBJECT_EX,
+ offsetof(PyObj_pjsip_cred_info, realm), 0,
+ "Realm"
+ },
+ {
+ "scheme", T_OBJECT_EX,
+ offsetof(PyObj_pjsip_cred_info, scheme), 0,
+ "Scheme"
+ },
+ {
+ "username", T_OBJECT_EX,
+ offsetof(PyObj_pjsip_cred_info, username), 0,
+ "User name"
+ },
+ {
+ "data", T_OBJECT_EX,
+ offsetof(PyObj_pjsip_cred_info, data), 0,
+ "The data, which can be a plaintext password or a hashed digest, "
+ "depending on the value of data_type"
+ },
+ {
+ "data_type", T_INT,
+ offsetof(PyObj_pjsip_cred_info, data_type), 0,
+ "Type of data"
+ },
+
+ {NULL} /* Sentinel */
+};
+
+/*
+ * PyTyp_pjsip_cred_info
+ */
+static PyTypeObject PyTyp_pjsip_cred_info =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "_pjsua.Pjsip_Cred_Info", /*tp_name*/
+ sizeof(PyObj_pjsip_cred_info), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor)PyObj_pjsip_cred_info_delete,/*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "PJSIP credential information", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ PyObj_pjsip_cred_info_members, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ PyObj_pjsip_cred_info_new, /* tp_new */
+
+};
+
+
+//////////////////////////////////////////////////////////////////////////////
+/*
+ * PyObj_pjsua_callback
+ * C/python typewrapper for callback struct
+ */
+typedef struct PyObj_pjsua_callback
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+ PyObject * on_call_state;
+ PyObject * on_incoming_call;
+ PyObject * on_call_media_state;
+ PyObject * on_dtmf_digit;
+ PyObject * on_call_transfer_request;
+ PyObject * on_call_transfer_status;
+ PyObject * on_call_replace_request;
+ PyObject * on_call_replaced;
+ PyObject * on_reg_state;
+ PyObject * on_incoming_subscribe;
+ PyObject * on_buddy_state;
+ PyObject * on_pager;
+ PyObject * on_pager_status;
+ PyObject * on_typing;
+ PyObject * on_mwi_info;
+} PyObj_pjsua_callback;
+
+
+/*
+ * PyObj_pjsua_callback_delete
+ * destructor function for callback struct
+ */
+static void PyObj_pjsua_callback_delete(PyObj_pjsua_callback* self)
+{
+ Py_XDECREF(self->on_call_state);
+ Py_XDECREF(self->on_incoming_call);
+ Py_XDECREF(self->on_call_media_state);
+ Py_XDECREF(self->on_dtmf_digit);
+ Py_XDECREF(self->on_call_transfer_request);
+ Py_XDECREF(self->on_call_transfer_status);
+ Py_XDECREF(self->on_call_replace_request);
+ Py_XDECREF(self->on_call_replaced);
+ Py_XDECREF(self->on_reg_state);
+ Py_XDECREF(self->on_incoming_subscribe);
+ Py_XDECREF(self->on_buddy_state);
+ Py_XDECREF(self->on_pager);
+ Py_XDECREF(self->on_pager_status);
+ Py_XDECREF(self->on_typing);
+ Py_XDECREF(self->on_mwi_info);
+ self->ob_type->tp_free((PyObject*)self);
+}
+
+
+/*
+ * PyObj_pjsua_callback_new
+ * * declares constructor for callback struct
+ */
+static PyObject * PyObj_pjsua_callback_new(PyTypeObject *type,
+ PyObject *args,
+ PyObject *kwds)
+{
+ PyObj_pjsua_callback *self;
+
+ PJ_UNUSED_ARG(args);
+ PJ_UNUSED_ARG(kwds);
+
+ self = (PyObj_pjsua_callback *)type->tp_alloc(type, 0);
+ if (self != NULL) {
+ self->on_call_state = Py_BuildValue("");
+ self->on_incoming_call = Py_BuildValue("");
+ self->on_call_media_state = Py_BuildValue("");
+ self->on_dtmf_digit = Py_BuildValue("");
+ self->on_call_transfer_request = Py_BuildValue("");
+ self->on_call_transfer_status = Py_BuildValue("");
+ self->on_call_replace_request = Py_BuildValue("");
+ self->on_call_replaced = Py_BuildValue("");
+ self->on_reg_state = Py_BuildValue("");
+ self->on_incoming_subscribe = Py_BuildValue("");
+ self->on_buddy_state = Py_BuildValue("");
+ self->on_pager = Py_BuildValue("");
+ self->on_pager_status = Py_BuildValue("");
+ self->on_typing = Py_BuildValue("");
+ self->on_mwi_info = Py_BuildValue("");
+ }
+
+ return (PyObject *)self;
+}
+
+
+/*
+ * PyObj_pjsua_callback_members
+ * declares available functions for callback object
+ */
+static PyMemberDef PyObj_pjsua_callback_members[] =
+{
+ {
+ "on_call_state", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_callback, on_call_state), 0,
+ "Notify application when invite state has changed. Application may "
+ "then query the call info to get the detail call states."
+ },
+ {
+ "on_incoming_call", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_callback, on_incoming_call), 0,
+ "Notify application on incoming call."
+ },
+ {
+ "on_call_media_state", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_callback, on_call_media_state), 0,
+ "Notify application when media state in the call has changed. Normal "
+ "application would need to implement this callback, e.g. to connect "
+ "the call's media to sound device."
+ },
+ {
+ "on_dtmf_digit", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_callback, on_dtmf_digit), 0,
+ "Notify application upon receiving incoming DTMF digit."
+ },
+ {
+ "on_call_transfer_request", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_callback, on_call_transfer_request), 0,
+ "Notify application on call being transfered. "
+ "Application can decide to accept/reject transfer request "
+ "by setting the code (default is 200). When this callback "
+ "is not defined, the default behavior is to accept the "
+ "transfer."
+ },
+ {
+ "on_call_transfer_status", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_callback, on_call_transfer_status), 0,
+ "Notify application of the status of previously sent call "
+ "transfer request. Application can monitor the status of the "
+ "call transfer request, for example to decide whether to "
+ "terminate existing call."
+ },
+ {
+ "on_call_replace_request", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_callback, on_call_replace_request), 0,
+ "Notify application about incoming INVITE with Replaces header. "
+ "Application may reject the request by setting non-2xx code."
+ },
+ {
+ "on_call_replaced", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_callback, on_call_replaced), 0,
+ "Notify application that an existing call has been replaced with "
+ "a new call. This happens when PJSUA-API receives incoming INVITE "
+ "request with Replaces header."
+ " "
+ "After this callback is called, normally PJSUA-API will disconnect "
+ "old_call_id and establish new_call_id."
+ },
+ {
+ "on_reg_state", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_callback, on_reg_state), 0,
+ "Notify application when registration status has changed. Application "
+ "may then query the account info to get the registration details."
+ },
+ {
+ "on_incoming_subscribe", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_callback, on_incoming_subscribe), 0,
+ "Notification when incoming SUBSCRIBE request is received."
+ },
+ {
+ "on_buddy_state", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_callback, on_buddy_state), 0,
+ "Notify application when the buddy state has changed. Application may "
+ "then query the buddy into to get the details."
+ },
+ {
+ "on_pager", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_callback, on_pager), 0,
+ "Notify application on incoming pager (i.e. MESSAGE request). "
+ "Argument call_id will be -1 if MESSAGE request is not related to an "
+ "existing call."
+ },
+ {
+ "on_pager_status", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_callback, on_pager_status), 0,
+ "Notify application about the delivery status of outgoing pager "
+ "request."
+ },
+ {
+ "on_typing", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_callback, on_typing), 0,
+ "Notify application about typing indication."
+ },
+ {
+ "on_mwi_info", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_callback, on_mwi_info), 0,
+ "Notify application about MWI indication."
+ },
+ {NULL} /* Sentinel */
+};
+
+
+/*
+ * PyTyp_pjsua_callback
+ * callback class definition
+ */
+static PyTypeObject PyTyp_pjsua_callback =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "_pjsua.Callback", /*tp_name*/
+ sizeof(PyObj_pjsua_callback), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor)PyObj_pjsua_callback_delete, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "This structure describes application callback "
+ "to receive various event notifications from "
+ "PJSUA-API", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ PyObj_pjsua_callback_members, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ PyObj_pjsua_callback_new, /* tp_new */
+
+};
+
+
+//////////////////////////////////////////////////////////////////////////////
+/*
+ * PyObj_pjsua_media_config
+ * C/Python wrapper for pjsua_media_config object
+ */
+typedef struct
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+ unsigned clock_rate;
+ unsigned snd_clock_rate;
+ unsigned channel_count;
+ unsigned audio_frame_ptime;
+ int snd_auto_close_time;
+ unsigned max_media_ports;
+ int has_ioqueue;
+ unsigned thread_cnt;
+ unsigned quality;
+ unsigned ptime;
+ int no_vad;
+ unsigned ilbc_mode;
+ unsigned tx_drop_pct;
+ unsigned rx_drop_pct;
+ unsigned ec_options;
+ unsigned ec_tail_len;
+ int jb_min;
+ int jb_max;
+ int enable_ice;
+ int enable_turn;
+ PyObject *turn_server;
+ int turn_conn_type;
+ PyObject *turn_realm;
+ PyObject *turn_username;
+ int turn_passwd_type;
+ PyObject *turn_passwd;
+} PyObj_pjsua_media_config;
+
+
+/*
+ * PyObj_pjsua_media_config_members
+ * declares attributes accessible from both C and Python for media_config file
+ */
+static PyMemberDef PyObj_pjsua_media_config_members[] =
+{
+ {
+ "clock_rate", T_INT,
+ offsetof(PyObj_pjsua_media_config, clock_rate), 0,
+ "Clock rate to be applied to the conference bridge. If value is zero, "
+ "default clock rate will be used (16KHz)."
+ },
+ {
+ "snd_clock_rate", T_INT,
+ offsetof(PyObj_pjsua_media_config, snd_clock_rate), 0,
+ "Specify different clock rate of sound device, otherwise 0."
+ },
+ {
+ "channel_count", T_INT,
+ offsetof(PyObj_pjsua_media_config, channel_count), 0,
+ "Specify channel count (default 1)."
+ },
+ {
+ "audio_frame_ptime", T_INT,
+ offsetof(PyObj_pjsua_media_config, audio_frame_ptime), 0,
+ "Audio frame length in milliseconds."
+ },
+ {
+ "snd_auto_close_time", T_INT,
+ offsetof(PyObj_pjsua_media_config, snd_auto_close_time), 0,
+ "Sound idle time before it's closed."
+ },
+ {
+ "max_media_ports", T_INT,
+ offsetof(PyObj_pjsua_media_config, max_media_ports), 0,
+ "Specify maximum number of media ports to be created in the "
+ "conference bridge. Since all media terminate in the bridge (calls, "
+ "file player, file recorder, etc), the value must be large enough to "
+ "support all of them. However, the larger the value, the more "
+ "computations are performed."
+ },
+ {
+ "has_ioqueue", T_INT,
+ offsetof(PyObj_pjsua_media_config, has_ioqueue), 0,
+ "Specify whether the media manager should manage its own ioqueue for "
+ "the RTP/RTCP sockets. If yes, ioqueue will be created and at least "
+ "one worker thread will be created too. If no, the RTP/RTCP sockets "
+ "will share the same ioqueue as SIP sockets, and no worker thread is "
+ "needed."
+ },
+ {
+ "thread_cnt", T_INT,
+ offsetof(PyObj_pjsua_media_config, thread_cnt), 0,
+ "Specify the number of worker threads to handle incoming RTP packets. "
+ "A value of one is recommended for most applications."
+ },
+ {
+ "quality", T_INT,
+ offsetof(PyObj_pjsua_media_config, quality), 0,
+ "The media quality also sets speex codec quality/complexity to the "
+ "number."
+ },
+ {
+ "ptime", T_INT,
+ offsetof(PyObj_pjsua_media_config, ptime), 0,
+ "Specify default ptime."
+ },
+ {
+ "no_vad", T_INT,
+ offsetof(PyObj_pjsua_media_config, no_vad), 0,
+ "Disable VAD?"
+ },
+ {
+ "ilbc_mode", T_INT,
+ offsetof(PyObj_pjsua_media_config, ilbc_mode), 0,
+ "iLBC mode (20 or 30)."
+ },
+ {
+ "tx_drop_pct", T_INT,
+ offsetof(PyObj_pjsua_media_config, tx_drop_pct), 0,
+ "Percentage of RTP packet to drop in TX direction (to simulate packet "
+ "lost)."
+ },
+ {
+ "rx_drop_pct", T_INT,
+ offsetof(PyObj_pjsua_media_config, rx_drop_pct), 0,
+ "Percentage of RTP packet to drop in RX direction (to simulate packet "
+ "lost)."},
+ {
+ "ec_options", T_INT,
+ offsetof(PyObj_pjsua_media_config, ec_options), 0,
+ "Echo canceller options (see pjmedia_echo_create())"
+ },
+ {
+ "ec_tail_len", T_INT,
+ offsetof(PyObj_pjsua_media_config, ec_tail_len), 0,
+ "Echo canceller tail length, in miliseconds."
+ },
+ {
+ "jb_min", T_INT,
+ offsetof(PyObj_pjsua_media_config, jb_min), 0,
+ "Jitter buffer minimum size in milliseconds."
+ },
+ {
+ "jb_max", T_INT,
+ offsetof(PyObj_pjsua_media_config, jb_max), 0,
+ "Jitter buffer maximum size in milliseconds."
+ },
+ {
+ "enable_ice", T_INT,
+ offsetof(PyObj_pjsua_media_config, enable_ice), 0,
+ "Enable ICE."
+ },
+ {
+ "enable_turn", T_INT,
+ offsetof(PyObj_pjsua_media_config, enable_turn), 0,
+ "Enable TURN."
+ },
+ {
+ "turn_server", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_media_config, turn_server), 0,
+ "Specify the TURN server."
+ },
+ {
+ "turn_conn_type", T_INT,
+ offsetof(PyObj_pjsua_media_config, turn_conn_type), 0,
+ "Specify TURN connection type."
+ },
+ {
+ "turn_realm", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_media_config, turn_realm), 0,
+ "Specify the TURN realm."
+ },
+ {
+ "turn_username", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_media_config, turn_username), 0,
+ "Specify the TURN username."
+ },
+ {
+ "turn_passwd_type", T_INT,
+ offsetof(PyObj_pjsua_media_config, turn_passwd_type), 0,
+ "Specify TURN password type."
+ },
+ {
+ "turn_passwd", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_media_config, turn_passwd), 0,
+ "Specify the TURN password."
+ },
+
+ {NULL} /* Sentinel */
+};
+
+
+static PyObject *PyObj_pjsua_media_config_new(PyTypeObject *type,
+ PyObject *args,
+ PyObject *kwds)
+{
+ PyObj_pjsua_media_config *self;
+
+ PJ_UNUSED_ARG(args);
+ PJ_UNUSED_ARG(kwds);
+
+ self = (PyObj_pjsua_media_config*)type->tp_alloc(type, 0);
+ if (self != NULL) {
+ self->turn_server = PyString_FromString("");
+ self->turn_realm = PyString_FromString("");
+ self->turn_username = PyString_FromString("");
+ self->turn_passwd = PyString_FromString("");
+ }
+
+ return (PyObject *)self;
+}
+
+static void PyObj_pjsua_media_config_delete(PyObj_pjsua_media_config * self)
+{
+ Py_XDECREF(self->turn_server);
+ Py_XDECREF(self->turn_realm);
+ Py_XDECREF(self->turn_username);
+ Py_XDECREF(self->turn_passwd);
+ self->ob_type->tp_free((PyObject*)self);
+}
+
+static void PyObj_pjsua_media_config_import(PyObj_pjsua_media_config *obj,
+ const pjsua_media_config *cfg)
+{
+ obj->clock_rate = cfg->clock_rate;
+ obj->snd_clock_rate = cfg->snd_clock_rate;
+ obj->channel_count = cfg->channel_count;
+ obj->audio_frame_ptime = cfg->audio_frame_ptime;
+ obj->snd_auto_close_time= cfg->snd_auto_close_time;
+ obj->max_media_ports = cfg->max_media_ports;
+ obj->has_ioqueue = cfg->has_ioqueue;
+ obj->thread_cnt = cfg->thread_cnt;
+ obj->quality = cfg->quality;
+ obj->ptime = cfg->ptime;
+ obj->no_vad = cfg->no_vad;
+ obj->ilbc_mode = cfg->ilbc_mode;
+ obj->jb_min = cfg->jb_min_pre;
+ obj->jb_max = cfg->jb_max;
+ obj->tx_drop_pct = cfg->tx_drop_pct;
+ obj->rx_drop_pct = cfg->rx_drop_pct;
+ obj->ec_options = cfg->ec_options;
+ obj->ec_tail_len = cfg->ec_tail_len;
+ obj->enable_ice = cfg->enable_ice;
+ obj->enable_turn = cfg->enable_turn;
+ Py_XDECREF(obj->turn_server);
+ obj->turn_server = PyString_FromPJ(&cfg->turn_server);
+ obj->turn_conn_type = cfg->turn_conn_type;
+ if (cfg->turn_auth_cred.type == PJ_STUN_AUTH_CRED_STATIC) {
+ const pj_stun_auth_cred *cred = &cfg->turn_auth_cred;
+
+ Py_XDECREF(obj->turn_realm);
+ obj->turn_realm = PyString_FromPJ(&cred->data.static_cred.realm);
+ Py_XDECREF(obj->turn_username);
+ obj->turn_username = PyString_FromPJ(&cred->data.static_cred.username);
+ obj->turn_passwd_type = cred->data.static_cred.data_type;
+ Py_XDECREF(obj->turn_passwd);
+ obj->turn_passwd = PyString_FromPJ(&cred->data.static_cred.data);
+ } else {
+ Py_XDECREF(obj->turn_realm);
+ obj->turn_realm = PyString_FromString("");
+ Py_XDECREF(obj->turn_username);
+ obj->turn_username = PyString_FromString("");
+ obj->turn_passwd_type = 0;
+ Py_XDECREF(obj->turn_passwd);
+ obj->turn_passwd = PyString_FromString("");
+ }
+}
+
+static void PyObj_pjsua_media_config_export(pjsua_media_config *cfg,
+ const PyObj_pjsua_media_config *obj)
+{
+ cfg->clock_rate = obj->clock_rate;
+ cfg->snd_clock_rate = obj->snd_clock_rate;
+ cfg->channel_count = obj->channel_count;
+ cfg->audio_frame_ptime = obj->audio_frame_ptime;
+ cfg->snd_auto_close_time=obj->snd_auto_close_time;
+ cfg->max_media_ports = obj->max_media_ports;
+ cfg->has_ioqueue = obj->has_ioqueue;
+ cfg->thread_cnt = obj->thread_cnt;
+ cfg->quality = obj->quality;
+ cfg->ptime = obj->ptime;
+ cfg->no_vad = obj->no_vad;
+ cfg->jb_min_pre = obj->jb_min;
+ cfg->jb_max = obj->jb_max;
+ cfg->ilbc_mode = obj->ilbc_mode;
+ cfg->tx_drop_pct = obj->tx_drop_pct;
+ cfg->rx_drop_pct = obj->rx_drop_pct;
+ cfg->ec_options = obj->ec_options;
+ cfg->ec_tail_len = obj->ec_tail_len;
+ cfg->enable_ice = obj->enable_ice;
+ cfg->enable_turn = obj->enable_turn;
+
+ if (cfg->enable_turn) {
+ cfg->turn_server = PyString_ToPJ(obj->turn_server);
+ cfg->turn_conn_type = obj->turn_conn_type;
+ cfg->turn_auth_cred.type = PJ_STUN_AUTH_CRED_STATIC;
+ cfg->turn_auth_cred.data.static_cred.realm = PyString_ToPJ(obj->turn_realm);
+ cfg->turn_auth_cred.data.static_cred.username = PyString_ToPJ(obj->turn_username);
+ cfg->turn_auth_cred.data.static_cred.data_type= obj->turn_passwd_type;
+ cfg->turn_auth_cred.data.static_cred.data = PyString_ToPJ(obj->turn_passwd);
+ }
+}
+
+
+/*
+ * PyTyp_pjsua_media_config
+ */
+static PyTypeObject PyTyp_pjsua_media_config =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "_pjsua.Media_Config", /*tp_name*/
+ sizeof(PyObj_pjsua_media_config),/*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor)PyObj_pjsua_media_config_delete,/*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "Media Config objects", /*tp_doc*/
+ 0, /*tp_traverse*/
+ 0, /*tp_clear*/
+ 0, /*tp_richcompare*/
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ PyObj_pjsua_media_config_members, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ PyObj_pjsua_media_config_new, /* tp_new */
+};
+
+
+//////////////////////////////////////////////////////////////////////////////
+/*
+ * PyObj_pjsua_config
+ * attribute list for config object
+ */
+typedef struct
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+ unsigned max_calls;
+ unsigned thread_cnt;
+ PyObject *outbound_proxy;
+ PyObject *stun_domain;
+ PyObject *stun_host;
+ PyListObject *nameserver;
+ PyObj_pjsua_callback *cb;
+ PyObject *user_agent;
+} PyObj_pjsua_config;
+
+
+static void PyObj_pjsua_config_delete(PyObj_pjsua_config* self)
+{
+ Py_XDECREF(self->outbound_proxy);
+ Py_XDECREF(self->stun_domain);
+ Py_XDECREF(self->stun_host);
+ Py_XDECREF(self->nameserver);
+ Py_XDECREF(self->cb);
+ Py_XDECREF(self->user_agent);
+ self->ob_type->tp_free((PyObject*)self);
+}
+
+
+static void PyObj_pjsua_config_import(PyObj_pjsua_config *obj,
+ const pjsua_config *cfg)
+{
+ unsigned i;
+
+ obj->max_calls = cfg->max_calls;
+ obj->thread_cnt = cfg->thread_cnt;
+ Py_XDECREF(obj->outbound_proxy);
+ if (cfg->outbound_proxy_cnt)
+ obj->outbound_proxy = PyString_FromPJ(&cfg->outbound_proxy[0]);
+ else
+ obj->outbound_proxy = PyString_FromString("");
+
+ Py_XDECREF(obj->stun_domain);
+ obj->stun_domain = PyString_FromPJ(&cfg->stun_domain);
+ Py_XDECREF(obj->stun_host);
+ obj->stun_host = PyString_FromPJ(&cfg->stun_host);
+ Py_XDECREF(obj->nameserver);
+ obj->nameserver = (PyListObject *)PyList_New(0);
+ for (i=0; i<cfg->nameserver_count; ++i) {
+ PyObject * str;
+ str = PyString_FromPJ(&cfg->nameserver[i]);
+ PyList_Append((PyObject *)obj->nameserver, str);
+ }
+ Py_XDECREF(obj->user_agent);
+ obj->user_agent = PyString_FromPJ(&cfg->user_agent);
+}
+
+
+static void PyObj_pjsua_config_export(pjsua_config *cfg,
+ PyObj_pjsua_config *obj)
+{
+ unsigned i;
+
+ cfg->max_calls = obj->max_calls;
+ cfg->thread_cnt = obj->thread_cnt;
+ if (PyString_Size(obj->outbound_proxy) > 0) {
+ cfg->outbound_proxy_cnt = 1;
+ cfg->outbound_proxy[0] = PyString_ToPJ(obj->outbound_proxy);
+ } else {
+ cfg->outbound_proxy_cnt = 0;
+ }
+ cfg->nameserver_count = PyList_Size((PyObject*)obj->nameserver);
+ if (cfg->nameserver_count > PJ_ARRAY_SIZE(cfg->nameserver))
+ cfg->nameserver_count = PJ_ARRAY_SIZE(cfg->nameserver);
+ for (i = 0; i < cfg->nameserver_count; i++) {
+ PyObject *item = PyList_GetItem((PyObject *)obj->nameserver,i);
+ cfg->nameserver[i] = PyString_ToPJ(item);
+ }
+ cfg->stun_domain = PyString_ToPJ(obj->stun_domain);
+ cfg->stun_host = PyString_ToPJ(obj->stun_host);
+ cfg->user_agent = PyString_ToPJ(obj->user_agent);
+
+}
+
+
+static PyObject *PyObj_pjsua_config_new(PyTypeObject *type,
+ PyObject *args,
+ PyObject *kwds)
+{
+ PyObj_pjsua_config *self;
+
+ PJ_UNUSED_ARG(args);
+ PJ_UNUSED_ARG(kwds);
+
+ self = (PyObj_pjsua_config *)type->tp_alloc(type, 0);
+ if (self != NULL) {
+ self->user_agent = PyString_FromString("");
+ self->outbound_proxy = PyString_FromString("");
+ self->stun_domain = PyString_FromString("");
+ self->stun_host = PyString_FromString("");
+ self->cb = (PyObj_pjsua_callback *)
+ PyType_GenericNew(&PyTyp_pjsua_callback, NULL, NULL);
+ }
+ return (PyObject *)self;
+}
+
+
+/*
+ * PyObj_pjsua_config_members
+ * attribute list accessible from Python/C
+ */
+static PyMemberDef PyObj_pjsua_config_members[] =
+{
+ {
+ "max_calls", T_INT,
+ offsetof(PyObj_pjsua_config, max_calls), 0,
+ "Maximum calls to support (default: 4) "
+ },
+ {
+ "thread_cnt", T_INT,
+ offsetof(PyObj_pjsua_config, thread_cnt), 0,
+ "Number of worker threads. Normally application will want to have at "
+ "least one worker thread, unless when it wants to poll the library "
+ "periodically, which in this case the worker thread can be set to "
+ "zero."
+ },
+ {
+ "outbound_proxy", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_config, outbound_proxy), 0,
+ "SIP URL of the outbound proxy (optional)"
+ },
+ {
+ "stun_domain", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_config, stun_domain), 0,
+ "Domain of the STUN server (optional). STUN server will be resolved "
+ "using DNS SRV resolution only when nameserver is configured. "
+ "Alternatively, if DNS SRV resolution for STUN is not desired, "
+ "application can specify the STUN server hostname or IP address "
+ "in stun_host attribute."
+ },
+ {
+ "stun_host", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_config, stun_host), 0,
+ "Hostname or IP address of the STUN server (optional)."
+ },
+ {
+ "nameserver", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_config, nameserver), 0,
+ "IP address of the nameserver."
+ },
+ {
+ "cb", T_OBJECT_EX, offsetof(PyObj_pjsua_config, cb), 0,
+ "Application callback."
+ },
+ {
+ "user_agent", T_OBJECT_EX, offsetof(PyObj_pjsua_config, user_agent), 0,
+ "User agent string (default empty)"
+ },
+ {NULL} /* Sentinel */
+};
+
+
+/*
+ * PyTyp_pjsua_config
+ * type wrapper for config class
+ */
+static PyTypeObject PyTyp_pjsua_config =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "_pjsua.Config", /*tp_name*/
+ sizeof(PyObj_pjsua_config),/*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor)PyObj_pjsua_config_delete,/*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "Config object", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ PyObj_pjsua_config_members,/* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ PyObj_pjsua_config_new, /* tp_new */
+
+};
+
+//////////////////////////////////////////////////////////////////////////////
+/*
+ * PyObj_pjsua_logging_config
+ * configuration class for logging_config object
+ */
+typedef struct
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+ int msg_logging;
+ unsigned level;
+ unsigned console_level;
+ unsigned decor;
+ PyObject *log_filename;
+ PyObject *cb;
+} PyObj_pjsua_logging_config;
+
+
+/*
+ * PyObj_pjsua_logging_config_delete
+ * deletes a logging config from memory
+ */
+static void PyObj_pjsua_logging_config_delete(PyObj_pjsua_logging_config* self)
+{
+ Py_XDECREF(self->log_filename);
+ Py_XDECREF(self->cb);
+ self->ob_type->tp_free((PyObject*)self);
+}
+
+
+static void PyObj_pjsua_logging_config_import(PyObj_pjsua_logging_config *obj,
+ const pjsua_logging_config *cfg)
+{
+ obj->msg_logging = cfg->msg_logging;
+ obj->level = cfg->level;
+ obj->console_level = cfg->console_level;
+ obj->decor = cfg->decor;
+ Py_XDECREF(obj->log_filename);
+ obj->log_filename = PyString_FromPJ(&cfg->log_filename);
+}
+
+static void PyObj_pjsua_logging_config_export(pjsua_logging_config *cfg,
+ PyObj_pjsua_logging_config *obj)
+{
+ cfg->msg_logging = obj->msg_logging;
+ cfg->level = obj->level;
+ cfg->console_level = obj->console_level;
+ cfg->decor = obj->decor;
+ cfg->log_filename = PyString_ToPJ(obj->log_filename);
+}
+
+
+/*
+ * PyObj_pjsua_logging_config_new
+ * constructor for logging_config object
+ */
+static PyObject * PyObj_pjsua_logging_config_new(PyTypeObject *type,
+ PyObject *args,
+ PyObject *kwds)
+{
+ PyObj_pjsua_logging_config *self;
+
+ PJ_UNUSED_ARG(args);
+ PJ_UNUSED_ARG(kwds);
+
+ self = (PyObj_pjsua_logging_config *)type->tp_alloc(type, 0);
+ if (self != NULL) {
+ self->log_filename = PyString_FromString("");
+ self->cb = Py_BuildValue("");
+ }
+
+ return (PyObject *)self;
+}
+
+
+/*
+ * PyObj_pjsua_logging_config_members
+ */
+static PyMemberDef PyObj_pjsua_logging_config_members[] =
+{
+ {
+ "msg_logging", T_INT,
+ offsetof(PyObj_pjsua_logging_config, msg_logging), 0,
+ "Log incoming and outgoing SIP message? Yes!"
+ },
+ {
+ "level", T_INT,
+ offsetof(PyObj_pjsua_logging_config, level), 0,
+ "Input verbosity level. Value 5 is reasonable."
+ },
+ {
+ "console_level", T_INT,
+ offsetof(PyObj_pjsua_logging_config, console_level),
+ 0, "Verbosity level for console. Value 4 is reasonable."
+ },
+ {
+ "decor", T_INT,
+ offsetof(PyObj_pjsua_logging_config, decor), 0,
+ "Log decoration"
+ },
+ {
+ "log_filename", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_logging_config, log_filename), 0,
+ "Optional log filename"
+ },
+ {
+ "cb", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_logging_config, cb), 0,
+ "Optional callback function to be called to write log to application "
+ "specific device. This function will be called forlog messages on "
+ "input verbosity level."
+ },
+ {NULL} /* Sentinel */
+};
+
+
+
+
+/*
+ * PyTyp_pjsua_logging_config
+ */
+static PyTypeObject PyTyp_pjsua_logging_config =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "_pjsua.Logging_Config", /*tp_name*/
+ sizeof(PyObj_pjsua_logging_config), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor)PyObj_pjsua_logging_config_delete,/*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "Logging Config objects", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ PyObj_pjsua_logging_config_members,/* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ PyObj_pjsua_logging_config_new, /* tp_new */
+
+};
+
+
+//////////////////////////////////////////////////////////////////////////////
+/*
+ * PyObj_pjsua_msg_data
+ * typewrapper for MessageData class
+ * !modified @ 061206
+ */
+typedef struct
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+ PyObject * hdr_list;
+ PyObject * content_type;
+ PyObject * msg_body;
+} PyObj_pjsua_msg_data;
+
+
+/*
+ * PyObj_pjsua_msg_data_delete
+ * deletes a msg_data
+ * !modified @ 061206
+ */
+static void PyObj_pjsua_msg_data_delete(PyObj_pjsua_msg_data* self)
+{
+ Py_XDECREF(self->hdr_list);
+ Py_XDECREF(self->content_type);
+ Py_XDECREF(self->msg_body);
+ self->ob_type->tp_free((PyObject*)self);
+}
+
+
+/*
+ * PyObj_pjsua_msg_data_new
+ * constructor for msg_data object
+ * !modified @ 061206
+ */
+static PyObject * PyObj_pjsua_msg_data_new(PyTypeObject *type,
+ PyObject *args,
+ PyObject *kwds)
+{
+ PyObj_pjsua_msg_data *self;
+
+ PJ_UNUSED_ARG(args);
+ PJ_UNUSED_ARG(kwds);
+
+ self = (PyObj_pjsua_msg_data *)type->tp_alloc(type, 0);
+ if (self != NULL) {
+ self->hdr_list = PyList_New(0);
+ self->content_type = PyString_FromString("");
+ self->msg_body = PyString_FromString("");
+ }
+
+ return (PyObject *)self;
+}
+
+
+/*
+ * PyObj_pjsua_msg_data_members
+ * !modified @ 061206
+ */
+static PyMemberDef PyObj_pjsua_msg_data_members[] =
+{
+ {
+ "hdr_list", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_msg_data, hdr_list), 0,
+ "Additional message headers as linked list of strings."
+ },
+ {
+ "content_type", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_msg_data, content_type), 0,
+ "MIME type of optional message body."
+ },
+ {
+ "msg_body", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_msg_data, msg_body), 0,
+ "Optional message body."
+ },
+ {NULL} /* Sentinel */
+};
+
+
+/*
+ * PyTyp_pjsua_msg_data
+ */
+static PyTypeObject PyTyp_pjsua_msg_data =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "_pjsua.Msg_Data", /*tp_name*/
+ sizeof(PyObj_pjsua_msg_data), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor)PyObj_pjsua_msg_data_delete,/*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "msg_data objects", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ PyObj_pjsua_msg_data_members, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ PyObj_pjsua_msg_data_new, /* tp_new */
+
+};
+
+
+//////////////////////////////////////////////////////////////////////////////
+/*
+ * PyObj_pjsua_transport_config
+ * Transport configuration for creating UDP transports for both SIP
+ * and media.
+ */
+typedef struct
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+ unsigned port;
+ PyObject *public_addr;
+ PyObject *bound_addr;
+} PyObj_pjsua_transport_config;
+
+
+/*
+ * PyObj_pjsua_transport_config_delete
+ * deletes a transport config from memory
+ */
+static void PyObj_pjsua_transport_config_delete(PyObj_pjsua_transport_config* self)
+{
+ Py_XDECREF(self->public_addr);
+ Py_XDECREF(self->bound_addr);
+ self->ob_type->tp_free((PyObject*)self);
+}
+
+
+static void PyObj_pjsua_transport_config_export(pjsua_transport_config *cfg,
+ PyObj_pjsua_transport_config *obj)
+{
+ pjsua_transport_config_default(cfg);
+ cfg->public_addr = PyString_ToPJ(obj->public_addr);
+ cfg->bound_addr = PyString_ToPJ(obj->bound_addr);
+ cfg->port = obj->port;
+
+}
+
+static void PyObj_pjsua_transport_config_import(PyObj_pjsua_transport_config *obj,
+ const pjsua_transport_config *cfg)
+{
+ Py_XDECREF(obj->public_addr);
+ obj->public_addr = PyString_FromPJ(&cfg->public_addr);
+
+ Py_XDECREF(obj->bound_addr);
+ obj->bound_addr = PyString_FromPJ(&cfg->bound_addr);
+
+ obj->port = cfg->port;
+}
+
+
+/*
+ * PyObj_pjsua_transport_config_new
+ * constructor for transport_config object
+ */
+static PyObject * PyObj_pjsua_transport_config_new(PyTypeObject *type,
+ PyObject *args,
+ PyObject *kwds)
+{
+ PyObj_pjsua_transport_config *self;
+
+ PJ_UNUSED_ARG(args);
+ PJ_UNUSED_ARG(kwds);
+
+ self = (PyObj_pjsua_transport_config *)type->tp_alloc(type, 0);
+ if (self != NULL) {
+ self->public_addr = PyString_FromString("");
+ self->bound_addr = PyString_FromString("");
+ }
+
+ return (PyObject *)self;
+}
+
+
+/*
+ * PyObj_pjsua_transport_config_members
+ */
+static PyMemberDef PyObj_pjsua_transport_config_members[] =
+{
+ {
+ "port", T_INT,
+ offsetof(PyObj_pjsua_transport_config, port), 0,
+ "UDP port number to bind locally. This setting MUST be specified "
+ "even when default port is desired. If the value is zero, the "
+ "transport will be bound to any available port, and application "
+ "can query the port by querying the transport info."
+ },
+ {
+ "public_addr", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_transport_config, public_addr), 0,
+ "Optional address to advertise as the address of this transport. "
+ "Application can specify any address or hostname for this field, "
+ "for example it can point to one of the interface address in the "
+ "system, or it can point to the public address of a NAT router "
+ "where port mappings have been configured for the application."
+ },
+ {
+ "bound_addr", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_transport_config, bound_addr), 0,
+ "Optional address where the socket should be bound to. This option "
+ "SHOULD only be used to selectively bind the socket to particular "
+ "interface (instead of 0.0.0.0), and SHOULD NOT be used to set the "
+ "published address of a transport (the public_addr field should be "
+ "used for that purpose)."
+ },
+ {NULL} /* Sentinel */
+};
+
+
+
+
+/*
+ * PyTyp_pjsua_transport_config
+ */
+static PyTypeObject PyTyp_pjsua_transport_config =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "_pjsua.Transport_Config", /*tp_name*/
+ sizeof(PyObj_pjsua_transport_config), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor)PyObj_pjsua_transport_config_delete,/*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "Transport setting", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ PyObj_pjsua_transport_config_members,/* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ PyObj_pjsua_transport_config_new,/* tp_new */
+};
+
+
+//////////////////////////////////////////////////////////////////////////////
+/*
+ * PyObj_pjsua_transport_info
+ * Transport info
+ */
+typedef struct
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+ int id;
+ int type;
+ PyObject *type_name;
+ PyObject *info;
+ unsigned flag;
+ PyObject *addr;
+ unsigned port;
+ unsigned usage_count;
+} PyObj_pjsua_transport_info;
+
+
+/*
+ * PyObj_pjsua_transport_info_delete
+ * deletes a transport info from memory
+ */
+static void PyObj_pjsua_transport_info_delete(PyObj_pjsua_transport_info* self)
+{
+ Py_XDECREF(self->type_name);
+ Py_XDECREF(self->info);
+ Py_XDECREF(self->addr);
+ self->ob_type->tp_free((PyObject*)self);
+}
+
+
+static void PyObj_pjsua_transport_info_import(PyObj_pjsua_transport_info *obj,
+ const pjsua_transport_info *info)
+{
+ obj->id = info->id;
+ obj->type = info->type;
+ obj->type_name = PyString_FromPJ(&info->type_name);
+ obj->info = PyString_FromPJ(&info->info);
+ obj->flag = info->flag;
+ obj->addr = PyString_FromPJ(&info->local_name.host);
+ obj->port = info->local_name.port;
+ obj->usage_count= info->usage_count;
+}
+
+/*
+ * PyObj_pjsua_transport_info_new
+ * constructor for transport_info object
+ */
+static PyObject * PyObj_pjsua_transport_info_new(PyTypeObject *type,
+ PyObject *args,
+ PyObject *kwds)
+{
+ PyObj_pjsua_transport_info *self;
+
+ PJ_UNUSED_ARG(args);
+ PJ_UNUSED_ARG(kwds);
+
+ self = (PyObj_pjsua_transport_info *)type->tp_alloc(type, 0);
+ if (self != NULL)
+ {
+ self->type_name = PyString_FromString("");
+ self->info = PyString_FromString("");
+ self->addr = PyString_FromString("");
+ }
+
+ return (PyObject *)self;
+}
+
+
+/*
+ * PyObj_pjsua_transport_info_members
+ */
+static PyMemberDef PyObj_pjsua_transport_info_members[] =
+{
+ {
+ "id", T_INT,
+ offsetof(PyObj_pjsua_transport_info, id), 0,
+ "PJSUA transport identification."
+ },
+ {
+ "type", T_INT,
+ offsetof(PyObj_pjsua_transport_info, type), 0,
+ "Transport type."
+ },
+ {
+ "type_name", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_transport_info, type_name), 0,
+ "Transport type name."
+ },
+ {
+ "info", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_transport_info, info), 0,
+ "Transport string info/description."
+ },
+ {
+ "flag", T_INT,
+ offsetof(PyObj_pjsua_transport_info, flag), 0,
+ "Transport flag (see ##pjsip_transport_flags_e)."
+ },
+ {
+ "addr", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_transport_info, addr), 0,
+ "Published address (or transport address name)."
+ },
+ {
+ "port", T_INT,
+ offsetof(PyObj_pjsua_transport_info, port), 0,
+ "Published port number."
+ },
+ {
+ "usage_count", T_INT,
+ offsetof(PyObj_pjsua_transport_info, usage_count), 0,
+ "Current number of objects currently referencing this transport."
+ },
+ {NULL} /* Sentinel */
+};
+
+
+/*
+ * PyTyp_pjsua_transport_info
+ */
+static PyTypeObject PyTyp_pjsua_transport_info =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "_pjsua.Transport_Info", /*tp_name*/
+ sizeof(PyObj_pjsua_transport_info), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor)PyObj_pjsua_transport_info_delete,/*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "Transport Info objects", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ PyObj_pjsua_transport_info_members, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ PyObj_pjsua_transport_info_new, /* tp_new */
+
+};
+
+
+//////////////////////////////////////////////////////////////////////////////
+
+/*
+ * PyObj_pjsua_acc_config
+ * Acc Config
+ */
+typedef struct
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+ int priority;
+ PyObject *id;
+ PyObject *reg_uri;
+ int publish_enabled;
+ int mwi_enabled;
+ PyObject *force_contact;
+ PyListObject *proxy;
+ unsigned reg_timeout;
+ unsigned reg_delay_before_refresh;
+ PyListObject *cred_info;
+ int transport_id;
+ int auth_initial_send;
+ PyObject *auth_initial_algorithm;
+ PyObject *pidf_tuple_id;
+ PyObject *contact_params;
+ PyObject *contact_uri_params;
+ int require_100rel;
+ int use_timer;
+ unsigned timer_se;
+ unsigned timer_min_se;
+ int allow_contact_rewrite;
+ int ka_interval;
+ PyObject *ka_data;
+ unsigned use_srtp;
+ unsigned srtp_secure_signaling;
+} PyObj_pjsua_acc_config;
+
+
+/*
+ * PyObj_pjsua_acc_config_delete
+ * deletes a acc_config from memory
+ */
+static void PyObj_pjsua_acc_config_delete(PyObj_pjsua_acc_config* self)
+{
+ Py_XDECREF(self->id);
+ Py_XDECREF(self->reg_uri);
+ Py_XDECREF(self->force_contact);
+ Py_XDECREF(self->proxy);
+ Py_XDECREF(self->cred_info);
+ Py_XDECREF(self->auth_initial_algorithm);
+ Py_XDECREF(self->pidf_tuple_id);
+ Py_XDECREF(self->contact_params);
+ Py_XDECREF(self->contact_uri_params);
+ Py_XDECREF(self->ka_data);
+ self->ob_type->tp_free((PyObject*)self);
+}
+
+
+static void PyObj_pjsua_acc_config_import(PyObj_pjsua_acc_config *obj,
+ const pjsua_acc_config *cfg)
+{
+ unsigned i;
+
+ obj->priority = cfg->priority;
+ Py_XDECREF(obj->id);
+ obj->id = PyString_FromPJ(&cfg->id);
+ Py_XDECREF(obj->reg_uri);
+ obj->reg_uri = PyString_FromPJ(&cfg->reg_uri);
+ obj->publish_enabled = cfg->publish_enabled;
+ obj->mwi_enabled = cfg->mwi_enabled;
+ Py_XDECREF(obj->force_contact);
+ obj->force_contact = PyString_FromPJ(&cfg->force_contact);
+ Py_XDECREF(obj->proxy);
+ obj->proxy = (PyListObject *)PyList_New(0);
+ for (i=0; i<cfg->proxy_cnt; ++i) {
+ PyObject * str;
+ str = PyString_FromPJ(&cfg->proxy[i]);
+ PyList_Append((PyObject *)obj->proxy, str);
+ }
+
+ obj->reg_timeout = cfg->reg_timeout;
+ obj->reg_delay_before_refresh = cfg->reg_delay_before_refresh;
+
+ Py_XDECREF(obj->cred_info);
+ obj->cred_info = (PyListObject *)PyList_New(0);
+ for (i=0; i<cfg->cred_count; ++i) {
+ PyObj_pjsip_cred_info * ci;
+
+ ci = (PyObj_pjsip_cred_info *)
+ PyObj_pjsip_cred_info_new(&PyTyp_pjsip_cred_info,NULL,NULL);
+ PyObj_pjsip_cred_info_import(ci, &cfg->cred_info[i]);
+ PyList_Append((PyObject *)obj->cred_info, (PyObject *)ci);
+ }
+
+ obj->transport_id = cfg->transport_id;
+
+ obj->auth_initial_send = cfg->auth_pref.initial_auth;
+ Py_XDECREF(obj->auth_initial_algorithm);
+ obj->auth_initial_algorithm = PyString_FromPJ(&cfg->auth_pref.algorithm);
+ Py_XDECREF(obj->pidf_tuple_id);
+ obj->pidf_tuple_id = PyString_FromPJ(&cfg->pidf_tuple_id);
+ Py_XDECREF(obj->contact_params);
+ obj->contact_params = PyString_FromPJ(&cfg->contact_params);
+ Py_XDECREF(obj->contact_uri_params);
+ obj->contact_uri_params = PyString_FromPJ(&cfg->contact_uri_params);
+ obj->require_100rel = cfg->require_100rel;
+ obj->use_timer = cfg->use_timer;
+ obj->timer_se = cfg->timer_setting.sess_expires;
+ obj->timer_min_se = cfg->timer_setting.min_se;
+ obj->allow_contact_rewrite = cfg->allow_contact_rewrite;
+ obj->ka_interval = cfg->ka_interval;
+ Py_XDECREF(obj->ka_data);
+ obj->ka_data = PyString_FromPJ(&cfg->ka_data);
+ obj->use_srtp = cfg->use_srtp;
+ obj->srtp_secure_signaling = cfg->srtp_secure_signaling;
+}
+
+static void PyObj_pjsua_acc_config_export(pjsua_acc_config *cfg,
+ PyObj_pjsua_acc_config *obj)
+{
+ unsigned i;
+
+ cfg->priority = obj->priority;
+ cfg->id = PyString_ToPJ(obj->id);
+ cfg->reg_uri = PyString_ToPJ(obj->reg_uri);
+ cfg->publish_enabled = obj->publish_enabled;
+ cfg->mwi_enabled = obj->mwi_enabled;
+ cfg->force_contact = PyString_ToPJ(obj->force_contact);
+
+ cfg->proxy_cnt = PyList_Size((PyObject*)obj->proxy);
+ if (cfg->proxy_cnt > PJ_ARRAY_SIZE(cfg->proxy))
+ cfg->proxy_cnt = PJ_ARRAY_SIZE(cfg->proxy);
+ for (i = 0; i < cfg->proxy_cnt; i++) {
+ PyObject *item = PyList_GetItem((PyObject *)obj->proxy, i);
+ cfg->proxy[i] = PyString_ToPJ(item);
+ }
+
+ cfg->reg_timeout = obj->reg_timeout;
+ cfg->reg_delay_before_refresh = obj->reg_delay_before_refresh;
+
+ cfg->cred_count = PyList_Size((PyObject*)obj->cred_info);
+ if (cfg->cred_count > PJ_ARRAY_SIZE(cfg->cred_info))
+ cfg->cred_count = PJ_ARRAY_SIZE(cfg->cred_info);
+ for (i = 0; i < cfg->cred_count; i++) {
+ PyObj_pjsip_cred_info *ci;
+ ci = (PyObj_pjsip_cred_info*)
+ PyList_GetItem((PyObject *)obj->cred_info, i);
+ PyObj_pjsip_cred_info_export(&cfg->cred_info[i], ci);
+ }
+
+ cfg->transport_id = obj->transport_id;
+ cfg->auth_pref.initial_auth = obj->auth_initial_send;
+ cfg->auth_pref.algorithm = PyString_ToPJ(obj->auth_initial_algorithm);
+ cfg->pidf_tuple_id = PyString_ToPJ(obj->pidf_tuple_id);
+ cfg->contact_params = PyString_ToPJ(obj->contact_params);
+ cfg->contact_uri_params = PyString_ToPJ(obj->contact_uri_params);
+ cfg->require_100rel = obj->require_100rel;
+ cfg->use_timer = obj->use_timer;
+ cfg->timer_setting.sess_expires = obj->timer_se;
+ cfg->timer_setting.min_se = obj->timer_min_se;
+ cfg->allow_contact_rewrite = obj->allow_contact_rewrite;
+ cfg->ka_interval = obj->ka_interval;
+ cfg->ka_data = PyString_ToPJ(obj->ka_data);
+ cfg->use_srtp = obj->use_srtp;
+ cfg->srtp_secure_signaling = obj->srtp_secure_signaling;
+}
+
+
+/*
+ * PyObj_pjsua_acc_config_new
+ * constructor for acc_config object
+ */
+static PyObject * PyObj_pjsua_acc_config_new(PyTypeObject *type,
+ PyObject *args,
+ PyObject *kwds)
+{
+ PyObj_pjsua_acc_config *self;
+
+ PJ_UNUSED_ARG(args);
+ PJ_UNUSED_ARG(kwds);
+
+ self = (PyObj_pjsua_acc_config *)type->tp_alloc(type, 0);
+ if (self != NULL) {
+ self->id = PyString_FromString("");
+ self->reg_uri = PyString_FromString("");
+ self->force_contact = PyString_FromString("");
+ self->proxy = (PyListObject *)PyList_New(0);
+ self->cred_info = (PyListObject *)PyList_New(0);
+ self->auth_initial_algorithm = PyString_FromString("");
+ self->pidf_tuple_id = PyString_FromString("");
+ self->contact_params = PyString_FromString("");
+ self->contact_uri_params = PyString_FromString("");
+ self->ka_data = PyString_FromString("");
+ }
+
+ return (PyObject *)self;
+}
+
+
+
+/*
+ * PyObj_pjsua_acc_config_members
+ */
+static PyMemberDef PyObj_pjsua_acc_config_members[] =
+{
+ {
+ "priority", T_INT, offsetof(PyObj_pjsua_acc_config, priority), 0,
+ "Account priority, which is used to control the order of matching "
+ "incoming/outgoing requests. The higher the number means the higher "
+ "the priority is, and the account will be matched first. "
+ },
+ {
+ "id", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_acc_config, id), 0,
+ "The full SIP URL for the account. "
+ "The value can take name address or URL format, "
+ "and will look something like 'sip:account@serviceprovider'. "
+ "This field is mandatory."
+ },
+ {
+ "reg_uri", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_acc_config, reg_uri), 0,
+ "This is the URL to be put in the request URI for the registration, "
+ "and will look something like 'sip:serviceprovider'. "
+ "This field should be specified if registration is desired. "
+ "If the value is empty, no account registration will be performed. "
+ },
+ {
+ "publish_enabled", T_INT,
+ offsetof(PyObj_pjsua_acc_config, publish_enabled), 0,
+ "Publish presence? "
+ },
+ {
+ "mwi_enabled", T_INT,
+ offsetof(PyObj_pjsua_acc_config, mwi_enabled), 0,
+ "Enable MWI subscription "
+ },
+ {
+ "force_contact", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_acc_config, force_contact), 0,
+ "Optional URI to be put as Contact for this account. "
+ "It is recommended that this field is left empty, "
+ "so that the value will be calculated automatically "
+ "based on the transport address. "
+ },
+ {
+ "proxy", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_acc_config, proxy), 0,
+ "Optional URI of the proxies to be visited for all outgoing requests "
+ "that are using this account (REGISTER, INVITE, etc). Application need "
+ "to specify these proxies if the service provider requires "
+ "that requests destined towards its network should go through certain "
+ "proxies first (for example, border controllers)."
+ },
+ {
+ "reg_timeout", T_INT,
+ offsetof(PyObj_pjsua_acc_config, reg_timeout), 0,
+ "Optional interval for registration, in seconds. "
+ "If the value is zero, default interval will be used "
+ "(PJSUA_REG_INTERVAL, 55 seconds). "
+ },
+ {
+ "reg_delay_before_refresh", T_INT,
+ offsetof(PyObj_pjsua_acc_config, reg_delay_before_refresh), 0,
+ "Specify the number of seconds to refresh the client registration"
+ "before the registration expires."
+ "(PJSIP_REGISTER_CLIENT_DELAY_BEFORE_REFRESH, 5 seconds). "
+ },
+ {
+ "cred_info", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_acc_config, cred_info), 0,
+ "Array of credentials. If registration is desired, normally there "
+ "should be at least one credential specified, to successfully "
+ "authenticate against the service provider. More credentials can "
+ "be specified, for example when the requests are expected to be "
+ "challenged by the proxies in the route set."
+ },
+ {
+ "transport_id", T_INT,
+ offsetof(PyObj_pjsua_acc_config, transport_id), 0,
+ "Optionally bind this account to specific transport. This normally is"
+ " not a good idea, as account should be able to send requests using"
+ " any available transports according to the destination. But some"
+ " application may want to have explicit control over the transport to"
+ " use, so in that case it can set this field."
+ },
+ {
+ "auth_initial_send", T_INT,
+ offsetof(PyObj_pjsua_acc_config, auth_initial_send), 0,
+ "Send empty initial authorization header."
+ },
+ {
+ "auth_initial_algorithm", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_acc_config, auth_initial_algorithm), 0,
+ "Specify algorithm in empty initial authorization header."
+ },
+ {
+ "pidf_tuple_id", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_acc_config, pidf_tuple_id), 0,
+ "PIDF tuple id."
+ },
+ {
+ "contact_params", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_acc_config, contact_params), 0,
+ "Additional parameters for Contact header."
+ },
+ {
+ "contact_uri_params", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_acc_config, contact_uri_params), 0,
+ "Additional parameters for Contact URI."
+ },
+ {
+ "require_100rel", T_INT,
+ offsetof(PyObj_pjsua_acc_config, require_100rel), 0,
+ "Require reliable provisional response."
+ },
+ {
+ "use_timer", T_INT,
+ offsetof(PyObj_pjsua_acc_config, use_timer), 0,
+ "Use SIP session timers? (default=1)"
+ "0:inactive, 1:optional, 2:mandatory, 3:always"
+ },
+ {
+ "timer_se", T_INT,
+ offsetof(PyObj_pjsua_acc_config, timer_se), 0,
+ "Session timer expiration period, in seconds."
+ },
+ {
+ "timer_min_se", T_INT,
+ offsetof(PyObj_pjsua_acc_config, timer_min_se), 0,
+ "Session timer minimum expiration period, in seconds."
+ },
+ {
+ "allow_contact_rewrite", T_INT,
+ offsetof(PyObj_pjsua_acc_config, allow_contact_rewrite), 0,
+ "Re-REGISTER if behind symmetric NAT."
+ },
+ {
+ "ka_interval", T_INT,
+ offsetof(PyObj_pjsua_acc_config, ka_interval), 0,
+ "Keep-alive interval."
+ },
+ {
+ "ka_data", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_acc_config, ka_data), 0,
+ "Keep-alive data."
+ },
+ {
+ "use_srtp", T_INT,
+ offsetof(PyObj_pjsua_acc_config, use_srtp), 0,
+ "Specify SRTP usage."
+ },
+ {
+ "srtp_secure_signaling", T_INT,
+ offsetof(PyObj_pjsua_acc_config, srtp_secure_signaling), 0,
+ "Specify if SRTP requires secure signaling to be used."
+ },
+
+ {NULL} /* Sentinel */
+};
+
+
+
+
+/*
+ * PyTyp_pjsua_acc_config
+ */
+static PyTypeObject PyTyp_pjsua_acc_config =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "_pjsua.Acc_Config", /*tp_name*/
+ sizeof(PyObj_pjsua_acc_config), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor)PyObj_pjsua_acc_config_delete,/*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "Account settings", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ PyObj_pjsua_acc_config_members, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ PyObj_pjsua_acc_config_new, /* tp_new */
+
+};
+
+
+//////////////////////////////////////////////////////////////////////////////
+/*
+ * PyObj_pjsua_acc_info
+ * Acc Info
+ */
+typedef struct
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+ int id;
+ int is_default;
+ PyObject *acc_uri;
+ int has_registration;
+ int expires;
+ int status;
+ PyObject *status_text;
+ int online_status;
+ PyObject *online_status_text;
+} PyObj_pjsua_acc_info;
+
+
+/*
+ * PyObj_pjsua_acc_info_delete
+ * deletes a acc_info from memory
+ */
+static void PyObj_pjsua_acc_info_delete(PyObj_pjsua_acc_info* self)
+{
+ Py_XDECREF(self->acc_uri);
+ Py_XDECREF(self->status_text);
+ Py_XDECREF(self->online_status_text);
+ self->ob_type->tp_free((PyObject*)self);
+}
+
+
+static void PyObj_pjsua_acc_info_import(PyObj_pjsua_acc_info *obj,
+ const pjsua_acc_info *info)
+{
+ obj->id = info->id;
+ obj->is_default = info->is_default;
+ Py_XDECREF(obj->acc_uri);
+ obj->acc_uri = PyString_FromPJ(&info->acc_uri);
+ obj->has_registration = info->has_registration;
+ obj->expires = info->expires;
+ obj->status = info->status;
+ Py_XDECREF(obj->status_text);
+ obj->status_text= PyString_FromPJ(&info->status_text);
+ obj->online_status = info->online_status;
+ Py_XDECREF(obj->online_status_text);
+ obj->online_status_text = PyString_FromPJ(&info->online_status_text);
+}
+
+
+/*
+ * PyObj_pjsua_acc_info_new
+ * constructor for acc_info object
+ */
+static PyObject * PyObj_pjsua_acc_info_new(PyTypeObject *type,
+ PyObject *args,
+ PyObject *kwds)
+{
+ PyObj_pjsua_acc_info *self;
+
+ PJ_UNUSED_ARG(args);
+ PJ_UNUSED_ARG(kwds);
+
+ self = (PyObj_pjsua_acc_info *)type->tp_alloc(type, 0);
+ if (self != NULL) {
+ self->acc_uri = PyString_FromString("");
+ self->status_text = PyString_FromString("");
+ self->online_status_text = PyString_FromString("");
+ }
+
+ return (PyObject *)self;
+}
+
+/*
+ * acc_info_members
+ */
+static PyMemberDef acc_info_members[] =
+{
+ {
+ "id", T_INT,
+ offsetof(PyObj_pjsua_acc_info, id), 0,
+ "The account ID."
+ },
+ {
+ "is_default", T_INT,
+ offsetof(PyObj_pjsua_acc_info, is_default), 0,
+ "Flag to indicate whether this is the default account. "
+ },
+ {
+ "acc_uri", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_acc_info, acc_uri), 0,
+ "Account URI"
+ },
+ {
+ "has_registration", T_INT,
+ offsetof(PyObj_pjsua_acc_info, has_registration), 0,
+ "Flag to tell whether this account has registration setting "
+ "(reg_uri is not empty)."
+ },
+ {
+ "expires", T_INT,
+ offsetof(PyObj_pjsua_acc_info, expires), 0,
+ "An up to date expiration interval for account registration session."
+ },
+ {
+ "status", T_INT,
+ offsetof(PyObj_pjsua_acc_info, status), 0,
+ "Last registration status code. If status code is zero, "
+ "the account is currently not registered. Any other value indicates "
+ "the SIP status code of the registration. "
+ },
+ {
+ "status_text", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_acc_info, status_text), 0,
+ "String describing the registration status."
+ },
+ {
+ "online_status", T_INT,
+ offsetof(PyObj_pjsua_acc_info, online_status), 0,
+ "Presence online status for this account. "
+ },
+ {
+ "online_status_text", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_acc_info, online_status_text), 0,
+ "Presence online status text."
+ },
+ {NULL} /* Sentinel */
+};
+
+
+
+
+/*
+ * PyTyp_pjsua_acc_info
+ */
+static PyTypeObject PyTyp_pjsua_acc_info =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "_pjsua.Acc_Info", /*tp_name*/
+ sizeof(PyObj_pjsua_acc_info), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor)PyObj_pjsua_acc_info_delete,/*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "Account info", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ NULL, /* tp_methods */
+ acc_info_members, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ PyObj_pjsua_acc_info_new, /* tp_new */
+
+};
+
+
+//////////////////////////////////////////////////////////////////////////////
+
+/*
+ * PyObj_pjsua_buddy_config
+ * Buddy Config
+ */
+typedef struct
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+ PyObject *uri;
+ int subscribe;
+} PyObj_pjsua_buddy_config;
+
+
+/*
+ * PyObj_pjsua_buddy_config_delete
+ * deletes a buddy_config from memory
+ */
+static void PyObj_pjsua_buddy_config_delete(PyObj_pjsua_buddy_config* self)
+{
+ Py_XDECREF(self->uri);
+ self->ob_type->tp_free((PyObject*)self);
+}
+
+
+static void PyObj_pjsua_buddy_config_import(PyObj_pjsua_buddy_config *obj,
+ const pjsua_buddy_config *cfg)
+{
+ Py_XDECREF(obj->uri);
+ obj->uri = PyString_FromPJ(&cfg->uri);
+ obj->subscribe = cfg->subscribe;
+}
+
+
+static void PyObj_pjsua_buddy_config_export(pjsua_buddy_config *cfg,
+ PyObj_pjsua_buddy_config *obj)
+{
+ cfg->uri = PyString_ToPJ(obj->uri);
+ cfg->subscribe = obj->subscribe;
+ cfg->user_data = NULL;
+}
+
+
+/*
+ * PyObj_pjsua_buddy_config_new
+ * constructor for buddy_config object
+ */
+static PyObject *PyObj_pjsua_buddy_config_new(PyTypeObject *type,
+ PyObject *args,
+ PyObject *kwds)
+{
+ PyObj_pjsua_buddy_config *self;
+
+ PJ_UNUSED_ARG(args);
+ PJ_UNUSED_ARG(kwds);
+
+ self = (PyObj_pjsua_buddy_config *)type->tp_alloc(type, 0);
+ if (self != NULL) {
+ self->uri = PyString_FromString("");
+ }
+ return (PyObject *)self;
+}
+
+/*
+ * PyObj_pjsua_buddy_config_members
+ */
+static PyMemberDef PyObj_pjsua_buddy_config_members[] =
+{
+
+ {
+ "uri", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_buddy_config, uri), 0,
+ "TBuddy URL or name address."
+ },
+
+ {
+ "subscribe", T_INT,
+ offsetof(PyObj_pjsua_buddy_config, subscribe), 0,
+ "Specify whether presence subscription should start immediately. "
+ },
+
+ {NULL} /* Sentinel */
+};
+
+
+
+
+/*
+ * PyTyp_pjsua_buddy_config
+ */
+static PyTypeObject PyTyp_pjsua_buddy_config =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "_pjsua.Buddy_Config", /*tp_name*/
+ sizeof(PyObj_pjsua_buddy_config),/*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor)PyObj_pjsua_buddy_config_delete,/*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "Buddy config", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ PyObj_pjsua_buddy_config_members,/* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ PyObj_pjsua_buddy_config_new, /* tp_new */
+
+};
+
+//////////////////////////////////////////////////////////////////////////////
+/*
+ * PyObj_pjsua_buddy_info
+ * Buddy Info
+ */
+typedef struct
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+ int id;
+ PyObject *uri;
+ PyObject *contact;
+ int status;
+ PyObject *status_text;
+ int monitor_pres;
+ int activity;
+ int sub_state;
+ PyObject *sub_term_reason;
+} PyObj_pjsua_buddy_info;
+
+
+/*
+ * PyObj_pjsua_buddy_info_delete
+ * deletes a buddy_info from memory
+ * !modified @ 071206
+ */
+static void PyObj_pjsua_buddy_info_delete(PyObj_pjsua_buddy_info* self)
+{
+ Py_XDECREF(self->uri);
+ Py_XDECREF(self->contact);
+ Py_XDECREF(self->status_text);
+ Py_XDECREF(self->sub_term_reason);
+
+ self->ob_type->tp_free((PyObject*)self);
+}
+
+
+static void PyObj_pjsua_buddy_info_import(PyObj_pjsua_buddy_info *obj,
+ const pjsua_buddy_info *info)
+{
+ obj->id = info->id;
+ Py_XDECREF(obj->uri);
+ obj->uri = PyString_FromPJ(&info->uri);
+ Py_XDECREF(obj->contact);
+ obj->contact = PyString_FromPJ(&info->contact);
+ obj->status = info->status;
+ Py_XDECREF(obj->status_text);
+ obj->status_text = PyString_FromPJ(&info->status_text);
+ obj->monitor_pres = info->monitor_pres;
+ obj->activity = info->rpid.activity;
+ obj->sub_state = info->sub_state;
+ Py_XDECREF(obj->sub_term_reason);
+ obj->sub_term_reason = PyString_FromPJ(&info->sub_term_reason);
+}
+
+
+/*
+ * PyObj_pjsua_buddy_info_new
+ * constructor for buddy_info object
+ * !modified @ 071206
+ */
+static PyObject * PyObj_pjsua_buddy_info_new(PyTypeObject *type,
+ PyObject *args,
+ PyObject *kwds)
+{
+ PyObj_pjsua_buddy_info *self;
+
+ PJ_UNUSED_ARG(args);
+ PJ_UNUSED_ARG(kwds);
+
+ self = (PyObj_pjsua_buddy_info *)type->tp_alloc(type, 0);
+ if (self != NULL) {
+ self->uri = PyString_FromString("");
+ self->contact = PyString_FromString("");
+ self->status_text = PyString_FromString("");
+ self->sub_term_reason = PyString_FromString("");
+ }
+ return (PyObject *)self;
+}
+
+/*
+ * PyObj_pjsua_buddy_info_members
+ * !modified @ 071206
+ */
+static PyMemberDef PyObj_pjsua_buddy_info_members[] =
+{
+ {
+ "id", T_INT,
+ offsetof(PyObj_pjsua_buddy_info, id), 0,
+ "The buddy ID."
+ },
+ {
+ "uri", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_buddy_info, uri), 0,
+ "The full URI of the buddy, as specified in the configuration. "
+ },
+ {
+ "contact", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_buddy_info, contact), 0,
+ "Buddy's Contact, only available when presence subscription "
+ "has been established to the buddy."
+ },
+ {
+ "status", T_INT,
+ offsetof(PyObj_pjsua_buddy_info, status), 0,
+ "Buddy's online status. "
+ },
+ {
+ "status_text", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_buddy_info, status_text), 0,
+ "Text to describe buddy's online status."
+ },
+ {
+ "monitor_pres", T_INT,
+ offsetof(PyObj_pjsua_buddy_info, monitor_pres), 0,
+ "Flag to indicate that we should monitor the presence information "
+ "for this buddy (normally yes, unless explicitly disabled). "
+ },
+ {
+ "activity", T_INT,
+ offsetof(PyObj_pjsua_buddy_info, activity), 0,
+ "Activity type. "
+ },
+ {
+ "sub_state", T_INT,
+ offsetof(PyObj_pjsua_buddy_info, sub_state), 0,
+ "Subscription state."
+ },
+ {
+ "sub_term_reason", T_INT,
+ offsetof(PyObj_pjsua_buddy_info, sub_term_reason), 0,
+ "Subscription termination reason."
+ },
+
+
+ {NULL} /* Sentinel */
+};
+
+
+
+
+/*
+ * PyTyp_pjsua_buddy_info
+ */
+static PyTypeObject PyTyp_pjsua_buddy_info =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "_pjsua.Buddy_Info", /*tp_name*/
+ sizeof(PyObj_pjsua_buddy_info), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor)PyObj_pjsua_buddy_info_delete,/*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "Buddy Info object", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ PyObj_pjsua_buddy_info_members, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ PyObj_pjsua_buddy_info_new, /* tp_new */
+
+};
+
+
+//////////////////////////////////////////////////////////////////////////////
+
+/*
+ * PyObj_pjsua_codec_info
+ * Codec Info
+ */
+typedef struct
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+
+ PyObject * codec_id;
+ pj_uint8_t priority;
+} PyObj_pjsua_codec_info;
+
+
+/*
+ * codec_info_dealloc
+ * deletes a codec_info from memory
+ */
+static void codec_info_dealloc(PyObj_pjsua_codec_info* self)
+{
+ Py_XDECREF(self->codec_id);
+ self->ob_type->tp_free((PyObject*)self);
+}
+
+
+/*
+ * codec_info_new
+ * constructor for codec_info object
+ */
+static PyObject * codec_info_new(PyTypeObject *type, PyObject *args,
+ PyObject *kwds)
+{
+ PyObj_pjsua_codec_info *self;
+
+ PJ_UNUSED_ARG(args);
+ PJ_UNUSED_ARG(kwds);
+
+ self = (PyObj_pjsua_codec_info *)type->tp_alloc(type, 0);
+ if (self != NULL) {
+ self->codec_id = PyString_FromString("");
+ }
+ return (PyObject *)self;
+}
+
+/*
+ * codec_info_members
+ * !modified @ 071206
+ */
+static PyMemberDef codec_info_members[] =
+{
+ {
+ "codec_id", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_codec_info, codec_id), 0,
+ "Codec unique identification."
+ },
+ {
+ "priority", T_INT,
+ offsetof(PyObj_pjsua_codec_info, priority), 0,
+ "Codec priority (integer 0-255)."
+ },
+
+ {NULL} /* Sentinel */
+};
+
+/*
+ * PyTyp_pjsua_codec_info
+ */
+static PyTypeObject PyTyp_pjsua_codec_info =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "_pjsua.Codec_Info", /*tp_name*/
+ sizeof(PyObj_pjsua_codec_info), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor)codec_info_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "Codec Info", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ codec_info_members, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ codec_info_new, /* tp_new */
+
+};
+
+
+//////////////////////////////////////////////////////////////////////////////
+
+/*
+ * PyObj_pjsua_conf_port_info
+ * Conf Port Info
+ */
+typedef struct
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+
+ int slot_id;
+ PyObject *name;
+ unsigned clock_rate;
+ unsigned channel_count;
+ unsigned samples_per_frame;
+ unsigned bits_per_sample;
+ PyObject *listeners;
+
+} PyObj_pjsua_conf_port_info;
+
+
+/*
+ * conf_port_info_dealloc
+ * deletes a conf_port_info from memory
+ */
+static void conf_port_info_dealloc(PyObj_pjsua_conf_port_info* self)
+{
+ Py_XDECREF(self->name);
+ Py_XDECREF(self->listeners);
+ self->ob_type->tp_free((PyObject*)self);
+}
+
+
+/*
+ * conf_port_info_new
+ * constructor for conf_port_info object
+ */
+static PyObject * conf_port_info_new(PyTypeObject *type, PyObject *args,
+ PyObject *kwds)
+{
+ PyObj_pjsua_conf_port_info *self;
+
+ PJ_UNUSED_ARG(args);
+ PJ_UNUSED_ARG(kwds);
+
+ self = (PyObj_pjsua_conf_port_info *)type->tp_alloc(type, 0);
+ if (self != NULL) {
+ self->name = PyString_FromString("");
+ self->listeners = PyList_New(0);
+ }
+ return (PyObject *)self;
+}
+
+/*
+ * conf_port_info_members
+ */
+static PyMemberDef conf_port_info_members[] =
+{
+ {
+ "slot_id", T_INT,
+ offsetof(PyObj_pjsua_conf_port_info, slot_id), 0,
+ "Conference port number."
+ },
+ {
+ "name", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_conf_port_info, name), 0,
+ "Port name"
+ },
+ {
+ "clock_rate", T_INT,
+ offsetof(PyObj_pjsua_conf_port_info, clock_rate), 0,
+ "Clock rate"
+ },
+ {
+ "channel_count", T_INT,
+ offsetof(PyObj_pjsua_conf_port_info, channel_count), 0,
+ "Number of channels."
+ },
+ {
+ "samples_per_frame", T_INT,
+ offsetof(PyObj_pjsua_conf_port_info, samples_per_frame), 0,
+ "Samples per frame "
+ },
+ {
+ "bits_per_sample", T_INT,
+ offsetof(PyObj_pjsua_conf_port_info, bits_per_sample), 0,
+ "Bits per sample"
+ },
+ {
+ "listeners", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_conf_port_info, listeners), 0,
+ "Array of listeners (in other words, ports where this port "
+ "is transmitting to"
+ },
+
+ {NULL} /* Sentinel */
+};
+
+
+
+
+/*
+ * PyTyp_pjsua_conf_port_info
+ */
+static PyTypeObject PyTyp_pjsua_conf_port_info =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "_pjsua.Conf_Port_Info", /*tp_name*/
+ sizeof(PyObj_pjsua_conf_port_info), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor)conf_port_info_dealloc,/*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "Conf Port Info objects", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ conf_port_info_members, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ conf_port_info_new, /* tp_new */
+
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+/*
+ * PyObj_pjmedia_snd_dev_info
+ * PJMedia Snd Dev Info
+ */
+typedef struct
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+
+ unsigned input_count;
+ unsigned output_count;
+ unsigned default_samples_per_sec;
+ PyObject *name;
+
+} PyObj_pjmedia_snd_dev_info;
+
+/*
+ * pjmedia_snd_dev_info_dealloc
+ * deletes a pjmedia_snd_dev_info from memory
+ */
+static void pjmedia_snd_dev_info_dealloc(PyObj_pjmedia_snd_dev_info* self)
+{
+ Py_XDECREF(self->name);
+ self->ob_type->tp_free((PyObject*)self);
+}
+
+/*
+ * pjmedia_snd_dev_info_new
+ * constructor for pjmedia_snd_dev_info object
+ */
+static PyObject * pjmedia_snd_dev_info_new(PyTypeObject *type,
+ PyObject *args,
+ PyObject *kwds)
+{
+ PyObj_pjmedia_snd_dev_info *self;
+
+ PJ_UNUSED_ARG(args);
+ PJ_UNUSED_ARG(kwds);
+
+ self = (PyObj_pjmedia_snd_dev_info *)type->tp_alloc(type, 0);
+ if (self != NULL) {
+ self->name = PyString_FromString("");
+ }
+ return (PyObject *)self;
+}
+
+/*
+ * pjmedia_snd_dev_info_members
+ */
+static PyMemberDef pjmedia_snd_dev_info_members[] =
+{
+ {
+ "input_count", T_INT,
+ offsetof(PyObj_pjmedia_snd_dev_info, input_count), 0,
+ "Max number of input channels"
+ },
+ {
+ "output_count", T_INT,
+ offsetof(PyObj_pjmedia_snd_dev_info, output_count), 0,
+ "Max number of output channels"
+ },
+ {
+ "default_samples_per_sec", T_INT,
+ offsetof(PyObj_pjmedia_snd_dev_info, default_samples_per_sec), 0,
+ "Default sampling rate."
+ },
+ {
+ "name", T_OBJECT_EX,
+ offsetof(PyObj_pjmedia_snd_dev_info, name), 0,
+ "Device name"
+ },
+
+ {NULL} /* Sentinel */
+};
+
+
+/*
+ * PyTyp_pjmedia_snd_dev_info
+ */
+static PyTypeObject PyTyp_pjmedia_snd_dev_info =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "_pjsua.PJMedia_Snd_Dev_Info", /*tp_name*/
+ sizeof(PyObj_pjmedia_snd_dev_info), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor)pjmedia_snd_dev_info_dealloc,/*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "PJMedia Snd Dev Info object", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ pjmedia_snd_dev_info_members, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ pjmedia_snd_dev_info_new, /* tp_new */
+
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+/*
+ * PyObj_pjmedia_codec_param_info
+ * PJMedia Codec Param Info
+ */
+typedef struct
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+
+ unsigned clock_rate;
+ unsigned channel_cnt;
+ pj_uint32_t avg_bps;
+ pj_uint16_t frm_ptime;
+ pj_uint8_t pcm_bits_per_sample;
+ pj_uint8_t pt;
+
+} PyObj_pjmedia_codec_param_info;
+
+
+
+/*
+ * pjmedia_codec_param_info_members
+ */
+static PyMemberDef pjmedia_codec_param_info_members[] =
+{
+ {
+ "clock_rate", T_INT,
+ offsetof(PyObj_pjmedia_codec_param_info, clock_rate), 0,
+ "Sampling rate in Hz"
+ },
+ {
+ "channel_cnt", T_INT,
+ offsetof(PyObj_pjmedia_codec_param_info, channel_cnt), 0,
+ "Channel count"
+ },
+ {
+ "avg_bps", T_INT,
+ offsetof(PyObj_pjmedia_codec_param_info, avg_bps), 0,
+ "Average bandwidth in bits/sec"
+ },
+ {
+ "frm_ptime", T_INT,
+ offsetof(PyObj_pjmedia_codec_param_info, frm_ptime), 0,
+ "Base frame ptime in msec."
+ },
+ {
+ "pcm_bits_per_sample", T_INT,
+ offsetof(PyObj_pjmedia_codec_param_info, pcm_bits_per_sample), 0,
+ "Bits/sample in the PCM side"
+ },
+ {
+ "pt", T_INT,
+ offsetof(PyObj_pjmedia_codec_param_info, pt), 0,
+ "Payload type"
+ },
+
+ {NULL} /* Sentinel */
+};
+
+
+/*
+ * PyTyp_pjmedia_codec_param_info
+ */
+static PyTypeObject PyTyp_pjmedia_codec_param_info =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "_pjsua.PJMedia_Codec_Param_Info", /*tp_name*/
+ sizeof(PyObj_pjmedia_codec_param_info), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ 0, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "PJMedia Codec Param Info objects",/* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ pjmedia_codec_param_info_members,/* tp_members */
+};
+
+
+//////////////////////////////////////////////////////////////////////////////
+
+/*
+ * PyObj_pjmedia_codec_param_setting
+ * PJMedia Codec Param Setting
+ */
+typedef struct
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+ pj_uint8_t frm_per_pkt;
+ unsigned vad;
+ unsigned cng;
+ unsigned penh;
+ unsigned plc;
+#if 0
+ pj_uint8_t enc_fmtp_mode;
+ pj_uint8_t dec_fmtp_mode;
+#endif
+
+} PyObj_pjmedia_codec_param_setting;
+
+
+
+/*
+ * pjmedia_codec_param_setting_members
+ */
+static PyMemberDef pjmedia_codec_param_setting_members[] =
+{
+ {
+ "frm_per_pkt", T_INT,
+ offsetof(PyObj_pjmedia_codec_param_setting, frm_per_pkt), 0,
+ "Number of frames per packet"
+ },
+ {
+ "vad", T_INT,
+ offsetof(PyObj_pjmedia_codec_param_setting, vad), 0,
+ "Voice Activity Detector"
+ },
+ {
+ "cng", T_INT,
+ offsetof(PyObj_pjmedia_codec_param_setting, cng), 0,
+ "Comfort Noise Generator"
+ },
+ {
+ "penh", T_INT,
+ offsetof(PyObj_pjmedia_codec_param_setting, penh), 0,
+ "Perceptual Enhancement"
+ },
+ {
+ "plc", T_INT,
+ offsetof(PyObj_pjmedia_codec_param_setting, plc), 0,
+ "Packet loss concealment"
+ },
+#if 0 // no longer valid with latest modification in codec
+ {
+ "enc_fmtp_mode", T_INT,
+ offsetof(PyObj_pjmedia_codec_param_setting, enc_fmtp_mode), 0,
+ "Mode param in fmtp (def:0)"
+ },
+ {
+ "dec_fmtp_mode", T_INT,
+ offsetof(PyObj_pjmedia_codec_param_setting, dec_fmtp_mode), 0,
+ "Mode param in fmtp (def:0)"
+ },
+#endif
+
+ {NULL} /* Sentinel */
+};
+
+
+/*
+ * PyTyp_pjmedia_codec_param_setting
+ */
+static PyTypeObject PyTyp_pjmedia_codec_param_setting =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "_pjsua.PJMedia_Codec_Param_Setting",/*tp_name*/
+ sizeof(PyObj_pjmedia_codec_param_setting), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ 0, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "PJMedia Codec Param Setting", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ pjmedia_codec_param_setting_members,/* tp_members */
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+
+/*
+ * PyObj_pjmedia_codec_param
+ * PJMedia Codec Param
+ */
+typedef struct
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+
+ PyObj_pjmedia_codec_param_info * info;
+ PyObj_pjmedia_codec_param_setting * setting;
+
+} PyObj_pjmedia_codec_param;
+
+/*
+ * pjmedia_codec_param_dealloc
+ * deletes a pjmedia_codec_param from memory
+ */
+static void pjmedia_codec_param_dealloc(PyObj_pjmedia_codec_param* self)
+{
+ Py_XDECREF(self->info);
+ Py_XDECREF(self->setting);
+ self->ob_type->tp_free((PyObject*)self);
+}
+
+/*
+ * pjmedia_codec_param_new
+ * constructor for pjmedia_codec_param object
+ */
+static PyObject * pjmedia_codec_param_new(PyTypeObject *type,
+ PyObject *args,
+ PyObject *kwds)
+{
+ PyObj_pjmedia_codec_param *self;
+
+ PJ_UNUSED_ARG(args);
+ PJ_UNUSED_ARG(kwds);
+
+ self = (PyObj_pjmedia_codec_param *)type->tp_alloc(type, 0);
+ if (self != NULL) {
+ self->info = (PyObj_pjmedia_codec_param_info *)
+ PyType_GenericNew(&PyTyp_pjmedia_codec_param_info,
+ NULL, NULL);
+ self->setting = (PyObj_pjmedia_codec_param_setting *)
+ PyType_GenericNew(&PyTyp_pjmedia_codec_param_setting,
+ NULL, NULL);
+ }
+ return (PyObject *)self;
+}
+
+/*
+ * pjmedia_codec_param_members
+ */
+static PyMemberDef pjmedia_codec_param_members[] =
+{
+
+ {
+ "info", T_OBJECT_EX,
+ offsetof(PyObj_pjmedia_codec_param, info), 0,
+ "The 'info' part of codec param describes the capability of the codec,"
+ " and the value should NOT be changed by application."
+ },
+ {
+ "setting", T_OBJECT_EX,
+ offsetof(PyObj_pjmedia_codec_param, setting), 0,
+ "The 'setting' part of codec param describes various settings to be "
+ "applied to the codec. When the codec param is retrieved from the "
+ "codec or codec factory, the values of these will be filled by "
+ "the capability of the codec. Any features that are supported by "
+ "the codec (e.g. vad or plc) will be turned on, so that application "
+ "can query which capabilities are supported by the codec. "
+ "Application may change the settings here before instantiating "
+ "the codec/stream."
+ },
+
+ {NULL} /* Sentinel */
+};
+
+/*
+ * PyTyp_pjmedia_codec_param
+ */
+static PyTypeObject PyTyp_pjmedia_codec_param =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "_pjsua.PJMedia_Codec_Param", /*tp_name*/
+ sizeof(PyObj_pjmedia_codec_param),/*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor)pjmedia_codec_param_dealloc,/*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "PJMedia Codec Param", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ pjmedia_codec_param_members, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ pjmedia_codec_param_new, /* tp_new */
+
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+/*
+ * PyObj_pjsua_call_info
+ * Call Info
+ */
+typedef struct
+{
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+
+ int id;
+ int role;
+ int acc_id;
+ PyObject *local_info;
+ PyObject *local_contact;
+ PyObject *remote_info;
+ PyObject *remote_contact;
+ PyObject *call_id;
+ int state;
+ PyObject *state_text;
+ int last_status;
+ PyObject *last_status_text;
+ int media_status;
+ int media_dir;
+ int conf_slot;
+ int connect_duration;
+ int total_duration;
+
+} PyObj_pjsua_call_info;
+
+
+/*
+ * call_info_dealloc
+ * deletes a call_info from memory
+ */
+static void call_info_dealloc(PyObj_pjsua_call_info* self)
+{
+ Py_XDECREF(self->local_info);
+ Py_XDECREF(self->local_contact);
+ Py_XDECREF(self->remote_info);
+ Py_XDECREF(self->remote_contact);
+ Py_XDECREF(self->call_id);
+ Py_XDECREF(self->state_text);
+ Py_XDECREF(self->last_status_text);
+ self->ob_type->tp_free((PyObject*)self);
+}
+
+
+/*
+ * call_info_new
+ * constructor for call_info object
+ */
+static PyObject * call_info_new(PyTypeObject *type, PyObject *args,
+ PyObject *kwds)
+{
+ PyObj_pjsua_call_info *self;
+
+ PJ_UNUSED_ARG(args);
+ PJ_UNUSED_ARG(kwds);
+
+ self = (PyObj_pjsua_call_info *)type->tp_alloc(type, 0);
+ if (self != NULL) {
+ self->local_info = PyString_FromString("");
+ self->local_contact = PyString_FromString("");
+ self->remote_info = PyString_FromString("");
+ self->remote_contact = PyString_FromString("");
+ self->call_id = PyString_FromString("");
+ self->state_text = PyString_FromString("");
+ self->last_status_text = PyString_FromString("");
+ }
+ return (PyObject *)self;
+}
+
+/*
+ * call_info_members
+ */
+static PyMemberDef call_info_members[] =
+{
+ {
+ "id", T_INT,
+ offsetof(PyObj_pjsua_call_info, id), 0,
+ "Call identification"
+ },
+ {
+ "role", T_INT,
+ offsetof(PyObj_pjsua_call_info, role), 0,
+ "Initial call role (UAC == caller)"
+ },
+ {
+ "acc_id", T_INT,
+ offsetof(PyObj_pjsua_call_info, acc_id), 0,
+ "The account ID where this call belongs."
+ },
+ {
+ "local_info", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_call_info, local_info), 0,
+ "Local URI"
+ },
+ {
+ "local_contact", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_call_info, local_contact), 0,
+ "Local Contact"
+ },
+ {
+ "remote_info", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_call_info, remote_info), 0,
+ "Remote URI"
+ },
+ {
+ "remote_contact", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_call_info, remote_contact), 0,
+ "Remote Contact"
+ },
+ {
+ "call_id", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_call_info, call_id), 0,
+ "Dialog Call-ID string"
+ },
+ {
+ "state", T_INT,
+ offsetof(PyObj_pjsua_call_info, state), 0,
+ "Call state"
+ },
+ {
+ "state_text", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_call_info, state_text), 0,
+ "Text describing the state "
+ },
+ {
+ "last_status", T_INT,
+ offsetof(PyObj_pjsua_call_info, last_status), 0,
+ "Last status code heard, which can be used as cause code"
+ },
+ {
+ "last_status_text", T_OBJECT_EX,
+ offsetof(PyObj_pjsua_call_info, last_status_text), 0,
+ "The reason phrase describing the status."
+ },
+ {
+ "media_status", T_INT,
+ offsetof(PyObj_pjsua_call_info, media_status), 0,
+ "Call media status."
+ },
+ {
+ "media_dir", T_INT,
+ offsetof(PyObj_pjsua_call_info, media_dir), 0,
+ "Media direction"
+ },
+ {
+ "conf_slot", T_INT,
+ offsetof(PyObj_pjsua_call_info, conf_slot), 0,
+ "The conference port number for the call"
+ },
+ {
+ "connect_duration", T_INT,
+ offsetof(PyObj_pjsua_call_info, connect_duration), 0,
+ "Up-to-date call connected duration(zero when call is not established)"
+ },
+ {
+ "total_duration", T_INT,
+ offsetof(PyObj_pjsua_call_info, total_duration), 0,
+ "Total call duration, including set-up time"
+ },
+
+ {NULL} /* Sentinel */
+};
+
+
+
+
+/*
+ * PyTyp_pjsua_call_info
+ */
+static PyTypeObject PyTyp_pjsua_call_info =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "_pjsua.Call_Info", /*tp_name*/
+ sizeof(PyObj_pjsua_call_info), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor)call_info_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "Call Info", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ call_info_members, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ call_info_new, /* tp_new */
+
+};
+
+
+
+//////////////////////////////////////////////////////////////////////////////
+
+#endif /* __PY_PJSUA_H__ */
+
diff --git a/pjsip-apps/src/python/helper.mak b/pjsip-apps/src/python/helper.mak
new file mode 100644
index 0000000..b4acce6
--- /dev/null
+++ b/pjsip-apps/src/python/helper.mak
@@ -0,0 +1,17 @@
+include ../../../build.mak
+
+lib_dir:
+ @for token in `echo $(APP_LDFLAGS)`; do \
+ echo $$token | grep L | sed 's/-L//'; \
+ done
+
+inc_dir:
+ @for token in `echo $(APP_CFLAGS)`; do \
+ echo $$token | grep I | sed 's/-I//'; \
+ done
+
+libs:
+ @for token in `echo $(APP_LDLIBS)`; do \
+ echo $$token | grep \\-l | sed 's/-l//'; \
+ done
+
diff --git a/pjsip-apps/src/python/pjsua.py b/pjsip-apps/src/python/pjsua.py
new file mode 100644
index 0000000..183ce0e
--- /dev/null
+++ b/pjsip-apps/src/python/pjsua.py
@@ -0,0 +1,2862 @@
+# $Id: pjsua.py 2976 2009-10-29 08:16:46Z bennylp $
+#
+# Object oriented PJSUA wrapper.
+#
+# Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+
+"""Multimedia communication client library based on SIP protocol.
+
+This implements a fully featured multimedia communication client
+library based on PJSIP stack (http://www.pjsip.org)
+
+
+1. FEATURES
+
+ - Session Initiation Protocol (SIP) features:
+ - Basic registration and call
+ - Multiple accounts
+ - Call hold, attended and unattended call transfer
+ - Presence
+ - Instant messaging
+ - Multiple SIP accounts
+ - Media features:
+ - Audio
+ - Conferencing
+ - Narrowband and wideband
+ - Codecs: PCMA, PCMU, GSM, iLBC, Speex, G.722, L16
+ - RTP/RTCP
+ - Secure RTP (SRTP)
+ - WAV playback, recording, and playlist
+ - NAT traversal features
+ - Symmetric RTP
+ - STUN
+ - TURN
+ - ICE
+
+
+2. USING
+
+See http://www.pjsip.org/trac/wiki/Python_SIP_Tutorial for a more thorough
+tutorial. The paragraphs below explain basic tasks on using this module.
+
+
+"""
+import _pjsua
+import thread
+import threading
+import weakref
+import time
+
+class Error:
+ """Error exception class.
+
+ Member documentation:
+
+ op_name -- name of the operation that generated this error.
+ obj -- the object that generated this error.
+ err_code -- the error code.
+
+ """
+ op_name = ""
+ obj = None
+ err_code = -1
+ _err_msg = ""
+
+ def __init__(self, op_name, obj, err_code, err_msg=""):
+ self.op_name = op_name
+ self.obj = obj
+ self.err_code = err_code
+ self._err_msg = err_msg
+
+ def err_msg(self):
+ "Retrieve the description of the error."
+ if self._err_msg != "":
+ return self._err_msg
+ self._err_msg = Lib.strerror(self.err_code)
+ return self._err_msg
+
+ def __str__(self):
+ return "Object: " + str(self.obj) + ", operation=" + self.op_name + \
+ ", error=" + self.err_msg()
+
+#
+# Constants
+#
+
+class TransportType:
+ """SIP transport type constants.
+
+ Member documentation:
+ UNSPECIFIED -- transport type is unknown or unspecified
+ UDP -- UDP transport
+ TCP -- TCP transport
+ TLS -- TLS transport
+ IPV6 -- this is not a transport type but rather a flag
+ to select the IPv6 version of a transport
+ UDP_IPV6 -- IPv6 UDP transport
+ TCP_IPV6 -- IPv6 TCP transport
+ """
+ UNSPECIFIED = 0
+ UDP = 1
+ TCP = 2
+ TLS = 3
+ IPV6 = 128
+ UDP_IPV6 = UDP + IPV6
+ TCP_IPV6 = TCP + IPV6
+
+class TransportFlag:
+ """Transport flags to indicate the characteristics of the transport.
+
+ Member documentation:
+
+ RELIABLE -- transport is reliable.
+ SECURE -- transport is secure.
+ DATAGRAM -- transport is datagram based.
+
+ """
+ RELIABLE = 1
+ SECURE = 2
+ DATAGRAM = 4
+
+class CallRole:
+ """Call role constants.
+
+ Member documentation:
+
+ CALLER -- role is caller
+ CALLEE -- role is callee
+
+ """
+ CALLER = 0
+ CALLEE = 1
+
+class CallState:
+ """Call state constants.
+
+ Member documentation:
+
+ NULL -- call is not initialized.
+ CALLING -- initial INVITE is sent.
+ INCOMING -- initial INVITE is received.
+ EARLY -- provisional response has been sent or received.
+ CONNECTING -- 200/OK response has been sent or received.
+ CONFIRMED -- ACK has been sent or received.
+ DISCONNECTED -- call is disconnected.
+ """
+ NULL = 0
+ CALLING = 1
+ INCOMING = 2
+ EARLY = 3
+ CONNECTING = 4
+ CONFIRMED = 5
+ DISCONNECTED = 6
+
+
+class MediaState:
+ """Call media state constants.
+
+ Member documentation:
+
+ NULL -- media is not available.
+ ACTIVE -- media is active.
+ LOCAL_HOLD -- media is put on-hold by local party.
+ REMOTE_HOLD -- media is put on-hold by remote party.
+ ERROR -- media error (e.g. ICE negotiation failure).
+ """
+ NULL = 0
+ ACTIVE = 1
+ LOCAL_HOLD = 2
+ REMOTE_HOLD = 3
+ ERROR = 4
+
+
+class MediaDir:
+ """Media direction constants.
+
+ Member documentation:
+
+ NULL -- media is not active
+ ENCODING -- media is active in transmit/encoding direction only.
+ DECODING -- media is active in receive/decoding direction only
+ ENCODING_DECODING -- media is active in both directions.
+ """
+ NULL = 0
+ ENCODING = 1
+ DECODING = 2
+ ENCODING_DECODING = 3
+
+
+class PresenceActivity:
+ """Presence activities constants.
+
+ Member documentation:
+
+ UNKNOWN -- the person activity is unknown
+ AWAY -- the person is currently away
+ BUSY -- the person is currently engaging in other activity
+ """
+ UNKNOWN = 0
+ AWAY = 1
+ BUSY = 2
+
+
+class SubscriptionState:
+ """Presence subscription state constants.
+
+ """
+ NULL = 0
+ SENT = 1
+ ACCEPTED = 2
+ PENDING = 3
+ ACTIVE = 4
+ TERMINATED = 5
+ UNKNOWN = 6
+
+
+class TURNConnType:
+ """These constants specifies the connection type to TURN server.
+
+ Member documentation:
+ UDP -- use UDP transport.
+ TCP -- use TCP transport.
+ TLS -- use TLS transport.
+ """
+ UDP = 17
+ TCP = 6
+ TLS = 255
+
+
+class UAConfig:
+ """User agent configuration to be specified in Lib.init().
+
+ Member documentation:
+
+ max_calls -- maximum number of calls to be supported.
+ nameserver -- list of nameserver hostnames or IP addresses. Nameserver
+ must be configured if DNS SRV resolution is desired.
+ stun_domain -- if nameserver is configured, this can be used to query
+ the STUN server with DNS SRV.
+ stun_host -- the hostname or IP address of the STUN server. This will
+ also be used if DNS SRV resolution for stun_domain fails.
+ user_agent -- Optionally specify the user agent name.
+ """
+ max_calls = 4
+ nameserver = []
+ stun_domain = ""
+ stun_host = ""
+ user_agent = "pjsip python"
+
+ def _cvt_from_pjsua(self, cfg):
+ self.max_calls = cfg.max_calls
+ self.thread_cnt = cfg.thread_cnt
+ self.nameserver = cfg.nameserver
+ self.stun_domain = cfg.stun_domain
+ self.stun_host = cfg.stun_host
+ self.user_agent = cfg.user_agent
+
+ def _cvt_to_pjsua(self):
+ cfg = _pjsua.config_default()
+ cfg.max_calls = self.max_calls
+ cfg.thread_cnt = 0
+ cfg.nameserver = self.nameserver
+ cfg.stun_domain = self.stun_domain
+ cfg.stun_host = self.stun_host
+ cfg.user_agent = self.user_agent
+ return cfg
+
+
+class LogConfig:
+ """Logging configuration to be specified in Lib.init().
+
+ Member documentation:
+
+ msg_logging -- specify if SIP messages should be logged. Set to
+ True.
+ level -- specify the input verbosity level.
+ console_level -- specify the output verbosity level.
+ decor -- specify log decoration.
+ filename -- specify the log filename.
+ callback -- specify callback to be called to write the logging
+ messages. Sample function:
+
+ def log_cb(level, str, len):
+ print str,
+
+ """
+ msg_logging = True
+ level = 5
+ console_level = 5
+ decor = 0
+ filename = ""
+ callback = None
+
+ def __init__(self, level=-1, filename="", callback=None,
+ console_level=-1):
+ self._cvt_from_pjsua(_pjsua.logging_config_default())
+ if level != -1:
+ self.level = level
+ if filename != "":
+ self.filename = filename
+ if callback != None:
+ self.callback = callback
+ if console_level != -1:
+ self.console_level = console_level
+
+ def _cvt_from_pjsua(self, cfg):
+ self.msg_logging = cfg.msg_logging
+ self.level = cfg.level
+ self.console_level = cfg.console_level
+ self.decor = cfg.decor
+ self.filename = cfg.log_filename
+ self.callback = cfg.cb
+
+ def _cvt_to_pjsua(self):
+ cfg = _pjsua.logging_config_default()
+ cfg.msg_logging = self.msg_logging
+ cfg.level = self.level
+ cfg.console_level = self.console_level
+ cfg.decor = self.decor
+ cfg.log_filename = self.filename
+ cfg.cb = self.callback
+ return cfg
+
+
+class MediaConfig:
+ """Media configuration to be specified in Lib.init().
+
+ Member documentation:
+
+ clock_rate -- specify the core clock rate of the audio,
+ most notably the conference bridge.
+ snd_clock_rate -- optionally specify different clock rate for
+ the sound device.
+ snd_auto_close_time -- specify the duration in seconds when the
+ sound device should be closed after inactivity
+ period.
+ channel_count -- specify the number of channels to open the sound
+ device and the conference bridge.
+ audio_frame_ptime -- specify the length of audio frames in millisecond.
+ max_media_ports -- specify maximum number of audio ports to be
+ supported by the conference bridge.
+ quality -- specify the audio quality setting (1-10)
+ ptime -- specify the audio packet length of transmitted
+ RTP packet.
+ no_vad -- disable Voice Activity Detector (VAD) or Silence
+ Detector (SD)
+ ilbc_mode -- specify iLBC codec mode (must be 30 for now)
+ tx_drop_pct -- randomly drop transmitted RTP packets (for
+ simulation). Number is in percent.
+ rx_drop_pct -- randomly drop received RTP packets (for
+ simulation). Number is in percent.
+ ec_options -- Echo Canceller option (specify zero).
+ ec_tail_len -- specify Echo Canceller tail length in milliseconds.
+ Value zero will disable the echo canceller.
+ jb_min -- specify the minimum jitter buffer size in
+ milliseconds. Put -1 for default.
+ jb_max -- specify the maximum jitter buffer size in
+ milliseconds. Put -1 for default.
+ enable_ice -- enable Interactive Connectivity Establishment (ICE)
+ enable_turn -- enable TURN relay. TURN server settings must also
+ be configured.
+ turn_server -- specify the domain or hostname or IP address of
+ the TURN server, in "host[:port]" format.
+ turn_conn_type -- specify connection type to the TURN server, from
+ the TURNConnType constant.
+ turn_cred -- specify AuthCred for the TURN credential.
+ """
+ clock_rate = 16000
+ snd_clock_rate = 0
+ snd_auto_close_time = 5
+ channel_count = 1
+ audio_frame_ptime = 20
+ max_media_ports = 32
+ quality = 6
+ ptime = 0
+ no_vad = False
+ ilbc_mode = 30
+ tx_drop_pct = 0
+ rx_drop_pct = 0
+ ec_options = 0
+ ec_tail_len = 256
+ jb_min = -1
+ jb_max = -1
+ enable_ice = True
+ enable_turn = False
+ turn_server = ""
+ turn_conn_type = TURNConnType.UDP
+ turn_cred = None
+
+ def __init__(self):
+ default = _pjsua.media_config_default()
+ self._cvt_from_pjsua(default)
+
+ def _cvt_from_pjsua(self, cfg):
+ self.clock_rate = cfg.clock_rate
+ self.snd_clock_rate = cfg.snd_clock_rate
+ self.snd_auto_close_time = cfg.snd_auto_close_time
+ self.channel_count = cfg.channel_count
+ self.audio_frame_ptime = cfg.audio_frame_ptime
+ self.max_media_ports = cfg.max_media_ports
+ self.quality = cfg.quality
+ self.ptime = cfg.ptime
+ self.no_vad = cfg.no_vad
+ self.ilbc_mode = cfg.ilbc_mode
+ self.tx_drop_pct = cfg.tx_drop_pct
+ self.rx_drop_pct = cfg.rx_drop_pct
+ self.ec_options = cfg.ec_options
+ self.ec_tail_len = cfg.ec_tail_len
+ self.jb_min = cfg.jb_min
+ self.jb_max = cfg.jb_max
+ self.enable_ice = cfg.enable_ice
+ self.enable_turn = cfg.enable_turn
+ self.turn_server = cfg.turn_server
+ self.turn_conn_type = cfg.turn_conn_type
+ if cfg.turn_username:
+ self.turn_cred = AuthCred(cfg.turn_realm, cfg.turn_username,
+ cfg.turn_passwd, cfg.turn_passwd_type)
+ else:
+ self.turn_cred = None
+
+ def _cvt_to_pjsua(self):
+ cfg = _pjsua.media_config_default()
+ cfg.clock_rate = self.clock_rate
+ cfg.snd_clock_rate = self.snd_clock_rate
+ cfg.snd_auto_close_time = self.snd_auto_close_time
+ cfg.channel_count = self.channel_count
+ cfg.audio_frame_ptime = self.audio_frame_ptime
+ cfg.max_media_ports = self.max_media_ports
+ cfg.quality = self.quality
+ cfg.ptime = self.ptime
+ cfg.no_vad = self.no_vad
+ cfg.ilbc_mode = self.ilbc_mode
+ cfg.tx_drop_pct = self.tx_drop_pct
+ cfg.rx_drop_pct = self.rx_drop_pct
+ cfg.ec_options = self.ec_options
+ cfg.ec_tail_len = self.ec_tail_len
+ cfg.jb_min = self.jb_min
+ cfg.jb_max = self.jb_max
+ cfg.enable_ice = self.enable_ice
+ cfg.enable_turn = self.enable_turn
+ cfg.turn_server = self.turn_server
+ cfg.turn_conn_type = self.turn_conn_type
+ if self.turn_cred:
+ cfg.turn_realm = self.turn_cred.realm
+ cfg.turn_username = self.turn_cred.username
+ cfg.turn_passwd_type = self.turn_cred.passwd_type
+ cfg.turn_passwd = self.turn_cred.passwd
+ return cfg
+
+
+class TransportConfig:
+ """SIP transport configuration class.
+
+ Member configuration:
+
+ port -- port number.
+ bound_addr -- optionally specify the address to bind the socket to.
+ Default is empty to bind to INADDR_ANY.
+ public_addr -- optionally override the published address for this
+ transport. If empty, the default behavior is to get
+ the public address from STUN or from the selected
+ local interface. Format is "host:port".
+ """
+ port = 0
+ bound_addr = ""
+ public_addr = ""
+
+ def __init__(self, port=0,
+ bound_addr="", public_addr=""):
+ self.port = port
+ self.bound_addr = bound_addr
+ self.public_addr = public_addr
+
+ def _cvt_to_pjsua(self):
+ cfg = _pjsua.transport_config_default()
+ cfg.port = self.port
+ cfg.bound_addr = self.bound_addr
+ cfg.public_addr = self.public_addr
+ return cfg
+
+
+class TransportInfo:
+ """SIP transport info.
+
+ Member documentation:
+
+ type -- transport type, from TransportType constants.
+ description -- longer description for this transport.
+ is_reliable -- True if transport is reliable.
+ is_secure -- True if transport is secure.
+ is_datagram -- True if transport is datagram based.
+ host -- the IP address of this transport.
+ port -- the port number.
+ ref_cnt -- number of objects referencing this transport.
+ """
+ type = ""
+ description = ""
+ is_reliable = False
+ is_secure = False
+ is_datagram = False
+ host = ""
+ port = 0
+ ref_cnt = 0
+
+ def __init__(self, ti):
+ self.type = ti.type_name
+ self.description = ti.info
+ self.is_reliable = (ti.flag & TransportFlag.RELIABLE)
+ self.is_secure = (ti.flag & TransportFlag.SECURE)
+ self.is_datagram = (ti.flag & TransportFlag.DATAGRAM)
+ self.host = ti.addr
+ self.port = ti.port
+ self.ref_cnt = ti.usage_count
+
+
+class Transport:
+ "SIP transport class."
+ _id = -1
+ _lib = None
+ _obj_name = ""
+
+ def __init__(self, lib, id):
+ self._lib = weakref.proxy(lib)
+ self._id = id
+ self._obj_name = "{Transport " + self.info().description + "}"
+ _Trace((self, 'created'))
+
+ def __del__(self):
+ _Trace((self, 'destroyed'))
+
+ def __str__(self):
+ return self._obj_name
+
+ def info(self):
+ """Get TransportInfo.
+ """
+ lck = self._lib.auto_lock()
+ ti = _pjsua.transport_get_info(self._id)
+ if not ti:
+ self._lib._err_check("info()", self, -1, "Invalid transport")
+ return TransportInfo(ti)
+
+ def enable(self):
+ """Enable this transport."""
+ lck = self._lib.auto_lock()
+ err = _pjsua.transport_set_enable(self._id, True)
+ self._lib._err_check("enable()", self, err)
+
+ def disable(self):
+ """Disable this transport."""
+ lck = self._lib.auto_lock()
+ err = _pjsua.transport_set_enable(self._id, 0)
+ self._lib._err_check("disable()", self, err)
+
+ def close(self, force=False):
+ """Close and destroy this transport.
+
+ Keyword argument:
+ force -- force deletion of this transport (not recommended).
+ """
+ lck = self._lib.auto_lock()
+ err = _pjsua.transport_close(self._id, force)
+ self._lib._err_check("close()", self, err)
+
+
+class SIPUri:
+ """Helper class to parse the most important components of SIP URI.
+
+ Member documentation:
+
+ scheme -- URI scheme ("sip" or "sips")
+ user -- user part of the URI (may be empty)
+ host -- host name part
+ port -- optional port number (zero if port is not specified).
+ transport -- transport parameter, or empty if transport is not
+ specified.
+
+ """
+ scheme = ""
+ user = ""
+ host = ""
+ port = 0
+ transport = ""
+
+ def __init__(self, uri=None):
+ if uri:
+ self.decode(uri)
+
+ def decode(self, uri):
+ """Parse SIP URL.
+
+ Keyword argument:
+ uri -- the URI string.
+
+ """
+ self.scheme, self.user, self.host, self.port, self.transport = \
+ _pjsua.parse_simple_uri(uri)
+
+ def encode(self):
+ """Encode this object into SIP URI string.
+
+ Return:
+ URI string.
+
+ """
+ output = self.scheme + ":"
+ if self.user and len(self.user):
+ output = output + self.user + "@"
+ output = output + self.host
+ if self.port:
+ output = output + ":" + output(self.port)
+ if self.transport:
+ output = output + ";transport=" + self.transport
+ return output
+
+
+class AuthCred:
+ """Authentication credential for SIP or TURN account.
+
+ Member documentation:
+
+ scheme -- authentication scheme (default is "Digest")
+ realm -- realm
+ username -- username
+ passwd_type -- password encoding (zero for plain-text)
+ passwd -- the password
+ """
+ scheme = "Digest"
+ realm = "*"
+ username = ""
+ passwd_type = 0
+ passwd = ""
+
+ def __init__(self, realm, username, passwd, scheme="Digest", passwd_type=0):
+ self.scheme = scheme
+ self.realm = realm
+ self.username = username
+ self.passwd_type = passwd_type
+ self.passwd = passwd
+
+
+class AccountConfig:
+ """ This describes account configuration to create an account.
+
+ Member documentation:
+
+ priority -- account priority for matching incoming
+ messages.
+ id -- SIP URI of this account. This setting is
+ mandatory.
+ force_contact -- force to use this URI as Contact URI. Setting
+ this value is generally not recommended.
+ reg_uri -- specify the registrar URI. Mandatory if
+ registration is required.
+ reg_timeout -- specify the SIP registration refresh interval
+ in seconds.
+ require_100rel -- specify if reliable provisional response is
+ to be enforced (with Require header).
+ publish_enabled -- specify if PUBLISH should be used. When
+ enabled, the PUBLISH will be sent to the
+ registrar.
+ pidf_tuple_id -- optionally specify the tuple ID in outgoing
+ PIDF document.
+ proxy -- list of proxy URI.
+ auth_cred -- list of AuthCred containing credentials to
+ authenticate against the registrars and
+ the proxies.
+ auth_initial_send -- specify if empty Authorization header should be
+ sent. May be needed for IMS.
+ auth_initial_algorithm -- when auth_initial_send is enabled, optionally
+ specify the authentication algorithm to use.
+ Valid values are "md5", "akav1-md5", or
+ "akav2-md5".
+ transport_id -- optionally specify the transport ID to be used
+ by this account. Shouldn't be needed unless
+ for specific requirements (e.g. in multi-homed
+ scenario).
+ allow_contact_rewrite -- specify whether the account should learn its
+ Contact address from REGISTER response and
+ update the registration accordingly. Default is
+ True.
+ ka_interval -- specify the interval to send NAT keep-alive
+ packet.
+ ka_data -- specify the NAT keep-alive packet contents.
+ use_srtp -- specify the SRTP usage policy. Valid values
+ are: 0=disable, 1=optional, 2=mandatory.
+ Default is 0.
+ srtp_secure_signaling -- specify the signaling security level required
+ by SRTP. Valid values are: 0=no secure
+ transport is required, 1=hop-by-hop secure
+ transport such as TLS is required, 2=end-to-
+ end secure transport is required (i.e. "sips").
+ """
+ priority = 0
+ id = ""
+ force_contact = ""
+ reg_uri = ""
+ reg_timeout = 0
+ require_100rel = False
+ publish_enabled = False
+ pidf_tuple_id = ""
+ proxy = []
+ auth_cred = []
+ auth_initial_send = False
+ auth_initial_algorithm = ""
+ transport_id = -1
+ allow_contact_rewrite = True
+ ka_interval = 15
+ ka_data = "\r\n"
+ use_srtp = 0
+ srtp_secure_signaling = 1
+
+ def __init__(self, domain="", username="", password="",
+ display="", registrar="", proxy=""):
+ """
+ Construct account config. If domain argument is specified,
+ a typical configuration will be built.
+
+ Keyword arguments:
+ domain -- domain name of the server.
+ username -- user name.
+ password -- plain-text password.
+ display -- optional display name for the user name.
+ registrar -- the registrar URI. If domain name is specified
+ and this argument is empty, the registrar URI
+ will be constructed from the domain name.
+ proxy -- the proxy URI. If domain name is specified
+ and this argument is empty, the proxy URI
+ will be constructed from the domain name.
+
+ """
+ default = _pjsua.acc_config_default()
+ self._cvt_from_pjsua(default)
+ if domain!="":
+ self.build_config(domain, username, password,
+ display, registrar, proxy)
+
+ def build_config(self, domain, username, password, display="",
+ registrar="", proxy=""):
+ """
+ Construct account config. If domain argument is specified,
+ a typical configuration will be built.
+
+ Keyword arguments:
+ domain -- domain name of the server.
+ username -- user name.
+ password -- plain-text password.
+ display -- optional display name for the user name.
+ registrar -- the registrar URI. If domain name is specified
+ and this argument is empty, the registrar URI
+ will be constructed from the domain name.
+ proxy -- the proxy URI. If domain name is specified
+ and this argument is empty, the proxy URI
+ will be constructed from the domain name.
+
+ """
+ if display != "":
+ display = display + " "
+ userpart = username
+ if userpart != "":
+ userpart = userpart + "@"
+ self.id = display + "<sip:" + userpart + domain + ">"
+ self.reg_uri = registrar
+ if self.reg_uri == "":
+ self.reg_uri = "sip:" + domain
+ if proxy == "":
+ proxy = "sip:" + domain + ";lr"
+ if proxy.find(";lr") == -1:
+ proxy = proxy + ";lr"
+ self.proxy.append(proxy)
+ if username != "":
+ self.auth_cred.append(AuthCred("*", username, password))
+
+ def _cvt_from_pjsua(self, cfg):
+ self.priority = cfg.priority
+ self.id = cfg.id
+ self.force_contact = cfg.force_contact
+ self.reg_uri = cfg.reg_uri
+ self.reg_timeout = cfg.reg_timeout
+ self.require_100rel = cfg.require_100rel
+ self.publish_enabled = cfg.publish_enabled
+ self.pidf_tuple_id = cfg.pidf_tuple_id
+ self.proxy = cfg.proxy
+ for cred in cfg.cred_info:
+ self.auth_cred.append(AuthCred(cred.realm, cred.username,
+ cred.data, cred.scheme,
+ cred.data_type))
+ self.auth_initial_send = cfg.auth_initial_send
+ self.auth_initial_algorithm = cfg.auth_initial_algorithm
+ self.transport_id = cfg.transport_id
+ self.allow_contact_rewrite = cfg.allow_contact_rewrite
+ self.ka_interval = cfg.ka_interval
+ self.ka_data = cfg.ka_data
+ self.use_srtp = cfg.use_srtp
+ self.srtp_secure_signaling = cfg.srtp_secure_signaling
+
+ def _cvt_to_pjsua(self):
+ cfg = _pjsua.acc_config_default()
+ cfg.priority = self.priority
+ cfg.id = self.id
+ cfg.force_contact = self.force_contact
+ cfg.reg_uri = self.reg_uri
+ cfg.reg_timeout = self.reg_timeout
+ cfg.require_100rel = self.require_100rel
+ cfg.publish_enabled = self.publish_enabled
+ cfg.pidf_tuple_id = self.pidf_tuple_id
+ cfg.proxy = self.proxy
+ for cred in self.auth_cred:
+ c = _pjsua.Pjsip_Cred_Info()
+ c.realm = cred.realm
+ c.scheme = cred.scheme
+ c.username = cred.username
+ c.data_type = cred.passwd_type
+ c.data = cred.passwd
+ cfg.cred_info.append(c)
+ cfg.auth_initial_send = self.auth_initial_send
+ cfg.auth_initial_algorithm = self.auth_initial_algorithm
+ cfg.transport_id = self.transport_id
+ cfg.allow_contact_rewrite = self.allow_contact_rewrite
+ cfg.ka_interval = self.ka_interval
+ cfg.ka_data = self.ka_data
+ cfg.use_srtp = self.use_srtp
+ cfg.srtp_secure_signaling = self.srtp_secure_signaling
+ return cfg
+
+
+# Account information
+class AccountInfo:
+ """This describes Account info. Application retrives account info
+ with Account.info().
+
+ Member documentation:
+
+ is_default -- True if this is the default account.
+ uri -- the account URI.
+ reg_active -- True if registration is active for this account.
+ reg_expires -- contains the current registration expiration value,
+ in seconds.
+ reg_status -- the registration status. If the value is less than
+ 700, it specifies SIP status code. Value greater than
+ this specifies the error code.
+ reg_reason -- contains the registration status text (e.g. the
+ error message).
+ online_status -- the account's presence online status, True if it's
+ publishing itself as online.
+ online_text -- the account's presence status text.
+
+ """
+ is_default = False
+ uri = ""
+ reg_active = False
+ reg_expires = -1
+ reg_status = 0
+ reg_reason = ""
+ online_status = False
+ online_text = ""
+
+ def __init__(self, ai):
+ self.is_default = ai.is_default
+ self.uri = ai.acc_uri
+ self.reg_active = ai.has_registration
+ self.reg_expires = ai.expires
+ self.reg_status = ai.status
+ self.reg_reason = ai.status_text
+ self.online_status = ai.online_status
+ self.online_text = ai.online_status_text
+
+# Account callback
+class AccountCallback:
+ """Class to receive notifications on account's events.
+
+ Derive a class from this class and register it to the Account object
+ using Account.set_callback() to start receiving events from the Account
+ object.
+
+ Member documentation:
+
+ account -- the Account object.
+
+ """
+ account = None
+
+ def __init__(self, account=None):
+ self._set_account(account)
+
+ def __del__(self):
+ pass
+
+ def _set_account(self, account):
+ if account:
+ self.account = weakref.proxy(account)
+ else:
+ self.account = None
+
+ def on_reg_state(self):
+ """Notification that the registration status has changed.
+ """
+ pass
+
+ def on_incoming_call(self, call):
+ """Notification about incoming call.
+
+ Unless this callback is implemented, the default behavior is to
+ reject the call with default status code.
+
+ Keyword arguments:
+ call -- the new incoming call
+ """
+ call.hangup()
+
+ def on_incoming_subscribe(self, buddy, from_uri, contact_uri, pres_obj):
+ """Notification when incoming SUBSCRIBE request is received.
+
+ Application may use this callback to authorize the incoming
+ subscribe request (e.g. ask user permission if the request
+ should be granted)
+
+ Keyword arguments:
+ buddy -- The buddy object, if buddy is found. Otherwise
+ the value is None.
+ from_uri -- The URI string of the sender.
+ pres_obj -- Opaque presence subscription object, which is
+ needed by Account.pres_notify()
+
+ Return:
+ Tuple (code, reason), where:
+ code: The status code. If code is >= 300, the
+ request is rejected. If code is 200, the
+ request is accepted and NOTIFY will be sent
+ automatically. If code is 202, application
+ must accept or reject the request later with
+ Account.press_notify().
+ reason: Optional reason phrase, or None to use the
+ default reasoh phrase for the status code.
+ """
+ return (200, None)
+
+ def on_pager(self, from_uri, contact, mime_type, body):
+ """
+ Notification that incoming instant message is received on
+ this account.
+
+ Keyword arguments:
+ from_uri -- sender's URI
+ contact -- sender's Contact URI
+ mime_type -- MIME type of the instant message body
+ body -- the instant message body
+
+ """
+ pass
+
+ def on_pager_status(self, to_uri, body, im_id, code, reason):
+ """
+ Notification about the delivery status of previously sent
+ instant message.
+
+ Keyword arguments:
+ to_uri -- the destination URI of the message
+ body -- the message body
+ im_id -- message ID
+ code -- SIP status code
+ reason -- SIP reason phrase
+
+ """
+ pass
+
+ def on_typing(self, from_uri, contact, is_typing):
+ """
+ Notification that remote is typing or stop typing.
+
+ Keyword arguments:
+ buddy -- Buddy object for the sender, if found. Otherwise
+ this will be None
+ from_uri -- sender's URI of the indication
+ contact -- sender's contact URI
+ is_typing -- boolean to indicate whether remote is currently
+ typing an instant message.
+
+ """
+ pass
+
+ def on_mwi_info(self, body):
+ """
+ Notification about change in Message Summary / Message Waiting
+ Indication (RFC 3842) status. MWI subscription must be enabled
+ in the account config to receive this notification.
+
+ Keyword arguments:
+ body -- String containing message body as received in the
+ NOTIFY request.
+
+ """
+ pass
+
+
+
+class Account:
+ """This describes SIP account class.
+
+ PJSUA accounts provide identity (or identities) of the user who is
+ currently using the application. In SIP terms, the identity is used
+ as the From header in outgoing requests.
+
+ Account may or may not have client registration associated with it.
+ An account is also associated with route set and some authentication
+ credentials, which are used when sending SIP request messages using
+ the account. An account also has presence's online status, which
+ will be reported to remote peer when they subscribe to the account's
+ presence, or which is published to a presence server if presence
+ publication is enabled for the account.
+
+ Account is created with Lib.create_account(). At least one account
+ MUST be created. If no user association is required, application can
+ create a userless account by calling Lib.create_account_for_transport().
+ A userless account identifies local endpoint instead of a particular
+ user, and it correspond with a particular transport instance.
+
+ Also one account must be set as the default account, which is used as
+ the account to use when PJSUA fails to match a request with any other
+ accounts.
+
+ """
+ _id = -1
+ _lib = None
+ _cb = AccountCallback(None)
+ _obj_name = ""
+
+ def __init__(self, lib, id, cb=None):
+ """Construct this class. This is normally called by Lib class and
+ not by application.
+
+ Keyword arguments:
+ lib -- the Lib instance.
+ id -- the pjsua account ID.
+ cb -- AccountCallback instance to receive events from this Account.
+ If callback is not specified here, it must be set later
+ using set_callback().
+ """
+ self._id = id
+ self._lib = weakref.ref(lib)
+ self._obj_name = "{Account " + self.info().uri + "}"
+ self.set_callback(cb)
+ _pjsua.acc_set_user_data(self._id, self)
+ _Trace((self, 'created'))
+
+ def __del__(self):
+ if self._id != -1:
+ _pjsua.acc_set_user_data(self._id, 0)
+ _Trace((self, 'destroyed'))
+
+ def __str__(self):
+ return self._obj_name
+
+ def info(self):
+ """Retrieve AccountInfo for this account.
+ """
+ lck = self._lib().auto_lock()
+ ai = _pjsua.acc_get_info(self._id)
+ if ai==None:
+ self._lib()._err_check("info()", self, -1, "Invalid account")
+ return AccountInfo(ai)
+
+ def is_valid(self):
+ """
+ Check if this account is still valid.
+
+ """
+ lck = self._lib().auto_lock()
+ return _pjsua.acc_is_valid(self._id)
+
+ def set_callback(self, cb):
+ """Register callback to receive notifications from this object.
+
+ Keyword argument:
+ cb -- AccountCallback instance.
+
+ """
+ if cb:
+ self._cb = cb
+ else:
+ self._cb = AccountCallback(self)
+ self._cb._set_account(self)
+
+ def set_default(self):
+ """ Set this account as default account to send outgoing requests
+ and as the account to receive incoming requests when more exact
+ matching criteria fails.
+ """
+ lck = self._lib().auto_lock()
+ err = _pjsua.acc_set_default(self._id)
+ self._lib()._err_check("set_default()", self, err)
+
+ def is_default(self):
+ """ Check if this account is the default account.
+
+ """
+ lck = self._lib().auto_lock()
+ def_id = _pjsua.acc_get_default()
+ return self.is_valid() and def_id==self._id
+
+ def delete(self):
+ """ Delete this account.
+
+ """
+ lck = self._lib().auto_lock()
+ err = _pjsua.acc_set_user_data(self._id, 0)
+ self._lib()._err_check("delete()", self, err)
+ err = _pjsua.acc_del(self._id)
+ self._lib()._err_check("delete()", self, err)
+ self._id = -1
+
+ def set_basic_status(self, is_online):
+ """ Set basic presence status of this account.
+
+ Keyword argument:
+ is_online -- boolean to indicate basic presence availability.
+
+ """
+ lck = self._lib().auto_lock()
+ err = _pjsua.acc_set_online_status(self._id, is_online)
+ self._lib()._err_check("set_basic_status()", self, err)
+
+ def set_presence_status(self, is_online,
+ activity=PresenceActivity.UNKNOWN,
+ pres_text="", rpid_id=""):
+ """ Set presence status of this account.
+
+ Keyword arguments:
+ is_online -- boolean to indicate basic presence availability
+ activity -- value from PresenceActivity
+ pres_text -- optional string to convey additional information about
+ the activity (such as "On the phone")
+ rpid_id -- optional string to be placed as RPID ID.
+
+ """
+ lck = self._lib().auto_lock()
+ err = _pjsua.acc_set_online_status2(self._id, is_online, activity,
+ pres_text, rpid_id)
+ self._lib()._err_check("set_presence_status()", self, err)
+
+ def set_registration(self, renew):
+ """Manually renew registration or unregister from the server.
+
+ Keyword argument:
+ renew -- boolean to indicate whether registration is renewed.
+ Setting this value for False will trigger unregistration.
+
+ """
+ lck = self._lib().auto_lock()
+ err = _pjsua.acc_set_registration(self._id, renew)
+ self._lib()._err_check("set_registration()", self, err)
+
+ def set_transport(self, transport):
+ """Set this account to only use the specified transport to send
+ outgoing requests.
+
+ Keyword argument:
+ transport -- Transport object.
+
+ """
+ lck = self._lib().auto_lock()
+ err = _pjsua.acc_set_transport(self._id, transport._id)
+ self._lib()._err_check("set_transport()", self, err)
+
+ def make_call(self, dst_uri, cb=None, hdr_list=None):
+ """Make outgoing call to the specified URI.
+
+ Keyword arguments:
+ dst_uri -- Destination SIP URI.
+ cb -- CallCallback instance to be installed to the newly
+ created Call object. If this CallCallback is not
+ specified (i.e. None is given), it must be installed
+ later using call.set_callback().
+ hdr_list -- Optional list of headers to be sent with outgoing
+ INVITE
+
+ Return:
+ Call instance.
+ """
+ lck = self._lib().auto_lock()
+ call = Call(self._lib(), -1, cb)
+ err, cid = _pjsua.call_make_call(self._id, dst_uri, 0,
+ call, Lib._create_msg_data(hdr_list))
+ self._lib()._err_check("make_call()", self, err)
+ call.attach_to_id(cid)
+ return call
+
+ def add_buddy(self, uri, cb=None):
+ """Add new buddy.
+
+ Keyword argument:
+ uri -- SIP URI of the buddy
+ cb -- BuddyCallback instance to be installed to the newly
+ created Buddy object. If this callback is not specified
+ (i.e. None is given), it must be installed later using
+ buddy.set_callback().
+
+ Return:
+ Buddy object
+ """
+ lck = self._lib().auto_lock()
+ buddy_cfg = _pjsua.buddy_config_default()
+ buddy_cfg.uri = uri
+ buddy_cfg.subscribe = False
+ err, buddy_id = _pjsua.buddy_add(buddy_cfg)
+ self._lib()._err_check("add_buddy()", self, err)
+ buddy = Buddy(self._lib(), buddy_id, self, cb)
+ return buddy
+
+ def pres_notify(self, pres_obj, state, reason="", hdr_list=None):
+ """Send NOTIFY to inform account presence status or to terminate
+ server side presence subscription.
+
+ Keyword arguments:
+ pres_obj -- The subscription object from on_incoming_subscribe()
+ callback
+ state -- Subscription state, from SubscriptionState
+ reason -- Optional reason phrase.
+ hdr_list -- Optional header list.
+ """
+ lck = self._lib().auto_lock()
+ _pjsua.acc_pres_notify(self._id, pres_obj, state, reason,
+ Lib._create_msg_data(hdr_list))
+
+ def send_pager(self, uri, text, im_id=0, content_type="text/plain", \
+ hdr_list=None):
+ """Send instant message to arbitrary URI.
+
+ Keyword arguments:
+ text -- Instant message to be sent
+ uri -- URI to send the Instant Message to.
+ im_id -- Optional instant message ID to identify this
+ instant message when delivery status callback
+ is called.
+ content_type -- MIME type identifying the instant message
+ hdr_list -- Optional list of headers to be sent with the
+ request.
+
+ """
+ lck = self._lib().auto_lock()
+ err = _pjsua.im_send(self._id, uri, \
+ content_type, text, \
+ Lib._create_msg_data(hdr_list), \
+ im_id)
+ self._lib()._err_check("send_pager()", self, err)
+
+class CallCallback:
+ """Class to receive event notification from Call objects.
+
+ Use Call.set_callback() method to install instance of this callback
+ class to receive event notifications from the call object.
+
+ Member documentation:
+
+ call -- the Call object.
+
+ """
+ call = None
+
+ def __init__(self, call=None):
+ self._set_call(call)
+
+ def __del__(self):
+ pass
+
+ def _set_call(self, call):
+ if call:
+ self.call = weakref.proxy(call)
+ else:
+ self.call = None
+
+ def on_state(self):
+ """Notification that the call's state has changed.
+
+ """
+ pass
+
+ def on_media_state(self):
+ """Notification that the call's media state has changed.
+
+ """
+ pass
+
+ def on_dtmf_digit(self, digits):
+ """Notification on incoming DTMF digits.
+
+ Keyword argument:
+ digits -- string containing the received digits.
+
+ """
+ pass
+
+ def on_transfer_request(self, dst, code):
+ """Notification that call is being transfered by remote party.
+
+ Application can decide to accept/reject transfer request by returning
+ code greater than or equal to 500. The default behavior is to accept
+ the transfer by returning 202.
+
+ Keyword arguments:
+ dst -- string containing the destination URI
+ code -- the suggested status code to return to accept the request.
+
+ Return:
+ the callback should return 202 to accept the request, or 300-699 to
+ reject the request.
+
+ """
+ return code
+
+ def on_transfer_status(self, code, reason, final, cont):
+ """
+ Notification about the status of previous call transfer request.
+
+ Keyword arguments:
+ code -- SIP status code to indicate completion status.
+ text -- SIP status reason phrase.
+ final -- if True then this is a final status and no further
+ notifications will be sent for this call transfer
+ status.
+ cont -- suggested return value.
+
+ Return:
+ If the callback returns false then no further notification will
+ be sent for the transfer request for this call.
+
+ """
+ return cont
+
+ def on_replace_request(self, code, reason):
+ """Notification when incoming INVITE with Replaces header is received.
+
+ Application may reject the request by returning value greather than
+ or equal to 500. The default behavior is to accept the request.
+
+ Keyword arguments:
+ code -- default status code to return
+ reason -- default reason phrase to return
+
+ Return:
+ The callback should return (code, reason) tuple.
+
+ """
+ return code, reason
+
+ def on_replaced(self, new_call):
+ """
+ Notification that this call will be replaced with new_call.
+ After this callback is called, this call will be disconnected.
+
+ Keyword arguments:
+ new_call -- the new call that will replace this call.
+ """
+ pass
+
+ def on_pager(self, mime_type, body):
+ """
+ Notification that incoming instant message is received on
+ this call.
+
+ Keyword arguments:
+ mime_type -- MIME type of the instant message body.
+ body -- the instant message body.
+
+ """
+ pass
+
+ def on_pager_status(self, body, im_id, code, reason):
+ """
+ Notification about the delivery status of previously sent
+ instant message.
+
+ Keyword arguments:
+ body -- message body
+ im_id -- message ID
+ code -- SIP status code
+ reason -- SIP reason phrase
+
+ """
+ pass
+
+ def on_typing(self, is_typing):
+ """
+ Notification that remote is typing or stop typing.
+
+ Keyword arguments:
+ is_typing -- boolean to indicate whether remote is currently
+ typing an instant message.
+
+ """
+ pass
+
+
+class CallInfo:
+ """This structure contains various information about Call.
+
+ Application may retrieve this information with Call.info().
+
+ Member documentation:
+
+ role -- CallRole
+ account -- Account object.
+ uri -- SIP URI of local account.
+ contact -- local Contact URI.
+ remote_uri -- remote SIP URI.
+ remote_contact -- remote Contact URI
+ sip_call_id -- call's Call-ID identification
+ state -- CallState
+ state_text -- state text.
+ last_code -- last SIP status code
+ last_reason -- text phrase for last_code
+ media_state -- MediaState
+ media_dir -- MediaDir
+ conf_slot -- conference slot number for this call.
+ call_time -- call's connected duration in seconds.
+ total_time -- total call duration in seconds.
+ """
+ role = CallRole.CALLER
+ account = None
+ uri = ""
+ contact = ""
+ remote_uri = ""
+ remote_contact = ""
+ sip_call_id = ""
+ state = CallState.NULL
+ state_text = ""
+ last_code = 0
+ last_reason = ""
+ media_state = MediaState.NULL
+ media_dir = MediaDir.NULL
+ conf_slot = -1
+ call_time = 0
+ total_time = 0
+
+ def __init__(self, lib=None, ci=None):
+ if lib and ci:
+ self._cvt_from_pjsua(lib, ci)
+
+ def _cvt_from_pjsua(self, lib, ci):
+ self.role = ci.role
+ self.account = lib._lookup_account(ci.acc_id)
+ self.uri = ci.local_info
+ self.contact = ci.local_contact
+ self.remote_uri = ci.remote_info
+ self.remote_contact = ci.remote_contact
+ self.sip_call_id = ci.call_id
+ self.state = ci.state
+ self.state_text = ci.state_text
+ self.last_code = ci.last_status
+ self.last_reason = ci.last_status_text
+ self.media_state = ci.media_status
+ self.media_dir = ci.media_dir
+ self.conf_slot = ci.conf_slot
+ self.call_time = ci.connect_duration / 1000
+ self.total_time = ci.total_duration / 1000
+
+
+class Call:
+ """This class represents SIP call.
+
+ Application initiates outgoing call with Account.make_call(), and
+ incoming calls are reported in AccountCallback.on_incoming_call().
+ """
+ _id = -1
+ _cb = None
+ _lib = None
+ _obj_name = ""
+
+ def __init__(self, lib, call_id, cb=None):
+ self._lib = weakref.ref(lib)
+ self.set_callback(cb)
+ self.attach_to_id(call_id)
+ _Trace((self, 'created'))
+
+ def __del__(self):
+ if self._id != -1:
+ _pjsua.call_set_user_data(self._id, 0)
+ _Trace((self, 'destroyed'))
+
+ def __str__(self):
+ return self._obj_name
+
+ def attach_to_id(self, call_id):
+ lck = self._lib().auto_lock()
+ if self._id != -1:
+ _pjsua.call_set_user_data(self._id, 0)
+ self._id = call_id
+ if self._id != -1:
+ _pjsua.call_set_user_data(self._id, self)
+ self._obj_name = "{Call " + self.info().remote_uri + "}"
+ else:
+ self._obj_name = "{Call object}"
+
+ def set_callback(self, cb):
+ """
+ Set callback object to retrieve event notifications from this call.
+
+ Keyword arguments:
+ cb -- CallCallback instance.
+ """
+ if cb:
+ self._cb = cb
+ else:
+ self._cb = CallCallback(self)
+ self._cb._set_call(self)
+
+ def info(self):
+ """
+ Get the CallInfo.
+ """
+ lck = self._lib().auto_lock()
+ ci = _pjsua.call_get_info(self._id)
+ if not ci:
+ self._lib()._err_check("info", self, -1, "Invalid call")
+ call_info = CallInfo(self._lib(), ci)
+ return call_info
+
+ def is_valid(self):
+ """
+ Check if this call is still valid.
+ """
+ lck = self._lib().auto_lock()
+ return _pjsua.call_is_active(self._id)
+
+ def dump_status(self, with_media=True, indent="", max_len=1024):
+ """
+ Dump the call status.
+ """
+ lck = self._lib().auto_lock()
+ return _pjsua.call_dump(self._id, with_media, max_len, indent)
+
+ def answer(self, code=200, reason="", hdr_list=None):
+ """
+ Send provisional or final response to incoming call.
+
+ Keyword arguments:
+ code -- SIP status code.
+ reason -- Reason phrase. Put empty to send default reason
+ phrase for the status code.
+ hdr_list -- Optional list of headers to be sent with the
+ INVITE response.
+
+ """
+ lck = self._lib().auto_lock()
+ err = _pjsua.call_answer(self._id, code, reason,
+ Lib._create_msg_data(hdr_list))
+ self._lib()._err_check("answer()", self, err)
+
+ def hangup(self, code=603, reason="", hdr_list=None):
+ """
+ Terminate the call.
+
+ Keyword arguments:
+ code -- SIP status code.
+ reason -- Reason phrase. Put empty to send default reason
+ phrase for the status code.
+ hdr_list -- Optional list of headers to be sent with the
+ message.
+
+ """
+ lck = self._lib().auto_lock()
+ err = _pjsua.call_hangup(self._id, code, reason,
+ Lib._create_msg_data(hdr_list))
+ self._lib()._err_check("hangup()", self, err)
+
+ def hold(self, hdr_list=None):
+ """
+ Put the call on hold.
+
+ Keyword arguments:
+ hdr_list -- Optional list of headers to be sent with the
+ message.
+ """
+ lck = self._lib().auto_lock()
+ err = _pjsua.call_set_hold(self._id, Lib._create_msg_data(hdr_list))
+ self._lib()._err_check("hold()", self, err)
+
+ def unhold(self, hdr_list=None):
+ """
+ Release the call from hold.
+
+ Keyword arguments:
+ hdr_list -- Optional list of headers to be sent with the
+ message.
+
+ """
+ lck = self._lib().auto_lock()
+ err = _pjsua.call_reinvite(self._id, True,
+ Lib._create_msg_data(hdr_list))
+ self._lib()._err_check("unhold()", self, err)
+
+ def reinvite(self, hdr_list=None):
+ """
+ Send re-INVITE and optionally offer new codecs to use.
+
+ Keyword arguments:
+ hdr_list -- Optional list of headers to be sent with the
+ message.
+
+ """
+ lck = self._lib().auto_lock()
+ err = _pjsua.call_reinvite(self._id, True,
+ Lib._create_msg_data(hdr_list))
+ self._lib()._err_check("reinvite()", self, err)
+
+ def update(self, hdr_list=None, options=0):
+ """
+ Send UPDATE and optionally offer new codecs to use.
+
+ Keyword arguments:
+ hdr_list -- Optional list of headers to be sent with the
+ message.
+ options -- Must be zero for now.
+
+ """
+ lck = self._lib().auto_lock()
+ err = _pjsua.call_update(self._id, options,
+ Lib._create_msg_data(hdr_list))
+ self._lib()._err_check("update()", self, err)
+
+ def transfer(self, dest_uri, hdr_list=None):
+ """
+ Transfer the call to new destination.
+
+ Keyword arguments:
+ dest_uri -- Specify the SIP URI to transfer the call to.
+ hdr_list -- Optional list of headers to be sent with the
+ message.
+
+ """
+ lck = self._lib().auto_lock()
+ err = _pjsua.call_xfer(self._id, dest_uri,
+ Lib._create_msg_data(hdr_list))
+ self._lib()._err_check("transfer()", self, err)
+
+ def transfer_to_call(self, call, hdr_list=None, options=0):
+ """
+ Attended call transfer.
+
+ Keyword arguments:
+ call -- The Call object to transfer call to.
+ hdr_list -- Optional list of headers to be sent with the
+ message.
+ options -- Must be zero for now.
+
+ """
+ lck = self._lib().auto_lock()
+ err = _pjsua.call_xfer_replaces(self._id, call._id, options,
+ Lib._create_msg_data(hdr_list))
+ self._lib()._err_check("transfer_to_call()", self, err)
+
+ def dial_dtmf(self, digits):
+ """
+ Send DTMF digits with RTP event package.
+
+ Keyword arguments:
+ digits -- DTMF digit string.
+
+ """
+ lck = self._lib().auto_lock()
+ err = _pjsua.call_dial_dtmf(self._id, digits)
+ self._lib()._err_check("dial_dtmf()", self, err)
+
+ def send_request(self, method, hdr_list=None, content_type=None,
+ body=None):
+ """
+ Send arbitrary request to remote call.
+
+ This is useful for example to send INFO request. Note that this
+ function should not be used to send request that will change the
+ call state such as CANCEL or BYE.
+
+ Keyword arguments:
+ method -- SIP method name.
+ hdr_list -- Optional header list to be sent with the request.
+ content_type -- Content type to describe the body, if the body
+ is present
+ body -- Optional SIP message body.
+
+ """
+ lck = self._lib().auto_lock()
+ if hdr_list or body:
+ msg_data = _pjsua.Msg_Data()
+ if hdr_list:
+ msg_data.hdr_list = hdr_list
+ if content_type:
+ msg_data.content_type = content_type
+ if body:
+ msg_data.msg_body = body
+ else:
+ msg_data = None
+
+ err = _pjsua.call_send_request(self._id, method, msg_data)
+ self._lib()._err_check("send_request()", self, err)
+
+ def send_pager(self, text, im_id=0, content_type="text/plain",
+ hdr_list=None):
+ """Send instant message inside a call.
+
+ Keyword arguments:
+ text -- Instant message to be sent
+ im_id -- Optional instant message ID to identify this
+ instant message when delivery status callback
+ is called.
+ content_type -- MIME type identifying the instant message
+ hdr_list -- Optional list of headers to be sent with the
+ request.
+
+ """
+ lck = self._lib().auto_lock()
+ err = _pjsua.call_send_im(self._id, \
+ content_type, text, \
+ Lib._create_msg_data(hdr_list), \
+ im_id)
+ self._lib()._err_check("send_pager()", self, err)
+
+
+class BuddyInfo:
+ """This class contains information about Buddy. Application may
+ retrieve this information by calling Buddy.info().
+
+ Member documentation:
+
+ uri -- the Buddy URI.
+ contact -- the Buddy Contact URI, if available.
+ online_status -- the presence online status.
+ online_text -- the presence online status text.
+ activity -- the PresenceActivity
+ subscribed -- specify whether buddy's presence status is currently
+ being subscribed.
+ sub_state -- SubscriptionState
+ sub_term_reason -- The termination reason string of the last presence
+ subscription to this buddy, if any.
+ """
+ uri = ""
+ contact = ""
+ online_status = 0
+ online_text = ""
+ activity = PresenceActivity.UNKNOWN
+ subscribed = False
+ sub_state = SubscriptionState.NULL
+ sub_term_reason = ""
+
+ def __init__(self, pjsua_bi=None):
+ if pjsua_bi:
+ self._cvt_from_pjsua(pjsua_bi)
+
+ def _cvt_from_pjsua(self, inf):
+ self.uri = inf.uri
+ self.contact = inf.contact
+ self.online_status = inf.status
+ self.online_text = inf.status_text
+ self.activity = inf.activity
+ self.subscribed = inf.monitor_pres
+ self.sub_state = inf.sub_state
+ self.sub_term_reason = inf.sub_term_reason
+
+
+class BuddyCallback:
+ """This class can be used to receive notifications about Buddy's
+ presence status change. Application needs to derive a class from
+ this class, and register the instance with Buddy.set_callback().
+
+ Member documentation:
+
+ buddy -- the Buddy object.
+ """
+ buddy = None
+
+ def __init__(self, buddy=None):
+ self._set_buddy(buddy)
+
+ def _set_buddy(self, buddy):
+ if buddy:
+ self.buddy = weakref.proxy(buddy)
+ else:
+ self.buddy = None
+
+ def on_state(self):
+ """
+ Notification that buddy's presence state has changed. Application
+ may then retrieve the new status with Buddy.info() function.
+ """
+ pass
+
+ def on_pager(self, mime_type, body):
+ """Notification that incoming instant message is received from
+ this buddy.
+
+ Keyword arguments:
+ mime_type -- MIME type of the instant message body
+ body -- the instant message body
+
+ """
+ pass
+
+ def on_pager_status(self, body, im_id, code, reason):
+ """Notification about the delivery status of previously sent
+ instant message.
+
+ Keyword arguments:
+ body -- the message body
+ im_id -- message ID
+ code -- SIP status code
+ reason -- SIP reason phrase
+
+ """
+ pass
+
+ def on_typing(self, is_typing):
+ """Notification that remote is typing or stop typing.
+
+ Keyword arguments:
+ is_typing -- boolean to indicate whether remote is currently
+ typing an instant message.
+
+ """
+ pass
+
+
+class Buddy:
+ """A Buddy represents person or remote agent.
+
+ This class provides functions to subscribe to buddy's presence and
+ to send or receive instant messages from the buddy.
+ """
+ _id = -1
+ _lib = None
+ _cb = None
+ _obj_name = ""
+ _acc = None
+
+ def __init__(self, lib, id, account, cb):
+ self._id = id
+ self._lib = weakref.ref(lib)
+ self._acc = weakref.ref(account)
+ self._obj_name = "{Buddy " + self.info().uri + "}"
+ self.set_callback(cb)
+ _pjsua.buddy_set_user_data(self._id, self)
+ _Trace((self, 'created'))
+
+ def __del__(self):
+ if self._id != -1:
+ _pjsua.buddy_set_user_data(self._id, 0)
+ _Trace((self, 'destroyed'))
+
+ def __str__(self):
+ return self._obj_name
+
+ def info(self):
+ """
+ Get buddy info as BuddyInfo.
+ """
+ lck = self._lib().auto_lock()
+ return BuddyInfo(_pjsua.buddy_get_info(self._id))
+
+ def set_callback(self, cb):
+ """Install callback to receive notifications from this object.
+
+ Keyword argument:
+ cb -- BuddyCallback instance.
+ """
+ if cb:
+ self._cb = cb
+ else:
+ self._cb = BuddyCallback(self)
+ self._cb._set_buddy(self)
+
+ def subscribe(self):
+ """
+ Subscribe to buddy's presence status notification.
+ """
+ lck = self._lib().auto_lock()
+ err = _pjsua.buddy_subscribe_pres(self._id, True)
+ self._lib()._err_check("subscribe()", self, err)
+
+ def unsubscribe(self):
+ """
+ Unsubscribe from buddy's presence status notification.
+ """
+ lck = self._lib().auto_lock()
+ err = _pjsua.buddy_subscribe_pres(self._id, False)
+ self._lib()._err_check("unsubscribe()", self, err)
+
+ def delete(self):
+ """
+ Remove this buddy from the buddy list.
+ """
+ lck = self._lib().auto_lock()
+ if self._id != -1:
+ _pjsua.buddy_set_user_data(self._id, 0)
+ err = _pjsua.buddy_del(self._id)
+ self._lib()._err_check("delete()", self, err)
+
+ def send_pager(self, text, im_id=0, content_type="text/plain", \
+ hdr_list=None):
+ """Send instant message to remote buddy.
+
+ Keyword arguments:
+ text -- Instant message to be sent
+ im_id -- Optional instant message ID to identify this
+ instant message when delivery status callback
+ is called.
+ content_type -- MIME type identifying the instant message
+ hdr_list -- Optional list of headers to be sent with the
+ request.
+
+ """
+ lck = self._lib().auto_lock()
+ err = _pjsua.im_send(self._acc()._id, self.info().uri, \
+ content_type, text, \
+ Lib._create_msg_data(hdr_list), \
+ im_id)
+ self._lib()._err_check("send_pager()", self, err)
+
+ def send_typing_ind(self, is_typing=True, hdr_list=None):
+ """Send typing indication to remote buddy.
+
+ Keyword argument:
+ is_typing -- boolean to indicate wheter user is typing.
+ hdr_list -- Optional list of headers to be sent with the
+ request.
+
+ """
+ lck = self._lib().auto_lock()
+ err = _pjsua.im_typing(self._acc()._id, self.info().uri, \
+ is_typing, Lib._create_msg_data(hdr_list))
+ self._lib()._err_check("send_typing_ind()", self, err)
+
+
+
+# Sound device info
+class SoundDeviceInfo:
+ """This described the sound device info.
+
+ Member documentation:
+ name -- device name.
+ input_channels -- number of capture channels supported.
+ output_channels -- number of playback channels supported.
+ default_clock_rate -- default sampling rate.
+ """
+ name = ""
+ input_channels = 0
+ output_channels = 0
+ default_clock_rate = 0
+
+ def __init__(self, sdi):
+ self.name = sdi.name
+ self.input_channels = sdi.input_count
+ self.output_channels = sdi.output_count
+ self.default_clock_rate = sdi.default_samples_per_sec
+
+
+# Codec info
+class CodecInfo:
+ """This describes codec info.
+
+ Member documentation:
+ name -- codec name
+ priority -- codec priority (0-255)
+ clock_rate -- clock rate
+ channel_count -- number of channels
+ avg_bps -- average bandwidth in bits per second
+ frm_ptime -- base frame length in milliseconds
+ ptime -- RTP frame length in milliseconds.
+ pt -- payload type.
+ vad_enabled -- specify if Voice Activity Detection is currently
+ enabled.
+ plc_enabled -- specify if Packet Lost Concealment is currently
+ enabled.
+ """
+ name = ""
+ priority = 0
+ clock_rate = 0
+ channel_count = 0
+ avg_bps = 0
+ frm_ptime = 0
+ ptime = 0
+ pt = 0
+ vad_enabled = False
+ plc_enabled = False
+
+ def __init__(self, codec_info, codec_param):
+ self.name = codec_info.codec_id
+ self.priority = codec_info.priority
+ self.clock_rate = codec_param.info.clock_rate
+ self.channel_count = codec_param.info.channel_cnt
+ self.avg_bps = codec_param.info.avg_bps
+ self.frm_ptime = codec_param.info.frm_ptime
+ self.ptime = codec_param.info.frm_ptime * \
+ codec_param.setting.frm_per_pkt
+ self.ptime = codec_param.info.pt
+ self.vad_enabled = codec_param.setting.vad
+ self.plc_enabled = codec_param.setting.plc
+
+ def _cvt_to_pjsua(self):
+ ci = _pjsua.Codec_Info()
+ ci.codec_id = self.name
+ ci.priority = self.priority
+ return ci
+
+
+# Codec parameter
+class CodecParameter:
+ """This specifies various parameters that can be configured for codec.
+
+ Member documentation:
+
+ ptime -- specify the outgoing RTP packet length in milliseconds.
+ vad_enabled -- specify if VAD should be enabled.
+ plc_enabled -- specify if PLC should be enabled.
+ """
+ ptime = 0
+ vad_enabled = False
+ plc_enabled = False
+ _codec_param = None
+
+ def __init__(self, codec_param):
+ self.ptime = codec_param.info.frm_ptime * \
+ codec_param.setting.frm_per_pkt
+ self.vad_enabled = codec_param.setting.vad
+ self.plc_enabled = codec_param.setting.plc
+ self._codec_param = codec_param
+
+ def _cvt_to_pjsua(self):
+ self._codec_param.setting.frm_per_pkt = self.ptime / \
+ self._codec_param.info.frm_ptime
+ self._codec_param.setting.vad = self.vad_enabled
+ self._codec_param.setting.plc = self.plc_enabled
+ return self._codec_param
+
+
+# Library mutex
+class _LibMutex:
+ def __init__(self, lck):
+ self._lck = lck
+ self._lck.acquire()
+ #_Trace(('lock acquired',))
+
+ def __del__(self):
+ try:
+ self._lck.release()
+ #_Trace(('lock released',))
+ except:
+ #_Trace(('lock release error',))
+ pass
+
+
+# PJSUA Library
+_lib = None
+enable_trace = False
+
+class Lib:
+ """Library instance.
+
+ """
+ _quit = False
+ _has_thread = False
+ _lock = None
+
+ def __init__(self):
+ global _lib
+ if _lib:
+ raise Error("__init()__", None, -1,
+ "Library instance already exist")
+
+ self._lock = threading.RLock()
+ err = _pjsua.create()
+ self._err_check("_pjsua.create()", None, err)
+ _lib = self
+
+ def __del__(self):
+ _pjsua.destroy()
+ del self._lock
+ _Trace(('Lib destroyed',))
+
+ def __str__(self):
+ return "Lib"
+
+ @staticmethod
+ def instance():
+ """Return singleton instance of Lib.
+ """
+ return _lib
+
+ def init(self, ua_cfg=None, log_cfg=None, media_cfg=None):
+ """
+ Initialize pjsua with the specified configurations.
+
+ Keyword arguments:
+ ua_cfg -- optional UAConfig instance
+ log_cfg -- optional LogConfig instance
+ media_cfg -- optional MediaConfig instance
+
+ """
+ if not ua_cfg: ua_cfg = UAConfig()
+ if not log_cfg: log_cfg = LogConfig()
+ if not media_cfg: media_cfg = MediaConfig()
+
+ py_ua_cfg = ua_cfg._cvt_to_pjsua()
+ py_ua_cfg.cb.on_call_state = _cb_on_call_state
+ py_ua_cfg.cb.on_incoming_call = _cb_on_incoming_call
+ py_ua_cfg.cb.on_call_media_state = _cb_on_call_media_state
+ py_ua_cfg.cb.on_dtmf_digit = _cb_on_dtmf_digit
+ py_ua_cfg.cb.on_call_transfer_request = _cb_on_call_transfer_request
+ py_ua_cfg.cb.on_call_transfer_status = _cb_on_call_transfer_status
+ py_ua_cfg.cb.on_call_replace_request = _cb_on_call_replace_request
+ py_ua_cfg.cb.on_call_replaced = _cb_on_call_replaced
+ py_ua_cfg.cb.on_reg_state = _cb_on_reg_state
+ py_ua_cfg.cb.on_incoming_subscribe = _cb_on_incoming_subscribe
+ py_ua_cfg.cb.on_buddy_state = _cb_on_buddy_state
+ py_ua_cfg.cb.on_pager = _cb_on_pager
+ py_ua_cfg.cb.on_pager_status = _cb_on_pager_status
+ py_ua_cfg.cb.on_typing = _cb_on_typing
+ py_ua_cfg.cb.on_mwi_info = _cb_on_mwi_info;
+
+ err = _pjsua.init(py_ua_cfg, log_cfg._cvt_to_pjsua(),
+ media_cfg._cvt_to_pjsua())
+ self._err_check("init()", self, err)
+
+ def destroy(self):
+ """Destroy the library, and pjsua."""
+ global _lib
+ if self._has_thread:
+ self._quit = 1
+ loop = 0
+ while self._quit != 2 and loop < 400:
+ self.handle_events(5)
+ loop = loop + 1
+ time.sleep(0.050)
+ _pjsua.destroy()
+ _lib = None
+
+ def start(self, with_thread=True):
+ """Start the library.
+
+ Keyword argument:
+ with_thread -- specify whether the module should create worker
+ thread.
+
+ """
+ lck = self.auto_lock()
+ err = _pjsua.start()
+ self._err_check("start()", self, err)
+ self._has_thread = with_thread
+ if self._has_thread:
+ thread.start_new(_worker_thread_main, (0,))
+
+ def handle_events(self, timeout=50):
+ """Poll the events from underlying pjsua library.
+
+ Application must poll the stack periodically if worker thread
+ is disable when starting the library.
+
+ Keyword argument:
+ timeout -- in milliseconds.
+
+ """
+ lck = self.auto_lock()
+ return _pjsua.handle_events(timeout)
+
+ def thread_register(self, name):
+ """Register external threads (threads that are not created by PJSIP,
+ such as threads that are created by Python API) to PJSIP.
+
+ The call must be made from the new thread before calling any pjlib
+ functions.
+
+ Keyword arguments:
+ name -- Non descriptive name for the thread
+ """
+ dummy = 1
+ err = _pjsua.thread_register(name, dummy)
+ self._err_check("thread_register()", self, err)
+
+ def verify_sip_url(self, sip_url):
+ """Verify that the specified string is a valid URI.
+
+ Keyword argument:
+ sip_url -- the URL string.
+
+ Return:
+ 0 is the the URI is valid, otherwise the appropriate error
+ code is returned.
+
+ """
+ lck = self.auto_lock()
+ return _pjsua.verify_sip_url(sip_url)
+
+ def create_transport(self, type, cfg=None):
+ """Create SIP transport instance of the specified type.
+
+ Keyword arguments:
+ type -- transport type from TransportType constant.
+ cfg -- TransportConfig instance
+
+ Return:
+ Transport object
+
+ """
+ lck = self.auto_lock()
+ if not cfg: cfg=TransportConfig()
+ err, tp_id = _pjsua.transport_create(type, cfg._cvt_to_pjsua())
+ self._err_check("create_transport()", self, err)
+ return Transport(self, tp_id)
+
+ def create_account(self, acc_config, set_default=True, cb=None):
+ """
+ Create a new local pjsua account using the specified configuration.
+
+ Keyword arguments:
+ acc_config -- AccountConfig
+ set_default -- boolean to specify whether to use this as the
+ default account.
+ cb -- AccountCallback instance.
+
+ Return:
+ Account instance
+
+ """
+ lck = self.auto_lock()
+ err, acc_id = _pjsua.acc_add(acc_config._cvt_to_pjsua(), set_default)
+ self._err_check("create_account()", self, err)
+ return Account(self, acc_id, cb)
+
+ def create_account_for_transport(self, transport, set_default=True,
+ cb=None):
+ """Create a new local pjsua transport for the specified transport.
+
+ Keyword arguments:
+ transport -- the Transport instance.
+ set_default -- boolean to specify whether to use this as the
+ default account.
+ cb -- AccountCallback instance.
+
+ Return:
+ Account instance
+
+ """
+ lck = self.auto_lock()
+ err, acc_id = _pjsua.acc_add_local(transport._id, set_default)
+ self._err_check("create_account_for_transport()", self, err)
+ return Account(self, acc_id, cb)
+
+ def hangup_all(self):
+ """Hangup all calls.
+
+ """
+ lck = self.auto_lock()
+ _pjsua.call_hangup_all()
+
+ # Sound device API
+
+ def enum_snd_dev(self):
+ """Enumerate sound devices in the system.
+
+ Return:
+ list of SoundDeviceInfo. The index of the element specifies
+ the device ID for the device.
+ """
+ lck = self.auto_lock()
+ sdi_list = _pjsua.enum_snd_devs()
+ info = []
+ for sdi in sdi_list:
+ info.append(SoundDeviceInfo(sdi))
+ return info
+
+ def get_snd_dev(self):
+ """Get the device IDs of current sound devices used by pjsua.
+
+ Return:
+ (capture_dev_id, playback_dev_id) tuple
+ """
+ lck = self.auto_lock()
+ return _pjsua.get_snd_dev()
+
+ def set_snd_dev(self, capture_dev, playback_dev):
+ """Change the current sound devices.
+
+ Keyword arguments:
+ capture_dev -- the device ID of capture device to be used
+ playback_dev -- the device ID of playback device to be used.
+
+ """
+ lck = self.auto_lock()
+ err = _pjsua.set_snd_dev(capture_dev, playback_dev)
+ self._err_check("set_current_sound_devices()", self, err)
+
+ def set_null_snd_dev(self):
+ """Disable the sound devices. This is useful if the system
+ does not have sound device installed.
+
+ """
+ lck = self.auto_lock()
+ err = _pjsua.set_null_snd_dev()
+ self._err_check("set_null_snd_dev()", self, err)
+
+
+ # Conference bridge
+
+ def conf_get_max_ports(self):
+ """Get the conference bridge capacity.
+
+ Return:
+ conference bridge capacity.
+
+ """
+ lck = self.auto_lock()
+ return _pjsua.conf_get_max_ports()
+
+ def conf_connect(self, src_slot, dst_slot):
+ """Establish unidirectional media flow from souce to sink.
+
+ One source may transmit to multiple destinations/sink. And if
+ multiple sources are transmitting to the same sink, the media
+ will be mixed together. Source and sink may refer to the same ID,
+ effectively looping the media.
+
+ If bidirectional media flow is desired, application needs to call
+ this function twice, with the second one having the arguments
+ reversed.
+
+ Keyword arguments:
+ src_slot -- integer to identify the conference slot number of
+ the source/transmitter.
+ dst_slot -- integer to identify the conference slot number of
+ the destination/receiver.
+
+ """
+ lck = self.auto_lock()
+ err = _pjsua.conf_connect(src_slot, dst_slot)
+ self._err_check("conf_connect()", self, err)
+
+ def conf_disconnect(self, src_slot, dst_slot):
+ """Disconnect media flow from the source to destination port.
+
+ Keyword arguments:
+ src_slot -- integer to identify the conference slot number of
+ the source/transmitter.
+ dst_slot -- integer to identify the conference slot number of
+ the destination/receiver.
+
+ """
+ lck = self.auto_lock()
+ err = _pjsua.conf_disconnect(src_slot, dst_slot)
+ self._err_check("conf_disconnect()", self, err)
+
+ def conf_set_tx_level(self, slot, level):
+ """Adjust the signal level to be transmitted from the bridge to
+ the specified port by making it louder or quieter.
+
+ Keyword arguments:
+ slot -- integer to identify the conference slot number.
+ level -- Signal level adjustment. Value 1.0 means no level
+ adjustment, while value 0 means to mute the port.
+ """
+ lck = self.auto_lock()
+ err = _pjsua.conf_set_tx_level(slot, level)
+ self._err_check("conf_set_tx_level()", self, err)
+
+ def conf_set_rx_level(self, slot, level):
+ """Adjust the signal level to be received from the specified port
+ (to the bridge) by making it louder or quieter.
+
+ Keyword arguments:
+ slot -- integer to identify the conference slot number.
+ level -- Signal level adjustment. Value 1.0 means no level
+ adjustment, while value 0 means to mute the port.
+ """
+ lck = self.auto_lock()
+ err = _pjsua.conf_set_rx_level(slot, level)
+ self._err_check("conf_set_rx_level()", self, err)
+
+ def conf_get_signal_level(self, slot):
+ """Get last signal level transmitted to or received from the
+ specified port. The signal levels are float values from 0.0 to 1.0,
+ with 0.0 indicates no signal, and 1.0 indicates the loudest signal
+ level.
+
+ Keyword arguments:
+ slot -- integer to identify the conference slot number.
+
+ Return value:
+ (tx_level, rx_level) tuple.
+ """
+ lck = self.auto_lock()
+ err, tx_level, rx_level = _pjsua.conf_get_signal_level(slot)
+ self._err_check("conf_get_signal_level()", self, err)
+ return (tx_level, rx_level)
+
+
+
+ # Codecs API
+
+ def enum_codecs(self):
+ """Return list of codecs supported by pjsua.
+
+ Return:
+ list of CodecInfo
+
+ """
+ lck = self.auto_lock()
+ ci_list = _pjsua.enum_codecs()
+ codec_info = []
+ for ci in ci_list:
+ cp = _pjsua.codec_get_param(ci.codec_id)
+ if cp:
+ codec_info.append(CodecInfo(ci, cp))
+ return codec_info
+
+ def set_codec_priority(self, name, priority):
+ """Change the codec priority.
+
+ Keyword arguments:
+ name -- Codec name
+ priority -- Codec priority, which range is 0-255.
+
+ """
+ lck = self.auto_lock()
+ err = _pjsua.codec_set_priority(name, priority)
+ self._err_check("set_codec_priority()", self, err)
+
+ def get_codec_parameter(self, name):
+ """Get codec parameter for the specified codec.
+
+ Keyword arguments:
+ name -- codec name.
+
+ """
+ lck = self.auto_lock()
+ cp = _pjsua.codec_get_param(name)
+ if not cp:
+ self._err_check("get_codec_parameter()", self, -1,
+ "Invalid codec name")
+ return CodecParameter(cp)
+
+ def set_codec_parameter(self, name, param):
+ """Modify codec parameter for the specified codec.
+
+ Keyword arguments:
+ name -- codec name
+ param -- codec parameter.
+
+ """
+ lck = self.auto_lock()
+ err = _pjsua.codec_set_param(name, param._cvt_to_pjsua())
+ self._err_check("set_codec_parameter()", self, err)
+
+ # WAV playback and recording
+
+ def create_player(self, filename, loop=False):
+ """Create WAV file player.
+
+ Keyword arguments
+ filename -- WAV file name
+ loop -- boolean to specify whether playback should
+ automatically restart upon EOF
+ Return:
+ WAV player ID
+
+ """
+ lck = self.auto_lock()
+ opt = 0
+ if not loop:
+ opt = opt + 1
+ err, player_id = _pjsua.player_create(filename, opt)
+ self._err_check("create_player()", self, err)
+ return player_id
+
+ def player_get_slot(self, player_id):
+ """Get the conference port ID for the specified player.
+
+ Keyword arguments:
+ player_id -- the WAV player ID
+
+ Return:
+ Conference slot number for the player
+
+ """
+ lck = self.auto_lock()
+ slot = _pjsua.player_get_conf_port(player_id)
+ if slot < 0:
+ self._err_check("player_get_slot()", self, -1,
+ "Invalid player id")
+ return slot
+
+ def player_set_pos(self, player_id, pos):
+ """Set WAV playback position.
+
+ Keyword arguments:
+ player_id -- WAV player ID
+ pos -- playback position, in samples
+
+ """
+ lck = self.auto_lock()
+ err = _pjsua.player_set_pos(player_id, pos)
+ self._err_check("player_set_pos()", self, err)
+
+ def player_destroy(self, player_id):
+ """Destroy the WAV player.
+
+ Keyword arguments:
+ player_id -- the WAV player ID.
+
+ """
+ lck = self.auto_lock()
+ err = _pjsua.player_destroy(player_id)
+ self._err_check("player_destroy()", self, err)
+
+ def create_playlist(self, filelist, label="playlist", loop=True):
+ """Create WAV playlist.
+
+ Keyword arguments:
+ filelist -- List of WAV file names.
+ label -- Optional name to be assigned to the playlist
+ object (useful for logging)
+ loop -- boolean to specify whether playback should
+ automatically restart upon EOF
+
+ Return:
+ playlist_id
+ """
+ lck = self.auto_lock()
+ opt = 0
+ if not loop:
+ opt = opt + 1
+ err, playlist_id = _pjsua.playlist_create(label, filelist, opt)
+ self._err_check("create_playlist()", self, err)
+ return playlist_id
+
+ def playlist_get_slot(self, playlist_id):
+ """Get the conference port ID for the specified playlist.
+
+ Keyword arguments:
+ playlist_id -- the WAV playlist ID
+
+ Return:
+ Conference slot number for the playlist
+
+ """
+ lck = self.auto_lock()
+ slot = _pjsua.player_get_conf_port(playlist_id)
+ if slot < 0:
+ self._err_check("playlist_get_slot()", self, -1,
+ "Invalid playlist id")
+ return slot
+
+ def playlist_destroy(self, playlist_id):
+ """Destroy the WAV playlist.
+
+ Keyword arguments:
+ playlist_id -- the WAV playlist ID.
+
+ """
+ lck = self.auto_lock()
+ err = _pjsua.player_destroy(playlist_id)
+ self._err_check("playlist_destroy()", self, err)
+
+ def create_recorder(self, filename):
+ """Create WAV file recorder.
+
+ Keyword arguments
+ filename -- WAV file name
+
+ Return:
+ WAV recorder ID
+
+ """
+ lck = self.auto_lock()
+ err, rec_id = _pjsua.recorder_create(filename, 0, None, -1, 0)
+ self._err_check("create_recorder()", self, err)
+ return rec_id
+
+ def recorder_get_slot(self, rec_id):
+ """Get the conference port ID for the specified recorder.
+
+ Keyword arguments:
+ rec_id -- the WAV recorder ID
+
+ Return:
+ Conference slot number for the recorder
+
+ """
+ lck = self.auto_lock()
+ slot = _pjsua.recorder_get_conf_port(rec_id)
+ if slot < 1:
+ self._err_check("recorder_get_slot()", self, -1,
+ "Invalid recorder id")
+ return slot
+
+ def recorder_destroy(self, rec_id):
+ """Destroy the WAV recorder.
+
+ Keyword arguments:
+ rec_id -- the WAV recorder ID.
+
+ """
+ lck = self.auto_lock()
+ err = _pjsua.recorder_destroy(rec_id)
+ self._err_check("recorder_destroy()", self, err)
+
+
+ # Internal functions
+
+ @staticmethod
+ def strerror(err):
+ return _pjsua.strerror(err)
+
+ def _err_check(self, op_name, obj, err_code, err_msg=""):
+ if err_code != 0:
+ raise Error(op_name, obj, err_code, err_msg)
+
+ @staticmethod
+ def _create_msg_data(hdr_list):
+ if not hdr_list:
+ return None
+ msg_data = _pjsua.Msg_Data()
+ msg_data.hdr_list = hdr_list
+ return msg_data
+
+ def auto_lock(self):
+ return _LibMutex(self._lock)
+
+ # Internal dictionary manipulation for calls, accounts, and buddies
+
+ def _lookup_call(self, call_id):
+ return _pjsua.call_get_user_data(call_id)
+
+ def _lookup_account(self, acc_id):
+ return _pjsua.acc_get_user_data(acc_id)
+
+ def _lookup_buddy(self, buddy_id, uri=None):
+ if buddy_id != -1:
+ buddy = _pjsua.buddy_get_user_data(buddy_id)
+ elif uri:
+ buddy_id = _pjsua.buddy_find(uri)
+ if buddy_id != -1:
+ buddy = _pjsua.buddy_get_user_data(buddy_id)
+ else:
+ buddy = None
+ else:
+ buddy = None
+
+ return buddy
+
+ # Account allbacks
+
+ def _cb_on_reg_state(self, acc_id):
+ acc = self._lookup_account(acc_id)
+ if acc:
+ acc._cb.on_reg_state()
+
+ def _cb_on_incoming_subscribe(self, acc_id, buddy_id, from_uri,
+ contact_uri, pres_obj):
+ acc = self._lookup_account(acc_id)
+ if acc:
+ buddy = self._lookup_buddy(buddy_id)
+ return acc._cb.on_incoming_subscribe(buddy, from_uri, contact_uri,
+ pres_obj)
+ else:
+ return (404, None)
+
+ def _cb_on_incoming_call(self, acc_id, call_id, rdata):
+ acc = self._lookup_account(acc_id)
+ if acc:
+ acc._cb.on_incoming_call( Call(self, call_id) )
+ else:
+ _pjsua.call_hangup(call_id, 603, None, None)
+
+ # Call callbacks
+
+ def _cb_on_call_state(self, call_id):
+ call = self._lookup_call(call_id)
+ if call:
+ if call._id == -1:
+ call.attach_to_id(call_id)
+ done = (call.info().state == CallState.DISCONNECTED)
+ call._cb.on_state()
+ if done:
+ _pjsua.call_set_user_data(call_id, 0)
+ else:
+ pass
+
+ def _cb_on_call_media_state(self, call_id):
+ call = self._lookup_call(call_id)
+ if call:
+ call._cb.on_media_state()
+
+ def _cb_on_dtmf_digit(self, call_id, digits):
+ call = self._lookup_call(call_id)
+ if call:
+ call._cb.on_dtmf_digit(digits)
+
+ def _cb_on_call_transfer_request(self, call_id, dst, code):
+ call = self._lookup_call(call_id)
+ if call:
+ return call._cb.on_transfer_request(dst, code)
+ else:
+ return 603
+
+ def _cb_on_call_transfer_status(self, call_id, code, text, final, cont):
+ call = self._lookup_call(call_id)
+ if call:
+ return call._cb.on_transfer_status(code, text, final, cont)
+ else:
+ return cont
+
+ def _cb_on_call_replace_request(self, call_id, rdata, code, reason):
+ call = self._lookup_call(call_id)
+ if call:
+ return call._cb.on_replace_request(code, reason)
+ else:
+ return code, reason
+
+ def _cb_on_call_replaced(self, old_call_id, new_call_id):
+ old_call = self._lookup_call(old_call_id)
+ new_call = self._lookup_call(new_call_id)
+ if old_call and new_call:
+ old_call._cb.on_replaced(new_call)
+
+ def _cb_on_pager(self, call_id, from_uri, to_uri, contact, mime_type,
+ body, acc_id):
+ call = None
+ if call_id != -1:
+ call = self._lookup_call(call_id)
+ if call:
+ call._cb.on_pager(mime_type, body)
+ else:
+ acc = self._lookup_account(acc_id)
+ buddy = self._lookup_buddy(-1, from_uri)
+ if buddy:
+ buddy._cb.on_pager(mime_type, body)
+ else:
+ acc._cb.on_pager(from_uri, contact, mime_type, body)
+
+ def _cb_on_pager_status(self, call_id, to_uri, body, user_data,
+ code, reason, acc_id):
+ call = None
+ if call_id != -1:
+ call = self._lookup_call(call_id)
+ if call:
+ call._cb.on_pager_status(body, user_data, code, reason)
+ else:
+ acc = self._lookup_account(acc_id)
+ buddy = self._lookup_buddy(-1, to_uri)
+ if buddy:
+ buddy._cb.on_pager_status(body, user_data, code, reason)
+ else:
+ acc._cb.on_pager_status(to_uri, body, user_data, code, reason)
+
+ def _cb_on_typing(self, call_id, from_uri, to_uri, contact, is_typing,
+ acc_id):
+ call = None
+ if call_id != -1:
+ call = self._lookup_call(call_id)
+ if call:
+ call._cb.on_typing(is_typing)
+ else:
+ acc = self._lookup_account(acc_id)
+ buddy = self._lookup_buddy(-1, from_uri)
+ if buddy:
+ buddy._cb.on_typing(is_typing)
+ else:
+ acc._cb.on_typing(from_uri, contact, is_typing)
+
+ def _cb_on_mwi_info(self, acc_id, body):
+ acc = self._lookup_account(acc_id)
+ if acc:
+ return acc._cb.on_mwi_info(body)
+
+ def _cb_on_buddy_state(self, buddy_id):
+ buddy = self._lookup_buddy(buddy_id)
+ if buddy:
+ buddy._cb.on_state()
+
+#
+# Internal
+#
+
+def _cb_on_call_state(call_id, e):
+ _lib._cb_on_call_state(call_id)
+
+def _cb_on_incoming_call(acc_id, call_id, rdata):
+ _lib._cb_on_incoming_call(acc_id, call_id, rdata)
+
+def _cb_on_call_media_state(call_id):
+ _lib._cb_on_call_media_state(call_id)
+
+def _cb_on_dtmf_digit(call_id, digits):
+ _lib._cb_on_dtmf_digit(call_id, digits)
+
+def _cb_on_call_transfer_request(call_id, dst, code):
+ return _lib._cb_on_call_transfer_request(call_id, dst, code)
+
+def _cb_on_call_transfer_status(call_id, code, reason, final, cont):
+ return _lib._cb_on_call_transfer_status(call_id, code, reason,
+ final, cont)
+def _cb_on_call_replace_request(call_id, rdata, code, reason):
+ return _lib._cb_on_call_replace_request(call_id, rdata, code, reason)
+
+def _cb_on_call_replaced(old_call_id, new_call_id):
+ _lib._cb_on_call_replaced(old_call_id, new_call_id)
+
+def _cb_on_reg_state(acc_id):
+ _lib._cb_on_reg_state(acc_id)
+
+def _cb_on_incoming_subscribe(acc_id, buddy_id, from_uri, contact_uri, pres):
+ return _lib._cb_on_incoming_subscribe(acc_id, buddy_id, from_uri,
+ contact_uri, pres)
+
+def _cb_on_buddy_state(buddy_id):
+ _lib._cb_on_buddy_state(buddy_id)
+
+def _cb_on_pager(call_id, from_uri, to, contact, mime_type, body, acc_id):
+ _lib._cb_on_pager(call_id, from_uri, to, contact, mime_type, body, acc_id)
+
+def _cb_on_pager_status(call_id, to, body, user_data, status, reason, acc_id):
+ _lib._cb_on_pager_status(call_id, to, body, user_data,
+ status, reason, acc_id)
+
+def _cb_on_typing(call_id, from_uri, to, contact, is_typing, acc_id):
+ _lib._cb_on_typing(call_id, from_uri, to, contact, is_typing, acc_id)
+
+def _cb_on_mwi_info(acc_id, body):
+ _lib._cb_on_mwi_info(acc_id, body)
+
+# Worker thread
+def _worker_thread_main(arg):
+ global _lib
+ _Trace(('worker thread started..',))
+ thread_desc = 0;
+ err = _pjsua.thread_register("python worker", thread_desc)
+ _lib._err_check("thread_register()", _lib, err)
+ while _lib and _lib._quit == 0:
+ _lib.handle_events(1)
+ time.sleep(0.050)
+ if _lib:
+ _lib._quit = 2
+ _Trace(('worker thread exited..',))
+
+def _Trace(args):
+ global enable_trace
+ if enable_trace:
+ print "** ",
+ for arg in args:
+ print arg,
+ print " **"
+
diff --git a/pjsip-apps/src/python/samples/call.py b/pjsip-apps/src/python/samples/call.py
new file mode 100644
index 0000000..60f9065
--- /dev/null
+++ b/pjsip-apps/src/python/samples/call.py
@@ -0,0 +1,169 @@
+# $Id: call.py 2171 2008-07-24 09:01:33Z bennylp $
+#
+# SIP call sample.
+#
+# Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+import sys
+import pjsua as pj
+
+LOG_LEVEL=3
+current_call = None
+
+# Logging callback
+def log_cb(level, str, len):
+ print str,
+
+
+# Callback to receive events from account
+class MyAccountCallback(pj.AccountCallback):
+
+ def __init__(self, account=None):
+ pj.AccountCallback.__init__(self, account)
+
+ # Notification on incoming call
+ def on_incoming_call(self, call):
+ global current_call
+ if current_call:
+ call.answer(486, "Busy")
+ return
+
+ print "Incoming call from ", call.info().remote_uri
+ print "Press 'a' to answer"
+
+ current_call = call
+
+ call_cb = MyCallCallback(current_call)
+ current_call.set_callback(call_cb)
+
+ current_call.answer(180)
+
+
+# Callback to receive events from Call
+class MyCallCallback(pj.CallCallback):
+
+ def __init__(self, call=None):
+ pj.CallCallback.__init__(self, call)
+
+ # Notification when call state has changed
+ def on_state(self):
+ global current_call
+ print "Call with", self.call.info().remote_uri,
+ print "is", self.call.info().state_text,
+ print "last code =", self.call.info().last_code,
+ print "(" + self.call.info().last_reason + ")"
+
+ if self.call.info().state == pj.CallState.DISCONNECTED:
+ current_call = None
+ print 'Current call is', current_call
+
+ # Notification when call's media state has changed.
+ def on_media_state(self):
+ if self.call.info().media_state == pj.MediaState.ACTIVE:
+ # Connect the call to sound device
+ call_slot = self.call.info().conf_slot
+ pj.Lib.instance().conf_connect(call_slot, 0)
+ pj.Lib.instance().conf_connect(0, call_slot)
+ print "Media is now active"
+ else:
+ print "Media is inactive"
+
+# Function to make call
+def make_call(uri):
+ try:
+ print "Making call to", uri
+ return acc.make_call(uri, cb=MyCallCallback())
+ except pj.Error, e:
+ print "Exception: " + str(e)
+ return None
+
+
+# Create library instance
+lib = pj.Lib()
+
+try:
+ # Init library with default config and some customized
+ # logging config.
+ lib.init(log_cfg = pj.LogConfig(level=LOG_LEVEL, callback=log_cb))
+
+ # Create UDP transport which listens to any available port
+ transport = lib.create_transport(pj.TransportType.UDP,
+ pj.TransportConfig(0))
+ print "\nListening on", transport.info().host,
+ print "port", transport.info().port, "\n"
+
+ # Start the library
+ lib.start()
+
+ # Create local account
+ acc = lib.create_account_for_transport(transport, cb=MyAccountCallback())
+
+ # If argument is specified then make call to the URI
+ if len(sys.argv) > 1:
+ lck = lib.auto_lock()
+ current_call = make_call(sys.argv[1])
+ print 'Current call is', current_call
+ del lck
+
+ my_sip_uri = "sip:" + transport.info().host + \
+ ":" + str(transport.info().port)
+
+ # Menu loop
+ while True:
+ print "My SIP URI is", my_sip_uri
+ print "Menu: m=make call, h=hangup call, a=answer call, q=quit"
+
+ input = sys.stdin.readline().rstrip("\r\n")
+ if input == "m":
+ if current_call:
+ print "Already have another call"
+ continue
+ print "Enter destination URI to call: ",
+ input = sys.stdin.readline().rstrip("\r\n")
+ if input == "":
+ continue
+ lck = lib.auto_lock()
+ current_call = make_call(input)
+ del lck
+
+ elif input == "h":
+ if not current_call:
+ print "There is no call"
+ continue
+ current_call.hangup()
+
+ elif input == "a":
+ if not current_call:
+ print "There is no call"
+ continue
+ current_call.answer(200)
+
+ elif input == "q":
+ break
+
+ # Shutdown the library
+ transport = None
+ acc.delete()
+ acc = None
+ lib.destroy()
+ lib = None
+
+except pj.Error, e:
+ print "Exception: " + str(e)
+ lib.destroy()
+ lib = None
+
diff --git a/pjsip-apps/src/python/samples/presence.py b/pjsip-apps/src/python/samples/presence.py
new file mode 100644
index 0000000..afeaeab
--- /dev/null
+++ b/pjsip-apps/src/python/samples/presence.py
@@ -0,0 +1,175 @@
+# $Id: presence.py 2171 2008-07-24 09:01:33Z bennylp $
+#
+# Presence and instant messaging
+#
+# Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+import sys
+import pjsua as pj
+
+LOG_LEVEL = 3
+pending_pres = None
+pending_uri = None
+
+def log_cb(level, str, len):
+ print str,
+
+class MyAccountCallback(pj.AccountCallback):
+ def __init__(self, account=None):
+ pj.AccountCallback.__init__(self, account)
+
+ def on_incoming_subscribe(self, buddy, from_uri, contact_uri, pres):
+ global pending_pres, pending_uri
+ # Allow buddy to subscribe to our presence
+ if buddy:
+ return (200, None)
+ print 'Incoming SUBSCRIBE request from', from_uri
+ print 'Press "A" to accept and add, "R" to reject the request'
+ pending_pres = pres
+ pending_uri = from_uri
+ return (202, None)
+
+
+class MyBuddyCallback(pj.BuddyCallback):
+ def __init__(self, buddy=None):
+ pj.BuddyCallback.__init__(self, buddy)
+
+ def on_state(self):
+ print "Buddy", self.buddy.info().uri, "is",
+ print self.buddy.info().online_text
+
+ def on_pager(self, mime_type, body):
+ print "Instant message from", self.buddy.info().uri,
+ print "(", mime_type, "):"
+ print body
+
+ def on_pager_status(self, body, im_id, code, reason):
+ if code >= 300:
+ print "Message delivery failed for message",
+ print body, "to", self.buddy.info().uri, ":", reason
+
+ def on_typing(self, is_typing):
+ if is_typing:
+ print self.buddy.info().uri, "is typing"
+ else:
+ print self.buddy.info().uri, "stops typing"
+
+
+lib = pj.Lib()
+
+try:
+ # Init library with default config and some customized
+ # logging config.
+ lib.init(log_cfg = pj.LogConfig(level=LOG_LEVEL, callback=log_cb))
+
+ # Create UDP transport which listens to any available port
+ transport = lib.create_transport(pj.TransportType.UDP,
+ pj.TransportConfig(0))
+ print "\nListening on", transport.info().host,
+ print "port", transport.info().port, "\n"
+
+ # Start the library
+ lib.start()
+
+ # Create local account
+ acc = lib.create_account_for_transport(transport, cb=MyAccountCallback())
+ acc.set_basic_status(True)
+
+ my_sip_uri = "sip:" + transport.info().host + \
+ ":" + str(transport.info().port)
+
+ buddy = None
+
+ # Menu loop
+ while True:
+ print "My SIP URI is", my_sip_uri
+ print "Menu: a=add buddy, d=delete buddy, t=toggle", \
+ " online status, i=send IM, q=quit"
+
+ input = sys.stdin.readline().rstrip("\r\n")
+ if input == "a":
+ # Add buddy
+ print "Enter buddy URI: ",
+ input = sys.stdin.readline().rstrip("\r\n")
+ if input == "":
+ continue
+
+ buddy = acc.add_buddy(input, cb=MyBuddyCallback())
+ buddy.subscribe()
+
+ elif input == "t":
+ acc.set_basic_status(not acc.info().online_status)
+
+ elif input == "i":
+ if not buddy:
+ print "Add buddy first"
+ continue
+
+ buddy.send_typing_ind(True)
+
+ print "Type the message: ",
+ input = sys.stdin.readline().rstrip("\r\n")
+ if input == "":
+ buddy.send_typing_ind(False)
+ continue
+
+ buddy.send_pager(input)
+
+ elif input == "d":
+ if buddy:
+ buddy.delete()
+ buddy = None
+ else:
+ print 'No buddy was added'
+
+ elif input == "A":
+ if pending_pres:
+ acc.pres_notify(pending_pres, pj.SubscriptionState.ACTIVE)
+ buddy = acc.add_buddy(pending_uri, cb=MyBuddyCallback())
+ buddy.subscribe()
+ pending_pres = None
+ pending_uri = None
+ else:
+ print "No pending request"
+
+ elif input == "R":
+ if pending_pres:
+ acc.pres_notify(pending_pres, pj.SubscriptionState.TERMINATED,
+ "rejected")
+ pending_pres = None
+ pending_uri = None
+ else:
+ print "No pending request"
+
+ elif input == "q":
+ break
+
+ # Shutdown the library
+ acc.delete()
+ acc = None
+ if pending_pres:
+ acc.pres_notify(pending_pres, pj.SubscriptionState.TERMINATED,
+ "rejected")
+ transport = None
+ lib.destroy()
+ lib = None
+
+except pj.Error, e:
+ print "Exception: " + str(e)
+ lib.destroy()
+ lib = None
+
diff --git a/pjsip-apps/src/python/samples/registration.py b/pjsip-apps/src/python/samples/registration.py
new file mode 100644
index 0000000..06670da
--- /dev/null
+++ b/pjsip-apps/src/python/samples/registration.py
@@ -0,0 +1,70 @@
+# $Id: registration.py 2171 2008-07-24 09:01:33Z bennylp $
+#
+# SIP account and registration sample. In this sample, the program
+# will block to wait until registration is complete
+#
+# Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+import sys
+import pjsua as pj
+import threading
+
+
+def log_cb(level, str, len):
+ print str,
+
+class MyAccountCallback(pj.AccountCallback):
+ sem = None
+
+ def __init__(self, account):
+ pj.AccountCallback.__init__(self, account)
+
+ def wait(self):
+ self.sem = threading.Semaphore(0)
+ self.sem.acquire()
+
+ def on_reg_state(self):
+ if self.sem:
+ if self.account.info().reg_status >= 200:
+ self.sem.release()
+
+lib = pj.Lib()
+
+try:
+ lib.init(log_cfg = pj.LogConfig(level=4, callback=log_cb))
+ lib.create_transport(pj.TransportType.UDP, pj.TransportConfig(5080))
+ lib.start()
+
+ acc = lib.create_account(pj.AccountConfig("pjsip.org", "bennylp", "***"))
+
+ acc_cb = MyAccountCallback(acc)
+ acc.set_callback(acc_cb)
+ acc_cb.wait()
+
+ print "\n"
+ print "Registration complete, status=", acc.info().reg_status, \
+ "(" + acc.info().reg_reason + ")"
+ print "\nPress ENTER to quit"
+ sys.stdin.readline()
+
+ lib.destroy()
+ lib = None
+
+except pj.Error, e:
+ print "Exception: " + str(e)
+ lib.destroy()
+
diff --git a/pjsip-apps/src/python/samples/simplecall.py b/pjsip-apps/src/python/samples/simplecall.py
new file mode 100644
index 0000000..40ac28f
--- /dev/null
+++ b/pjsip-apps/src/python/samples/simplecall.py
@@ -0,0 +1,88 @@
+# $Id: simplecall.py 2171 2008-07-24 09:01:33Z bennylp $
+#
+# SIP account and registration sample. In this sample, the program
+# will block to wait until registration is complete
+#
+# Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+import sys
+import pjsua as pj
+
+# Logging callback
+def log_cb(level, str, len):
+ print str,
+
+# Callback to receive events from Call
+class MyCallCallback(pj.CallCallback):
+ def __init__(self, call=None):
+ pj.CallCallback.__init__(self, call)
+
+ # Notification when call state has changed
+ def on_state(self):
+ print "Call is ", self.call.info().state_text,
+ print "last code =", self.call.info().last_code,
+ print "(" + self.call.info().last_reason + ")"
+
+ # Notification when call's media state has changed.
+ def on_media_state(self):
+ global lib
+ if self.call.info().media_state == pj.MediaState.ACTIVE:
+ # Connect the call to sound device
+ call_slot = self.call.info().conf_slot
+ lib.conf_connect(call_slot, 0)
+ lib.conf_connect(0, call_slot)
+ print "Hello world, I can talk!"
+
+
+# Check command line argument
+if len(sys.argv) != 2:
+ print "Usage: simplecall.py <dst-URI>"
+ sys.exit(1)
+
+try:
+ # Create library instance
+ lib = pj.Lib()
+
+ # Init library with default config
+ lib.init(log_cfg = pj.LogConfig(level=3, callback=log_cb))
+
+ # Create UDP transport which listens to any available port
+ transport = lib.create_transport(pj.TransportType.UDP)
+
+ # Start the library
+ lib.start()
+
+ # Create local/user-less account
+ acc = lib.create_account_for_transport(transport)
+
+ # Make call
+ call = acc.make_call(sys.argv[1], MyCallCallback())
+
+ # Wait for ENTER before quitting
+ print "Press <ENTER> to quit"
+ input = sys.stdin.readline().rstrip("\r\n")
+
+ # We're done, shutdown the library
+ lib.destroy()
+ lib = None
+
+except pj.Error, e:
+ print "Exception: " + str(e)
+ lib.destroy()
+ lib = None
+ sys.exit(1)
+
diff --git a/pjsip-apps/src/python/setup-vc.py b/pjsip-apps/src/python/setup-vc.py
new file mode 100644
index 0000000..cab1498
--- /dev/null
+++ b/pjsip-apps/src/python/setup-vc.py
@@ -0,0 +1,80 @@
+# $Id: setup-vc.py 4122 2012-05-14 11:04:46Z bennylp $
+#
+# pjsua Setup script for Visual Studio
+#
+# Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+from distutils.core import setup, Extension
+import os
+import sys
+
+# Find version
+pj_version=""
+pj_version_major=""
+pj_version_minor=""
+pj_version_rev=""
+pj_version_suffix=""
+f = open('../../../version.mak', 'r')
+for line in f:
+ if line.find("export PJ_VERSION_MAJOR") != -1:
+ tokens=line.split("=")
+ if len(tokens)>1:
+ pj_version_major= tokens[1].strip()
+ elif line.find("export PJ_VERSION_MINOR") != -1:
+ tokens=line.split("=")
+ if len(tokens)>1:
+ pj_version_minor= line.split("=")[1].strip()
+ elif line.find("export PJ_VERSION_REV") != -1:
+ tokens=line.split("=")
+ if len(tokens)>1:
+ pj_version_rev= line.split("=")[1].strip()
+ elif line.find("export PJ_VERSION_SUFFIX") != -1:
+ tokens=line.split("=")
+ if len(tokens)>1:
+ pj_version_suffix= line.split("=")[1].strip()
+
+f.close()
+if not pj_version_major:
+ print 'Unable to get PJ_VERSION_MAJOR'
+ sys.exit(1)
+
+pj_version = pj_version_major + "." + pj_version_minor
+if pj_version_rev:
+ pj_version += "." + pj_version_rev
+if pj_version_suffix:
+ pj_version += "-" + pj_version_suffix
+
+#print 'PJ_VERSION = "'+ pj_version + '"'
+
+
+# Check that extension has been built
+if not os.access('../../lib/_pjsua.pyd', os.R_OK):
+ print 'Error: file "../../lib/_pjsua.pyd" does not exist!'
+ print ''
+ print 'Please build the extension with Visual Studio first'
+ print 'For more info, see http://trac.pjsip.org/repos/wiki/Python_SIP_Tutorial'
+ sys.exit(1)
+
+setup(name="pjsua",
+ version=pj_version,
+ description='SIP User Agent Library based on PJSIP',
+ url='http://trac.pjsip.org/repos/wiki/Python_SIP_Tutorial',
+ data_files=[('lib/site-packages', ['../../lib/_pjsua.pyd'])],
+ py_modules=["pjsua"]
+ )
+
+
diff --git a/pjsip-apps/src/python/setup.py b/pjsip-apps/src/python/setup.py
new file mode 100644
index 0000000..ae22491
--- /dev/null
+++ b/pjsip-apps/src/python/setup.py
@@ -0,0 +1,113 @@
+# $Id: setup.py 4122 2012-05-14 11:04:46Z bennylp $
+#
+# pjsua Setup script.
+#
+# Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+from distutils.core import setup, Extension
+import os
+import sys
+import platform
+
+# find pjsip version
+pj_version=""
+pj_version_major=""
+pj_version_minor=""
+pj_version_rev=""
+pj_version_suffix=""
+f = open('../../../version.mak', 'r')
+for line in f:
+ if line.find("export PJ_VERSION_MAJOR") != -1:
+ tokens=line.split("=")
+ if len(tokens)>1:
+ pj_version_major= tokens[1].strip()
+ elif line.find("export PJ_VERSION_MINOR") != -1:
+ tokens=line.split("=")
+ if len(tokens)>1:
+ pj_version_minor= line.split("=")[1].strip()
+ elif line.find("export PJ_VERSION_REV") != -1:
+ tokens=line.split("=")
+ if len(tokens)>1:
+ pj_version_rev= line.split("=")[1].strip()
+ elif line.find("export PJ_VERSION_SUFFIX") != -1:
+ tokens=line.split("=")
+ if len(tokens)>1:
+ pj_version_suffix= line.split("=")[1].strip()
+
+f.close()
+if not pj_version_major:
+ print 'Unable to get PJ_VERSION_MAJOR'
+ sys.exit(1)
+
+pj_version = pj_version_major + "." + pj_version_minor
+if pj_version_rev:
+ pj_version += "." + pj_version_rev
+if pj_version_suffix:
+ pj_version += "-" + pj_version_suffix
+
+#print 'PJ_VERSION = "'+ pj_version + '"'
+
+
+# Fill in pj_inc_dirs
+pj_inc_dirs = []
+f = os.popen("make -f helper.mak inc_dir")
+for line in f:
+ pj_inc_dirs.append(line.rstrip("\r\n"))
+f.close()
+
+# Fill in pj_lib_dirs
+pj_lib_dirs = []
+f = os.popen("make -f helper.mak lib_dir")
+for line in f:
+ pj_lib_dirs.append(line.rstrip("\r\n"))
+f.close()
+
+# Fill in pj_libs
+pj_libs = []
+f = os.popen("make -f helper.mak libs")
+for line in f:
+ pj_libs.append(line.rstrip("\r\n"))
+f.close()
+
+# Mac OS X depedencies
+if platform.system() == 'Darwin':
+ extra_link_args = ["-framework", "CoreFoundation",
+ "-framework", "AudioToolbox"]
+ # OS X Lion support
+ if platform.mac_ver()[0].startswith("10.7"):
+ extra_link_args += ["-framework", "AudioUnit"]
+else:
+ extra_link_args = []
+
+
+setup(name="pjsua",
+ version=pj_version,
+ description='SIP User Agent Library based on PJSIP',
+ url='http://trac.pjsip.org/repos/wiki/Python_SIP_Tutorial',
+ ext_modules = [Extension("_pjsua",
+ ["_pjsua.c"],
+ define_macros=[('PJ_AUTOCONF', '1'),],
+ include_dirs=pj_inc_dirs,
+ library_dirs=pj_lib_dirs,
+ libraries=pj_libs,
+ extra_link_args=extra_link_args
+ )
+ ],
+ py_modules=["pjsua"]
+ )
+
+
diff --git a/pjsip-apps/src/samples/aectest.c b/pjsip-apps/src/samples/aectest.c
new file mode 100644
index 0000000..ff95db4
--- /dev/null
+++ b/pjsip-apps/src/samples/aectest.c
@@ -0,0 +1,304 @@
+/* $Id: aectest.c 3664 2011-07-19 03:42:28Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+/**
+ * \page page_pjmedia_samples_aectest_c Samples: AEC Test (aectest.c)
+ *
+ * Play a file to speaker, run AEC, and record the microphone input
+ * to see if echo is coming.
+ *
+ * This file is pjsip-apps/src/samples/aectest.c
+ *
+ * \includelineno aectest.c
+ */
+#include <pjmedia.h>
+#include <pjlib-util.h> /* pj_getopt */
+#include <pjlib.h>
+
+#define THIS_FILE "aectest.c"
+#define PTIME 20
+#define TAIL_LENGTH 200
+
+static const char *desc =
+" FILE \n"
+" \n"
+" aectest.c \n"
+" \n"
+" PURPOSE \n"
+" \n"
+" Test the AEC effectiveness. \n"
+" \n"
+" USAGE \n"
+" \n"
+" aectest [options] <PLAY.WAV> <REC.WAV> <OUTPUT.WAV> \n"
+" \n"
+" <PLAY.WAV> is the signal played to the speaker. \n"
+" <REC.WAV> is the signal captured from the microphone. \n"
+" <OUTPUT.WAV> is the output file to store the test result \n"
+"\n"
+" options:\n"
+" -d The delay between playback and capture in ms, at least 25 ms.\n"
+" Default is 25 ms. See note below. \n"
+" -l Set the echo tail length in ms. Default is 200 ms \n"
+" -r Set repeat count (default=1) \n"
+" -a Algorithm: 0=default, 1=speex, 3=echo suppress \n"
+" -i Interactive \n"
+"\n"
+" Note that for the AEC internal buffering mechanism, it is required\n"
+" that the echoed signal (in REC.WAV) is delayed from the \n"
+" corresponding reference signal (in PLAY.WAV) at least as much as \n"
+" frame time + PJMEDIA_WSOLA_DELAY_MSEC. In this application, frame \n"
+" time is 20 ms and default PJMEDIA_WSOLA_DELAY_MSEC is 5 ms, hence \n"
+" 25 ms delay is the minimum value. \n";
+
+/*
+ * Sample session:
+ *
+ * -d 100 -a 1 ../bin/orig8.wav ../bin/echo8.wav ../bin/result8.wav
+ */
+
+static void app_perror(const char *sender, const char *title, pj_status_t st)
+{
+ char errmsg[PJ_ERR_MSG_SIZE];
+
+ pj_strerror(st, errmsg, sizeof(errmsg));
+ PJ_LOG(3,(sender, "%s: %s", title, errmsg));
+}
+
+
+/*
+ * main()
+ */
+int main(int argc, char *argv[])
+{
+ pj_caching_pool cp;
+ pjmedia_endpt *med_endpt;
+ pj_pool_t *pool;
+ pjmedia_port *wav_play;
+ pjmedia_port *wav_rec;
+ pjmedia_port *wav_out;
+ pj_status_t status;
+ pjmedia_echo_state *ec;
+ pjmedia_frame play_frame, rec_frame;
+ unsigned opt = 0;
+ unsigned latency_ms = 25;
+ unsigned tail_ms = TAIL_LENGTH;
+ pj_timestamp t0, t1;
+ int i, repeat=1, interactive=0, c;
+
+ pj_optind = 0;
+ while ((c=pj_getopt(argc, argv, "d:l:a:r:i")) !=-1) {
+ switch (c) {
+ case 'd':
+ latency_ms = atoi(pj_optarg);
+ if (latency_ms < 25) {
+ puts("Invalid delay");
+ puts(desc);
+ }
+ break;
+ case 'l':
+ tail_ms = atoi(pj_optarg);
+ break;
+ case 'a':
+ {
+ int alg = atoi(pj_optarg);
+ switch (alg) {
+ case 0:
+ opt = 0;
+ case 1:
+ opt = PJMEDIA_ECHO_SPEEX;
+ break;
+ case 3:
+ opt = PJMEDIA_ECHO_SIMPLE;
+ break;
+ default:
+ puts("Invalid algorithm");
+ puts(desc);
+ return 1;
+ }
+ }
+ break;
+ case 'r':
+ repeat = atoi(pj_optarg);
+ if (repeat < 1) {
+ puts("Invalid repeat count");
+ puts(desc);
+ return 1;
+ }
+ break;
+ case 'i':
+ interactive = 1;
+ break;
+ }
+ }
+
+ if (argc - pj_optind != 3) {
+ puts("Error: missing argument(s)");
+ puts(desc);
+ return 1;
+ }
+
+ /* Must init PJLIB first: */
+ status = pj_init();
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ /* Must create a pool factory before we can allocate any memory. */
+ pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);
+
+ /*
+ * Initialize media endpoint.
+ * This will implicitly initialize PJMEDIA too.
+ */
+ status = pjmedia_endpt_create(&cp.factory, NULL, 1, &med_endpt);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ /* Create memory pool for our file player */
+ pool = pj_pool_create( &cp.factory, /* pool factory */
+ "wav", /* pool name. */
+ 4000, /* init size */
+ 4000, /* increment size */
+ NULL /* callback on error */
+ );
+
+ /* Open wav_play */
+ status = pjmedia_wav_player_port_create(pool, argv[pj_optind], PTIME,
+ PJMEDIA_FILE_NO_LOOP, 0,
+ &wav_play);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Error opening playback WAV file", status);
+ return 1;
+ }
+
+ /* Open recorded wav */
+ status = pjmedia_wav_player_port_create(pool, argv[pj_optind+1], PTIME,
+ PJMEDIA_FILE_NO_LOOP, 0,
+ &wav_rec);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Error opening recorded WAV file", status);
+ return 1;
+ }
+
+ /* play and rec WAVs must have the same clock rate */
+ if (PJMEDIA_PIA_SRATE(&wav_play->info) != PJMEDIA_PIA_SRATE(&wav_rec->info)) {
+ puts("Error: clock rate mismatch in the WAV files");
+ return 1;
+ }
+
+ /* .. and channel count */
+ if (PJMEDIA_PIA_CCNT(&wav_play->info) != PJMEDIA_PIA_CCNT(&wav_rec->info)) {
+ puts("Error: clock rate mismatch in the WAV files");
+ return 1;
+ }
+
+ /* Create output wav */
+ status = pjmedia_wav_writer_port_create(pool, argv[pj_optind+2],
+ PJMEDIA_PIA_SRATE(&wav_play->info),
+ PJMEDIA_PIA_CCNT(&wav_play->info),
+ PJMEDIA_PIA_SPF(&wav_play->info),
+ PJMEDIA_PIA_BITS(&wav_play->info),
+ 0, 0, &wav_out);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Error opening output WAV file", status);
+ return 1;
+ }
+
+ /* Create echo canceller */
+ status = pjmedia_echo_create2(pool, PJMEDIA_PIA_SRATE(&wav_play->info),
+ PJMEDIA_PIA_CCNT(&wav_play->info),
+ PJMEDIA_PIA_SPF(&wav_play->info),
+ tail_ms, latency_ms,
+ opt, &ec);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Error creating EC", status);
+ return 1;
+ }
+
+
+ /* Processing loop */
+ play_frame.buf = pj_pool_alloc(pool, PJMEDIA_PIA_SPF(&wav_play->info)<<1);
+ rec_frame.buf = pj_pool_alloc(pool, PJMEDIA_PIA_SPF(&wav_play->info)<<1);
+ pj_get_timestamp(&t0);
+ for (i=0; i < repeat; ++i) {
+ for (;;) {
+ play_frame.size = PJMEDIA_PIA_SPF(&wav_play->info) << 1;
+ status = pjmedia_port_get_frame(wav_play, &play_frame);
+ if (status != PJ_SUCCESS)
+ break;
+
+ status = pjmedia_echo_playback(ec, (short*)play_frame.buf);
+
+ rec_frame.size = PJMEDIA_PIA_SPF(&wav_play->info) << 1;
+ status = pjmedia_port_get_frame(wav_rec, &rec_frame);
+ if (status != PJ_SUCCESS)
+ break;
+
+ status = pjmedia_echo_capture(ec, (short*)rec_frame.buf, 0);
+
+ //status = pjmedia_echo_cancel(ec, (short*)rec_frame.buf,
+ // (short*)play_frame.buf, 0, NULL);
+
+ pjmedia_port_put_frame(wav_out, &rec_frame);
+ }
+
+ pjmedia_wav_player_port_set_pos(wav_play, 0);
+ pjmedia_wav_player_port_set_pos(wav_rec, 0);
+ }
+ pj_get_timestamp(&t1);
+
+ i = pjmedia_wav_writer_port_get_pos(wav_out) / sizeof(pj_int16_t) * 1000 /
+ (PJMEDIA_PIA_SRATE(&wav_out->info) * PJMEDIA_PIA_CCNT(&wav_out->info));
+ PJ_LOG(3,(THIS_FILE, "Processed %3d.%03ds audio",
+ i / 1000, i % 1000));
+ PJ_LOG(3,(THIS_FILE, "Completed in %u msec\n", pj_elapsed_msec(&t0, &t1)));
+
+ /* Destroy file port(s) */
+ status = pjmedia_port_destroy( wav_play );
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+ status = pjmedia_port_destroy( wav_rec );
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+ status = pjmedia_port_destroy( wav_out );
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ /* Destroy ec */
+ pjmedia_echo_destroy(ec);
+
+ /* Release application pool */
+ pj_pool_release( pool );
+
+ /* Destroy media endpoint. */
+ pjmedia_endpt_destroy( med_endpt );
+
+ /* Destroy pool factory */
+ pj_caching_pool_destroy( &cp );
+
+ /* Shutdown PJLIB */
+ pj_shutdown();
+
+ if (interactive) {
+ char s[10], *dummy;
+ puts("ENTER to quit");
+ dummy = fgets(s, sizeof(s), stdin);
+ }
+
+ /* Done. */
+ return 0;
+}
+
diff --git a/pjsip-apps/src/samples/auddemo.c b/pjsip-apps/src/samples/auddemo.c
new file mode 100644
index 0000000..c4e3562
--- /dev/null
+++ b/pjsip-apps/src/samples/auddemo.c
@@ -0,0 +1,582 @@
+/* $Id: auddemo.c 3664 2011-07-19 03:42:28Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <pjmedia-audiodev/audiodev.h>
+#include <pjmedia-audiodev/audiotest.h>
+#include <pjmedia.h>
+#include <pjlib.h>
+#include <pjlib-util.h>
+
+#define THIS_FILE "auddemo.c"
+#define MAX_DEVICES 64
+#define WAV_FILE "auddemo.wav"
+
+
+static unsigned dev_count;
+static unsigned playback_lat = PJMEDIA_SND_DEFAULT_PLAY_LATENCY;
+static unsigned capture_lat = PJMEDIA_SND_DEFAULT_REC_LATENCY;
+
+static void app_perror(const char *title, pj_status_t status)
+{
+ char errmsg[PJ_ERR_MSG_SIZE];
+
+ pj_strerror(status, errmsg, sizeof(errmsg));
+ printf( "%s: %s (err=%d)\n",
+ title, errmsg, status);
+}
+
+static void list_devices(void)
+{
+ unsigned i;
+ pj_status_t status;
+
+ dev_count = pjmedia_aud_dev_count();
+ if (dev_count == 0) {
+ PJ_LOG(3,(THIS_FILE, "No devices found"));
+ return;
+ }
+
+ PJ_LOG(3,(THIS_FILE, "Found %d devices:", dev_count));
+
+ for (i=0; i<dev_count; ++i) {
+ pjmedia_aud_dev_info info;
+
+ status = pjmedia_aud_dev_get_info(i, &info);
+ if (status != PJ_SUCCESS)
+ continue;
+
+ PJ_LOG(3,(THIS_FILE," %2d: %s [%s] (%d/%d)",
+ i, info.driver, info.name, info.input_count, info.output_count));
+ }
+}
+
+static const char *decode_caps(unsigned caps)
+{
+ static char text[200];
+ unsigned i;
+
+ text[0] = '\0';
+
+ for (i=0; i<31; ++i) {
+ if ((1 << i) & caps) {
+ const char *capname;
+ capname = pjmedia_aud_dev_cap_name((pjmedia_aud_dev_cap)(1 << i),
+ NULL);
+ strcat(text, capname);
+ strcat(text, " ");
+ }
+ }
+
+ return text;
+}
+
+static void show_dev_info(unsigned index)
+{
+#define H "%-20s"
+ pjmedia_aud_dev_info info;
+ char formats[200];
+ pj_status_t status;
+
+ if (index >= dev_count) {
+ PJ_LOG(1,(THIS_FILE, "Error: invalid index %u", index));
+ return;
+ }
+
+ status = pjmedia_aud_dev_get_info(index, &info);
+ if (status != PJ_SUCCESS) {
+ app_perror("pjmedia_aud_dev_get_info() error", status);
+ return;
+ }
+
+ PJ_LOG(3, (THIS_FILE, "Device at index %u:", index));
+ PJ_LOG(3, (THIS_FILE, "-------------------------"));
+
+ PJ_LOG(3, (THIS_FILE, H": %u (0x%x)", "ID", index, index));
+ PJ_LOG(3, (THIS_FILE, H": %s", "Name", info.name));
+ PJ_LOG(3, (THIS_FILE, H": %s", "Driver", info.driver));
+ PJ_LOG(3, (THIS_FILE, H": %u", "Input channels", info.input_count));
+ PJ_LOG(3, (THIS_FILE, H": %u", "Output channels", info.output_count));
+ PJ_LOG(3, (THIS_FILE, H": %s", "Capabilities", decode_caps(info.caps)));
+
+ formats[0] = '\0';
+ if (info.caps & PJMEDIA_AUD_DEV_CAP_EXT_FORMAT) {
+ unsigned i;
+
+ for (i=0; i<info.ext_fmt_cnt; ++i) {
+ char bitrate[32];
+
+ switch (info.ext_fmt[i].id) {
+ case PJMEDIA_FORMAT_L16:
+ strcat(formats, "L16/");
+ break;
+ case PJMEDIA_FORMAT_PCMA:
+ strcat(formats, "PCMA/");
+ break;
+ case PJMEDIA_FORMAT_PCMU:
+ strcat(formats, "PCMU/");
+ break;
+ case PJMEDIA_FORMAT_AMR:
+ strcat(formats, "AMR/");
+ break;
+ case PJMEDIA_FORMAT_G729:
+ strcat(formats, "G729/");
+ break;
+ case PJMEDIA_FORMAT_ILBC:
+ strcat(formats, "ILBC/");
+ break;
+ default:
+ strcat(formats, "unknown/");
+ break;
+ }
+ sprintf(bitrate, "%u", info.ext_fmt[i].det.aud.avg_bps);
+ strcat(formats, bitrate);
+ strcat(formats, " ");
+ }
+ }
+ PJ_LOG(3, (THIS_FILE, H": %s", "Extended formats", formats));
+
+#undef H
+}
+
+static void test_device(pjmedia_dir dir, unsigned rec_id, unsigned play_id,
+ unsigned clock_rate, unsigned ptime,
+ unsigned chnum)
+{
+ pjmedia_aud_param param;
+ pjmedia_aud_test_results result;
+ pj_status_t status;
+
+ if (dir & PJMEDIA_DIR_CAPTURE) {
+ status = pjmedia_aud_dev_default_param(rec_id, &param);
+ } else {
+ status = pjmedia_aud_dev_default_param(play_id, &param);
+ }
+
+ if (status != PJ_SUCCESS) {
+ app_perror("pjmedia_aud_dev_default_param()", status);
+ return;
+ }
+
+ param.dir = dir;
+ param.rec_id = rec_id;
+ param.play_id = play_id;
+ param.clock_rate = clock_rate;
+ param.channel_count = chnum;
+ param.samples_per_frame = clock_rate * chnum * ptime / 1000;
+
+ /* Latency settings */
+ param.flags |= (PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY |
+ PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY);
+ param.input_latency_ms = capture_lat;
+ param.output_latency_ms = playback_lat;
+
+ PJ_LOG(3,(THIS_FILE, "Performing test.."));
+
+ status = pjmedia_aud_test(&param, &result);
+ if (status != PJ_SUCCESS) {
+ app_perror("Test has completed with error", status);
+ return;
+ }
+
+ PJ_LOG(3,(THIS_FILE, "Done. Result:"));
+
+ if (dir & PJMEDIA_DIR_CAPTURE) {
+ if (result.rec.frame_cnt==0) {
+ PJ_LOG(1,(THIS_FILE, "Error: no frames captured!"));
+ } else {
+ PJ_LOG(3,(THIS_FILE, " %-20s: interval (min/max/avg/dev)=%u/%u/%u/%u, burst=%u",
+ "Recording result",
+ result.rec.min_interval,
+ result.rec.max_interval,
+ result.rec.avg_interval,
+ result.rec.dev_interval,
+ result.rec.max_burst));
+ }
+ }
+
+ if (dir & PJMEDIA_DIR_PLAYBACK) {
+ if (result.play.frame_cnt==0) {
+ PJ_LOG(1,(THIS_FILE, "Error: no playback!"));
+ } else {
+ PJ_LOG(3,(THIS_FILE, " %-20s: interval (min/max/avg/dev)=%u/%u/%u/%u, burst=%u",
+ "Playback result",
+ result.play.min_interval,
+ result.play.max_interval,
+ result.play.avg_interval,
+ result.play.dev_interval,
+ result.play.max_burst));
+ }
+ }
+
+ if (dir==PJMEDIA_DIR_CAPTURE_PLAYBACK) {
+ if (result.rec_drift_per_sec == 0) {
+ PJ_LOG(3,(THIS_FILE, " No clock drift detected"));
+ } else {
+ const char *which = result.rec_drift_per_sec>=0 ? "faster" : "slower";
+ unsigned drift = result.rec_drift_per_sec>=0 ?
+ result.rec_drift_per_sec :
+ -result.rec_drift_per_sec;
+
+ PJ_LOG(3,(THIS_FILE, " Clock drifts detected. Capture device "
+ "is running %d samples per second %s "
+ "than the playback device",
+ drift, which));
+ }
+ }
+}
+
+
+static pj_status_t wav_rec_cb(void *user_data, pjmedia_frame *frame)
+{
+ return pjmedia_port_put_frame((pjmedia_port*)user_data, frame);
+}
+
+static void record(unsigned rec_index, const char *filename)
+{
+ pj_pool_t *pool = NULL;
+ pjmedia_port *wav = NULL;
+ pjmedia_aud_param param;
+ pjmedia_aud_stream *strm = NULL;
+ char line[10], *dummy;
+ pj_status_t status;
+
+ if (filename == NULL)
+ filename = WAV_FILE;
+
+ pool = pj_pool_create(pjmedia_aud_subsys_get_pool_factory(), "wav",
+ 1000, 1000, NULL);
+
+ status = pjmedia_wav_writer_port_create(pool, filename, 16000,
+ 1, 320, 16, 0, 0, &wav);
+ if (status != PJ_SUCCESS) {
+ app_perror("Error creating WAV file", status);
+ goto on_return;
+ }
+
+ status = pjmedia_aud_dev_default_param(rec_index, &param);
+ if (status != PJ_SUCCESS) {
+ app_perror("pjmedia_aud_dev_default_param()", status);
+ goto on_return;
+ }
+
+ param.dir = PJMEDIA_DIR_CAPTURE;
+ param.clock_rate = PJMEDIA_PIA_SRATE(&wav->info);
+ param.samples_per_frame = PJMEDIA_PIA_SPF(&wav->info);
+ param.channel_count = PJMEDIA_PIA_CCNT(&wav->info);
+ param.bits_per_sample = PJMEDIA_PIA_BITS(&wav->info);
+
+ status = pjmedia_aud_stream_create(&param, &wav_rec_cb, NULL, wav,
+ &strm);
+ if (status != PJ_SUCCESS) {
+ app_perror("Error opening the sound device", status);
+ goto on_return;
+ }
+
+ status = pjmedia_aud_stream_start(strm);
+ if (status != PJ_SUCCESS) {
+ app_perror("Error starting the sound device", status);
+ goto on_return;
+ }
+
+ PJ_LOG(3,(THIS_FILE, "Recording started, press ENTER to stop"));
+ dummy = fgets(line, sizeof(line), stdin);
+
+on_return:
+ if (strm) {
+ pjmedia_aud_stream_stop(strm);
+ pjmedia_aud_stream_destroy(strm);
+ }
+ if (wav)
+ pjmedia_port_destroy(wav);
+ if (pool)
+ pj_pool_release(pool);
+}
+
+
+static pj_status_t wav_play_cb(void *user_data, pjmedia_frame *frame)
+{
+ return pjmedia_port_get_frame((pjmedia_port*)user_data, frame);
+}
+
+
+static void play_file(unsigned play_index, const char *filename)
+{
+ pj_pool_t *pool = NULL;
+ pjmedia_port *wav = NULL;
+ pjmedia_aud_param param;
+ pjmedia_aud_stream *strm = NULL;
+ char line[10], *dummy;
+ pj_status_t status;
+
+ if (filename == NULL)
+ filename = WAV_FILE;
+
+ pool = pj_pool_create(pjmedia_aud_subsys_get_pool_factory(), "wav",
+ 1000, 1000, NULL);
+
+ status = pjmedia_wav_player_port_create(pool, filename, 20, 0, 0, &wav);
+ if (status != PJ_SUCCESS) {
+ app_perror("Error opening WAV file", status);
+ goto on_return;
+ }
+
+ status = pjmedia_aud_dev_default_param(play_index, &param);
+ if (status != PJ_SUCCESS) {
+ app_perror("pjmedia_aud_dev_default_param()", status);
+ goto on_return;
+ }
+
+ param.dir = PJMEDIA_DIR_PLAYBACK;
+ param.clock_rate = PJMEDIA_PIA_SRATE(&wav->info);
+ param.samples_per_frame = PJMEDIA_PIA_SPF(&wav->info);
+ param.channel_count = PJMEDIA_PIA_CCNT(&wav->info);
+ param.bits_per_sample = PJMEDIA_PIA_BITS(&wav->info);
+
+ status = pjmedia_aud_stream_create(&param, NULL, &wav_play_cb, wav,
+ &strm);
+ if (status != PJ_SUCCESS) {
+ app_perror("Error opening the sound device", status);
+ goto on_return;
+ }
+
+ status = pjmedia_aud_stream_start(strm);
+ if (status != PJ_SUCCESS) {
+ app_perror("Error starting the sound device", status);
+ goto on_return;
+ }
+
+ PJ_LOG(3,(THIS_FILE, "Playback started, press ENTER to stop"));
+ dummy = fgets(line, sizeof(line), stdin);
+
+on_return:
+ if (strm) {
+ pjmedia_aud_stream_stop(strm);
+ pjmedia_aud_stream_destroy(strm);
+ }
+ if (wav)
+ pjmedia_port_destroy(wav);
+ if (pool)
+ pj_pool_release(pool);
+}
+
+
+static void print_menu(void)
+{
+ puts("");
+ puts("Audio demo menu:");
+ puts("-------------------------------");
+ puts(" l List devices");
+ puts(" R Refresh devices");
+ puts(" i ID Show device info for device ID");
+ puts(" t RID PID CR PTIM [CH] Perform test on the device:");
+ puts(" RID: record device ID (-1 for no)");
+ puts(" PID: playback device ID (-1 for no)");
+ puts(" CR: clock rate");
+ puts(" PTIM: ptime in ms");
+ puts(" CH: # of channels");
+ puts(" r RID [FILE] Record capture device RID to WAV file");
+ puts(" p PID [FILE] Playback WAV file to device ID PID");
+ puts(" d [RLAT PLAT] Get/set sound device latencies (in ms):");
+ puts(" Specify no param to get current latencies setting");
+ puts(" RLAT: record latency (-1 for default)");
+ puts(" PLAT: playback latency (-1 for default)");
+ puts(" v Toggle log verbosity");
+ puts(" q Quit");
+ puts("");
+ printf("Enter selection: ");
+ fflush(stdout);
+}
+
+int main()
+{
+ pj_caching_pool cp;
+ pj_bool_t done = PJ_FALSE;
+ pj_status_t status;
+
+ /* Init pjlib */
+ status = pj_init();
+ PJ_ASSERT_RETURN(status==PJ_SUCCESS, 1);
+
+ pj_log_set_decor(PJ_LOG_HAS_NEWLINE);
+
+ /* Must create a pool factory before we can allocate any memory. */
+ pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);
+
+ status = pjmedia_aud_subsys_init(&cp.factory);
+ if (status != PJ_SUCCESS) {
+ app_perror("pjmedia_aud_subsys_init()", status);
+ pj_caching_pool_destroy(&cp);
+ pj_shutdown();
+ return 1;
+ }
+
+ list_devices();
+
+ while (!done) {
+ char line[80];
+
+ print_menu();
+
+ if (fgets(line, sizeof(line), stdin)==NULL)
+ break;
+
+ switch (line[0]) {
+ case 'l':
+ list_devices();
+ break;
+
+ case 'R':
+ pjmedia_aud_dev_refresh();
+ puts("Audio device list refreshed.");
+ break;
+
+ case 'i':
+ {
+ unsigned dev_index;
+ if (sscanf(line+2, "%u", &dev_index) != 1) {
+ puts("error: device ID required");
+ break;
+ }
+ show_dev_info(dev_index);
+ }
+ break;
+
+ case 't':
+ {
+ pjmedia_dir dir;
+ int rec_id, play_id;
+ unsigned clock_rate, ptime, chnum;
+ int cnt;
+
+ cnt = sscanf(line+2, "%d %d %u %u %u", &rec_id, &play_id,
+ &clock_rate, &ptime, &chnum);
+ if (cnt < 4) {
+ puts("error: not enough parameters");
+ break;
+ }
+ if (clock_rate < 8000 || clock_rate > 128000) {
+ puts("error: invalid clock rate");
+ break;
+ }
+ if (ptime < 10 || ptime > 500) {
+ puts("error: invalid ptime");
+ break;
+ }
+ if (cnt==5) {
+ if (chnum < 1 || chnum > 4) {
+ puts("error: invalid number of channels");
+ break;
+ }
+ } else {
+ chnum = 1;
+ }
+
+ if (rec_id >= 0 && rec_id < (int)dev_count) {
+ if (play_id >= 0 && play_id < (int)dev_count)
+ dir = PJMEDIA_DIR_CAPTURE_PLAYBACK;
+ else
+ dir = PJMEDIA_DIR_CAPTURE;
+ } else if (play_id >= 0 && play_id < (int)dev_count) {
+ dir = PJMEDIA_DIR_PLAYBACK;
+ } else {
+ puts("error: at least one valid device index required");
+ break;
+ }
+
+ test_device(dir, rec_id, play_id, clock_rate, ptime, chnum);
+
+ }
+ break;
+
+ case 'r':
+ /* record */
+ {
+ int index;
+ char filename[80];
+ int count;
+
+ count = sscanf(line+2, "%d %s", &index, filename);
+ if (count==1)
+ record(index, NULL);
+ else if (count==2)
+ record(index, filename);
+ else
+ puts("error: invalid command syntax");
+ }
+ break;
+
+ case 'p':
+ /* playback */
+ {
+ int index;
+ char filename[80];
+ int count;
+
+ count = sscanf(line+2, "%d %s", &index, filename);
+ if (count==1)
+ play_file(index, NULL);
+ else if (count==2)
+ play_file(index, filename);
+ else
+ puts("error: invalid command syntax");
+ }
+ break;
+
+ case 'd':
+ /* latencies */
+ {
+ int rec_lat, play_lat;
+
+ if (sscanf(line+2, "%d %d", &rec_lat, &play_lat) == 2) {
+ capture_lat = (unsigned)
+ (rec_lat>=0? rec_lat:PJMEDIA_SND_DEFAULT_REC_LATENCY);
+ playback_lat = (unsigned)
+ (play_lat >= 0? play_lat : PJMEDIA_SND_DEFAULT_PLAY_LATENCY);
+ printf("Recording latency=%ums, playback latency=%ums",
+ capture_lat, playback_lat);
+ } else {
+ printf("Current latencies: record=%ums, playback=%ums",
+ capture_lat, playback_lat);
+ }
+ puts("");
+ }
+ break;
+
+ case 'v':
+ if (pj_log_get_level() <= 3) {
+ pj_log_set_level(5);
+ puts("Logging set to detail");
+ } else {
+ pj_log_set_level(3);
+ puts("Logging set to quiet");
+ }
+ break;
+
+ case 'q':
+ done = PJ_TRUE;
+ break;
+ }
+ }
+
+ pj_caching_pool_destroy(&cp);
+ pj_shutdown();
+ return 0;
+}
+
+
diff --git a/pjsip-apps/src/samples/aviplay.c b/pjsip-apps/src/samples/aviplay.c
new file mode 100644
index 0000000..2ac904e
--- /dev/null
+++ b/pjsip-apps/src/samples/aviplay.c
@@ -0,0 +1,560 @@
+/* $Id: aviplay.c 4051 2012-04-13 08:16:30Z ming $ */
+/*
+ * Copyright (C) 2010-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <pjmedia.h>
+#include <pjmedia/converter.h>
+#include <pjmedia-codec.h>
+#include <pjlib-util.h>
+#include <pjlib.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "util.h"
+
+/**
+ * \page page_pjmedia_samples_aviplay_c Samples: Playing AVI File to
+ * Video and Sound Devices
+ *
+ * This is a very simple example to use the @ref PJMEDIA_FILE_PLAY,
+ * @ref PJMED_SND_PORT, and @ref PJMEDIA_VID_PORT. In this example, we
+ * open the file, video, and sound devices, then connect the file to both
+ * video and sound devices to play the contents of the file.
+ *
+ *
+ * This file is pjsip-apps/src/samples/aviplay.c
+ *
+ * \includelineno aviplay.c
+ */
+
+
+/*
+ * aviplay.c
+ *
+ * PURPOSE:
+ * Play a AVI file to video and sound devices.
+ *
+ * USAGE:
+ * aviplay FILE.AVI
+ */
+
+
+#if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
+
+
+/* For logging purpose. */
+#define THIS_FILE "aviplay.c"
+
+static const char *desc =
+" FILE \n"
+" \n"
+" aviplay.c \n"
+" \n"
+" PURPOSE \n"
+" \n"
+" Demonstrate how to play a AVI file. \n"
+" \n"
+" USAGE \n"
+" \n"
+" aviplay FILE.AVI \n";
+
+struct codec_fmt {
+ pj_uint32_t pjmedia_id;
+ const char *codec_id;
+ /* Do we need to convert the decoded frame? */
+ pj_bool_t need_conversion;
+ /* If conversion is needed, dst_fmt indicates the destination format */
+ pjmedia_format_id dst_fmt;
+} codec_fmts[] = {{PJMEDIA_FORMAT_MJPEG, "mjpeg",
+ PJ_TRUE , PJMEDIA_FORMAT_I420},
+ {PJMEDIA_FORMAT_H263 , "h263" ,
+ PJ_FALSE, 0},
+ {PJMEDIA_FORMAT_MPEG4, "mp4v"},
+ {PJMEDIA_FORMAT_H264 , "h264"}
+ };
+
+typedef struct avi_port_t
+{
+ pjmedia_vid_port *vid_port;
+ pjmedia_snd_port *snd_port;
+ pj_bool_t is_running;
+ pj_bool_t is_quitting;
+} avi_port_t;
+
+typedef struct codec_port_data_t
+{
+ pjmedia_vid_codec *codec;
+ pjmedia_port *src_port;
+ pj_uint8_t *enc_buf;
+ pj_size_t enc_buf_size;
+
+ pjmedia_converter *conv;
+} codec_port_data_t;
+
+static pj_status_t avi_event_cb(pjmedia_event *event,
+ void *user_data)
+{
+ avi_port_t *ap = (avi_port_t *)user_data;
+
+ switch (event->type) {
+ case PJMEDIA_EVENT_WND_CLOSED:
+ ap->is_quitting = PJ_TRUE;
+ break;
+ case PJMEDIA_EVENT_MOUSE_BTN_DOWN:
+ if (ap->is_running) {
+ pjmedia_vid_port_stop(ap->vid_port);
+ if (ap->snd_port)
+ pjmedia_aud_stream_stop(
+ pjmedia_snd_port_get_snd_stream(ap->snd_port));
+ } else {
+ pjmedia_vid_port_start(ap->vid_port);
+ if (ap->snd_port)
+ pjmedia_aud_stream_start(
+ pjmedia_snd_port_get_snd_stream(ap->snd_port));
+ }
+ ap->is_running = !ap->is_running;
+ break;
+ default:
+ return PJ_SUCCESS;
+ }
+
+ /* We handled the event on our own, so return non-PJ_SUCCESS here */
+ return -1;
+}
+
+static pj_status_t codec_get_frame(pjmedia_port *port,
+ pjmedia_frame *frame)
+{
+ codec_port_data_t *port_data = (codec_port_data_t*)port->port_data.pdata;
+ pjmedia_vid_codec *codec = port_data->codec;
+ pjmedia_frame enc_frame;
+ pj_status_t status;
+
+ enc_frame.buf = port_data->enc_buf;
+ enc_frame.size = port_data->enc_buf_size;
+
+ if (port_data->conv) {
+ pj_size_t frame_size = frame->size;
+
+ status = pjmedia_port_get_frame(port_data->src_port, frame);
+ if (status != PJ_SUCCESS) goto on_error;
+
+ status = pjmedia_vid_codec_decode(codec, 1, frame,
+ frame->size, &enc_frame);
+ if (status != PJ_SUCCESS) goto on_error;
+
+ frame->size = frame_size;
+ status = pjmedia_converter_convert(port_data->conv, &enc_frame, frame);
+ if (status != PJ_SUCCESS) goto on_error;
+
+ return PJ_SUCCESS;
+ }
+
+ status = pjmedia_port_get_frame(port_data->src_port, &enc_frame);
+ if (status != PJ_SUCCESS) goto on_error;
+
+ status = pjmedia_vid_codec_decode(codec, 1, &enc_frame,
+ frame->size, frame);
+ if (status != PJ_SUCCESS) goto on_error;
+
+ return PJ_SUCCESS;
+
+on_error:
+ pj_perror(3, THIS_FILE, status, "codec_get_frame() error");
+ return status;
+}
+
+static int aviplay(pj_pool_t *pool, const char *fname)
+{
+ pjmedia_vid_port *renderer=NULL;
+ pjmedia_vid_port_param param;
+ const pjmedia_video_format_info *vfi;
+ pjmedia_video_format_detail *vfd;
+ pjmedia_snd_port *snd_port = NULL;
+ pj_status_t status;
+ int rc = 0;
+ pjmedia_avi_streams *avi_streams;
+ pjmedia_avi_stream *vid_stream, *aud_stream;
+ pjmedia_port *vid_port = NULL, *aud_port = NULL;
+ pjmedia_vid_codec *codec=NULL;
+ avi_port_t avi_port;
+
+ pj_bzero(&avi_port, sizeof(avi_port));
+
+ status = pjmedia_avi_player_create_streams(pool, fname, 0, &avi_streams);
+ if (status != PJ_SUCCESS) {
+ PJ_PERROR(2,("", status, " Error playing %s", fname));
+ rc = 210; goto on_return;
+ }
+
+ vid_stream = pjmedia_avi_streams_get_stream_by_media(avi_streams,
+ 0,
+ PJMEDIA_TYPE_VIDEO);
+ vid_port = pjmedia_avi_stream_get_port(vid_stream);
+
+ if (vid_port) {
+ pjmedia_vid_port_param_default(&param);
+
+ status = pjmedia_vid_dev_default_param(pool,
+ PJMEDIA_VID_DEFAULT_RENDER_DEV,
+ &param.vidparam);
+ if (status != PJ_SUCCESS) {
+ rc = 220; goto on_return;
+ }
+
+ /* Create renderer, set it to active */
+ param.active = PJ_TRUE;
+ param.vidparam.dir = PJMEDIA_DIR_RENDER;
+ vfd = pjmedia_format_get_video_format_detail(&vid_port->info.fmt,
+ PJ_TRUE);
+ pjmedia_format_init_video(&param.vidparam.fmt,
+ vid_port->info.fmt.id,
+ vfd->size.w, vfd->size.h,
+ vfd->fps.num, vfd->fps.denum);
+
+ vfi = pjmedia_get_video_format_info(
+ pjmedia_video_format_mgr_instance(),
+ vid_port->info.fmt.id);
+ /* Check whether the frame is encoded */
+ if (!vfi || vfi->bpp == 0) {
+ /* Yes, prepare codec */
+ pj_str_t codec_id_st;
+ unsigned info_cnt = 1, i, k;
+ const pjmedia_vid_codec_info *codec_info;
+ pj_str_t port_name = {"codec", 5};
+ pj_uint8_t *enc_buf = NULL;
+ pj_size_t enc_buf_size = 0;
+ pjmedia_vid_dev_info rdr_info;
+ pjmedia_port codec_port;
+ codec_port_data_t codec_port_data;
+ pjmedia_vid_codec_param codec_param;
+ struct codec_fmt *codecp = NULL;
+
+ /* Lookup codec */
+ for (i = 0; i < sizeof(codec_fmts)/sizeof(codec_fmts[0]); i++) {
+ if (vid_port->info.fmt.id == codec_fmts[i].pjmedia_id) {
+ codecp = &codec_fmts[i];
+ break;
+ }
+ }
+ if (!codecp) {
+ rc = 242; goto on_return;
+ }
+ pj_cstr(&codec_id_st, codecp->codec_id);
+ status = pjmedia_vid_codec_mgr_find_codecs_by_id(NULL,
+ &codec_id_st,
+ &info_cnt,
+ &codec_info,
+ NULL);
+ if (status != PJ_SUCCESS) {
+ rc = 245; goto on_return;
+ }
+ status = pjmedia_vid_codec_mgr_get_default_param(NULL, codec_info,
+ &codec_param);
+ if (status != PJ_SUCCESS) {
+ rc = 246; goto on_return;
+ }
+
+ pjmedia_format_copy(&codec_param.enc_fmt, &param.vidparam.fmt);
+
+ pjmedia_vid_dev_get_info(param.vidparam.rend_id, &rdr_info);
+ for (i=0; i<codec_info->dec_fmt_id_cnt; ++i) {
+ for (k=0; k<rdr_info.fmt_cnt; ++k) {
+ if (codec_info->dec_fmt_id[i]==(int)rdr_info.fmt[k].id)
+ {
+ param.vidparam.fmt.id = codec_info->dec_fmt_id[i];
+ i = codec_info->dec_fmt_id_cnt;
+ break;
+ }
+ }
+ }
+
+ /* Open codec */
+ status = pjmedia_vid_codec_mgr_alloc_codec(NULL, codec_info,
+ &codec);
+ if (status != PJ_SUCCESS) {
+ rc = 250; goto on_return;
+ }
+
+ status = pjmedia_vid_codec_init(codec, pool);
+ if (status != PJ_SUCCESS) {
+ rc = 251; goto on_return;
+ }
+
+ pjmedia_format_copy(&codec_param.dec_fmt, &param.vidparam.fmt);
+ codec_param.dir = PJMEDIA_DIR_DECODING;
+ codec_param.packing = PJMEDIA_VID_PACKING_WHOLE;
+ status = pjmedia_vid_codec_open(codec, &codec_param);
+ if (status != PJ_SUCCESS) {
+ rc = 252; goto on_return;
+ }
+
+ /* Alloc encoding buffer */
+ enc_buf_size = codec_param.dec_fmt.det.vid.size.w *
+ codec_param.dec_fmt.det.vid.size.h * 4
+ + 16; /*< padding, just in case */
+ enc_buf = pj_pool_alloc(pool,enc_buf_size);
+
+ /* Init codec port */
+ pj_bzero(&codec_port, sizeof(codec_port));
+ status = pjmedia_port_info_init2(&codec_port.info, &port_name,
+ 0x1234,
+ PJMEDIA_DIR_ENCODING,
+ &codec_param.dec_fmt);
+ if (status != PJ_SUCCESS) {
+ rc = 260; goto on_return;
+ }
+ pj_bzero(&codec_port_data, sizeof(codec_port_data));
+ codec_port_data.codec = codec;
+ codec_port_data.src_port = vid_port;
+ codec_port_data.enc_buf = enc_buf;
+ codec_port_data.enc_buf_size = enc_buf_size;
+
+ codec_port.get_frame = &codec_get_frame;
+ codec_port.port_data.pdata = &codec_port_data;
+
+ /* Check whether we need to convert the decoded frame */
+ if (codecp->need_conversion) {
+ pjmedia_conversion_param conv_param;
+
+ pjmedia_format_copy(&conv_param.src, &param.vidparam.fmt);
+ pjmedia_format_copy(&conv_param.dst, &param.vidparam.fmt);
+ conv_param.dst.id = codecp->dst_fmt;
+ param.vidparam.fmt.id = conv_param.dst.id;
+
+ status = pjmedia_converter_create(NULL, pool, &conv_param,
+ &codec_port_data.conv);
+ if (status != PJ_SUCCESS) {
+ rc = 270; goto on_return;
+ }
+ }
+
+ status = pjmedia_vid_port_create(pool, &param, &renderer);
+ if (status != PJ_SUCCESS) {
+ rc = 230; goto on_return;
+ }
+
+ status = pjmedia_vid_port_connect(renderer, &codec_port,
+ PJ_FALSE);
+ } else {
+ status = pjmedia_vid_port_create(pool, &param, &renderer);
+ if (status != PJ_SUCCESS) {
+ rc = 230; goto on_return;
+ }
+
+ /* Connect avi port to renderer */
+ status = pjmedia_vid_port_connect(renderer, vid_port,
+ PJ_FALSE);
+ }
+
+ if (status != PJ_SUCCESS) {
+ rc = 240; goto on_return;
+ }
+ }
+
+ aud_stream = pjmedia_avi_streams_get_stream_by_media(avi_streams,
+ 0,
+ PJMEDIA_TYPE_AUDIO);
+ aud_port = pjmedia_avi_stream_get_port(aud_stream);
+
+ if (aud_port) {
+ /* Create sound player port. */
+ status = pjmedia_snd_port_create_player(
+ pool, /* pool */
+ -1, /* use default dev. */
+ PJMEDIA_PIA_SRATE(&aud_port->info),/* clock rate. */
+ PJMEDIA_PIA_CCNT(&aud_port->info), /* # of channels. */
+ PJMEDIA_PIA_SPF(&aud_port->info), /* samples per frame. */
+ PJMEDIA_PIA_BITS(&aud_port->info), /* bits per sample. */
+ 0, /* options */
+ &snd_port /* returned port */
+ );
+ if (status != PJ_SUCCESS) {
+ rc = 310; goto on_return;
+ }
+
+ /* Connect file port to the sound player.
+ * Stream playing will commence immediately.
+ */
+ status = pjmedia_snd_port_connect(snd_port, aud_port);
+ if (status != PJ_SUCCESS) {
+ rc = 330; goto on_return;
+ }
+ }
+
+ if (vid_port) {
+ pjmedia_vid_dev_cb cb;
+
+ pj_bzero(&cb, sizeof(cb));
+ avi_port.snd_port = snd_port;
+ avi_port.vid_port = renderer;
+ avi_port.is_running = PJ_TRUE;
+ pjmedia_vid_port_set_cb(renderer, &cb, &avi_port);
+
+ /* subscribe events */
+ pjmedia_event_subscribe(NULL, &avi_event_cb, &avi_port,
+ renderer);
+
+ if (snd_port) {
+ /* Synchronize video rendering and audio playback */
+ pjmedia_vid_port_set_clock_src(
+ renderer,
+ pjmedia_snd_port_get_clock_src(
+ snd_port, PJMEDIA_DIR_PLAYBACK));
+ }
+
+
+ /* Start video streaming.. */
+ status = pjmedia_vid_port_start(renderer);
+ if (status != PJ_SUCCESS) {
+ rc = 270; goto on_return;
+ }
+ }
+
+ while (!avi_port.is_quitting) {
+ pj_thread_sleep(100);
+ }
+
+on_return:
+ if (snd_port) {
+ pjmedia_snd_port_disconnect(snd_port);
+ /* Without this sleep, Windows/DirectSound will repeteadly
+ * play the last frame during destroy.
+ */
+ pj_thread_sleep(100);
+ pjmedia_snd_port_destroy(snd_port);
+ }
+ if (renderer) {
+ pjmedia_event_unsubscribe(NULL, &avi_event_cb, &avi_port,
+ renderer);
+ pjmedia_vid_port_destroy(renderer);
+ }
+ if (aud_port)
+ pjmedia_port_destroy(aud_port);
+ if (vid_port)
+ pjmedia_port_destroy(vid_port);
+ if (codec) {
+ pjmedia_vid_codec_close(codec);
+ pjmedia_vid_codec_mgr_dealloc_codec(NULL, codec);
+ }
+
+ return rc;
+}
+
+
+static int main_func(int argc, char *argv[])
+{
+ pj_caching_pool cp;
+ pj_pool_t *pool;
+ int rc = 0;
+ pj_status_t status = PJ_SUCCESS;
+
+ if (argc != 2) {
+ puts("Error: filename required");
+ puts(desc);
+ return 1;
+ }
+
+
+ /* Must init PJLIB first: */
+ status = pj_init();
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ /* Must create a pool factory before we can allocate any memory. */
+ pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);
+
+ /* Create memory pool for our file player */
+ pool = pj_pool_create( &cp.factory, /* pool factory */
+ "AVI", /* pool name. */
+ 4000, /* init size */
+ 4000, /* increment size */
+ NULL /* callback on error */
+ );
+
+ pjmedia_video_format_mgr_create(pool, 64, 0, NULL);
+ pjmedia_converter_mgr_create(pool, NULL);
+ pjmedia_event_mgr_create(pool, 0, NULL);
+ pjmedia_vid_codec_mgr_create(pool, NULL);
+
+ status = pjmedia_vid_dev_subsys_init(&cp.factory);
+ if (status != PJ_SUCCESS)
+ goto on_return;
+
+ status = pjmedia_aud_subsys_init(&cp.factory);
+ if (status != PJ_SUCCESS) {
+ goto on_return;
+ }
+
+#if PJMEDIA_HAS_FFMPEG_VID_CODEC
+ status = pjmedia_codec_ffmpeg_vid_init(NULL, &cp.factory);
+ if (status != PJ_SUCCESS)
+ goto on_return;
+#endif
+
+ rc = aviplay(pool, argv[1]);
+
+ /*
+ * File should be playing and looping now
+ */
+
+ /* Without this sleep, Windows/DirectSound will repeteadly
+ * play the last frame during destroy.
+ */
+ pj_thread_sleep(100);
+
+on_return:
+#if PJMEDIA_HAS_FFMPEG_VID_CODEC
+ pjmedia_codec_ffmpeg_vid_deinit();
+#endif
+ pjmedia_aud_subsys_shutdown();
+ pjmedia_vid_dev_subsys_shutdown();
+
+ pjmedia_video_format_mgr_destroy(pjmedia_video_format_mgr_instance());
+ pjmedia_converter_mgr_destroy(pjmedia_converter_mgr_instance());
+ pjmedia_event_mgr_destroy(pjmedia_event_mgr_instance());
+ pjmedia_vid_codec_mgr_destroy(pjmedia_vid_codec_mgr_instance());
+
+ /* Release application pool */
+ pj_pool_release( pool );
+
+ /* Destroy pool factory */
+ pj_caching_pool_destroy( &cp );
+
+ /* Shutdown PJLIB */
+ pj_shutdown();
+
+ /* Done. */
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ return pj_run_app(&main_func, argc, argv, 0);
+}
+
+#else
+
+int main(int argc, char *argv[])
+{
+ PJ_UNUSED_ARG(argc);
+ PJ_UNUSED_ARG(argv);
+ puts("Error: this sample requires video capability (PJMEDIA_HAS_VIDEO == 1)");
+ return -1;
+}
+
+#endif /* PJMEDIA_HAS_VIDEO */
diff --git a/pjsip-apps/src/samples/confbench.c b/pjsip-apps/src/samples/confbench.c
new file mode 100644
index 0000000..4fe155d
--- /dev/null
+++ b/pjsip-apps/src/samples/confbench.c
@@ -0,0 +1,347 @@
+/* $Id: confbench.c 3664 2011-07-19 03:42:28Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+/**
+ * \page page_pjmedia_samples_confbench_c Samples: Benchmarking Conference Bridge
+ *
+ * Benchmarking pjmedia (conference bridge+resample). For my use only,
+ * and it only works in Win32.
+ *
+ * This file is pjsip-apps/src/samples/confbench.c
+ *
+ * \includelineno confbench.c
+ */
+
+
+#include <pjmedia.h>
+#include <pjlib-util.h> /* pj_getopt */
+#include <pjlib.h>
+#include <stdlib.h> /* atoi() */
+#include <stdio.h>
+#include <windows.h>
+
+/* For logging purpose. */
+#define THIS_FILE "confsample.c"
+
+
+/* Configurable:
+ * LARGE_SET will create in total of about 232 ports.
+ * HAS_RESAMPLE will activate resampling on about half
+ * the port.
+ */
+#define TEST_SET LARGE_SET
+#define HAS_RESAMPLE 0
+
+
+#define SMALL_SET 16
+#define LARGE_SET 100
+
+
+#define PORT_COUNT 254
+#define CLOCK_RATE 16000
+#define SAMPLES_PER_FRAME (CLOCK_RATE/100)
+#if HAS_RESAMPLE
+# define SINE_CLOCK 32000
+#else
+# define SINE_CLOCK CLOCK_RATE
+#endif
+#define SINE_PTIME 20
+#define DURATION 10
+
+#define SINE_COUNT TEST_SET
+#define NULL_COUNT TEST_SET
+#define IDLE_COUNT 32
+
+
+static void app_perror(const char *sender, const char *title, pj_status_t status)
+{
+ char errmsg[PJ_ERR_MSG_SIZE];
+
+ pj_strerror(status, errmsg, sizeof(errmsg));
+ PJ_LOG(1,(sender, "%s: %s", title, errmsg));
+}
+
+
+struct Times
+{
+ FILETIME kernel_time;
+ ULARGE_INTEGER u_kernel_time;
+ FILETIME user_time;
+ ULARGE_INTEGER u_user_time;
+ ULARGE_INTEGER u_total;
+};
+
+static void process(struct Times *t)
+{
+ pj_memcpy(&t->u_kernel_time, &t->kernel_time, sizeof(FILETIME));
+ pj_memcpy(&t->u_user_time, &t->user_time, sizeof(FILETIME));
+ t->u_total.QuadPart = t->u_kernel_time.QuadPart + t->u_user_time.QuadPart;
+}
+
+static void benchmark(void)
+{
+ FILETIME creation_time, exit_time;
+ struct Times start, end;
+ DWORD ts, te;
+ LARGE_INTEGER elapsed;
+ BOOL rc;
+ int i;
+ double pct;
+
+ puts("Test started!"); fflush(stdout);
+
+ ts = GetTickCount();
+ rc = GetProcessTimes(GetCurrentProcess(), &creation_time, &exit_time,
+ &start.kernel_time, &start.user_time);
+ for (i=DURATION; i>0; --i) {
+ printf("\r%d ", i); fflush(stdout);
+ pj_thread_sleep(1000);
+ }
+ rc = GetProcessTimes(GetCurrentProcess(), &creation_time, &exit_time,
+ &end.kernel_time, &end.user_time);
+ te = GetTickCount();
+
+ process(&start);
+ process(&end);
+
+ elapsed.QuadPart = end.u_total.QuadPart - start.u_total.QuadPart;
+
+ pct = elapsed.QuadPart * 100.0 / ((te-ts)*10000.0);
+
+ printf("CPU usage=%6.4f%%\n", pct); fflush(stdout);
+}
+
+
+
+/* Struct attached to sine generator */
+typedef struct
+{
+ pj_int16_t *samples; /* Sine samples. */
+} port_data;
+
+
+/* This callback is called to feed more samples */
+static pj_status_t sine_get_frame( pjmedia_port *port,
+ pjmedia_frame *frame)
+{
+ port_data *sine = port->port_data.pdata;
+ pj_int16_t *samples = frame->buf;
+ unsigned i, count, left, right;
+
+ /* Get number of samples */
+ count = frame->size / 2 / PJMEDIA_PIA_CCNT(&port->info);
+
+ left = 0;
+ right = 0;
+
+ for (i=0; i<count; ++i) {
+ *samples++ = sine->samples[left];
+ ++left;
+
+ if (PJMEDIA_PIA_CCNT(&port->info) == 2) {
+ *samples++ = sine->samples[right];
+ right += 2; /* higher pitch so we can distinguish left and right. */
+ if (right >= count)
+ right = 0;
+ }
+ }
+
+ /* Must set frame->type correctly, otherwise the sound device
+ * will refuse to play.
+ */
+ frame->type = PJMEDIA_FRAME_TYPE_AUDIO;
+
+ return PJ_SUCCESS;
+}
+
+#ifndef M_PI
+#define M_PI (3.14159265)
+#endif
+
+/*
+ * Create a media port to generate sine wave samples.
+ */
+static pj_status_t create_sine_port(pj_pool_t *pool,
+ unsigned sampling_rate,
+ unsigned channel_count,
+ pjmedia_port **p_port)
+{
+ pjmedia_port *port;
+ unsigned i;
+ unsigned count;
+ pj_str_t port_name;
+ port_data *sine;
+
+ PJ_ASSERT_RETURN(pool && channel_count > 0 && channel_count <= 2,
+ PJ_EINVAL);
+
+ port = pj_pool_zalloc(pool, sizeof(pjmedia_port));
+ PJ_ASSERT_RETURN(port != NULL, PJ_ENOMEM);
+
+ /* Fill in port info. */
+ port_name = pj_str("sine generator");
+ pjmedia_port_info_init(&port->info, &port_name,
+ 12345, sampling_rate, channel_count, 16,
+ sampling_rate * SINE_PTIME / 1000 * channel_count);
+
+ /* Set the function to feed frame */
+ port->get_frame = &sine_get_frame;
+
+ /* Create sine port data */
+ port->port_data.pdata = sine = pj_pool_zalloc(pool, sizeof(port_data));
+
+ /* Create samples */
+ count = PJMEDIA_PIA_SPF(&port->info) / channel_count;
+ sine->samples = pj_pool_alloc(pool, count * sizeof(pj_int16_t));
+ PJ_ASSERT_RETURN(sine->samples != NULL, PJ_ENOMEM);
+
+ /* initialise sinusoidal wavetable */
+ for( i=0; i<count; i++ )
+ {
+ sine->samples[i] = (pj_int16_t) (10000.0 *
+ sin(((double)i/(double)count) * M_PI * 8.) );
+ }
+
+ *p_port = port;
+
+ return PJ_SUCCESS;
+}
+
+int main()
+{
+ pj_caching_pool cp;
+ pjmedia_endpt *med_endpt;
+ pj_pool_t *pool;
+ pjmedia_conf *conf;
+ int i;
+ pjmedia_port *sine_port[SINE_COUNT], *null_port, *conf_port;
+ pjmedia_port *nulls[NULL_COUNT];
+ unsigned null_slots[NULL_COUNT];
+ pjmedia_master_port *master_port;
+ pj_status_t status;
+
+
+ pj_log_set_level(3);
+
+ status = pj_init();
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);
+ pool = pj_pool_create( &cp.factory, /* pool factory */
+ "wav", /* pool name. */
+ 4000, /* init size */
+ 4000, /* increment size */
+ NULL /* callback on error */
+ );
+
+ status = pjmedia_endpt_create(&cp.factory, NULL, 1, &med_endpt);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+
+
+ status = pjmedia_conf_create( pool,
+ PORT_COUNT,
+ CLOCK_RATE,
+ 1, SAMPLES_PER_FRAME, 16,
+ PJMEDIA_CONF_NO_DEVICE,
+ &conf);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to create conference bridge", status);
+ return 1;
+ }
+
+ printf("Resampling is %s\n", (HAS_RESAMPLE?"active":"disabled"));
+
+ /* Create Null ports */
+ printf("Creating %d null ports..\n", NULL_COUNT);
+ for (i=0; i<NULL_COUNT; ++i) {
+ status = pjmedia_null_port_create(pool, CLOCK_RATE, 1, SAMPLES_PER_FRAME*2, 16, &nulls[i]);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ status = pjmedia_conf_add_port(conf, pool, nulls[i], NULL, &null_slots[i]);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+ }
+
+ /* Create sine ports. */
+ printf("Creating %d sine generator ports..\n", SINE_COUNT);
+ for (i=0; i<SINE_COUNT; ++i) {
+ unsigned j, slot;
+
+ /* Load the WAV file to file port. */
+ status = create_sine_port(pool, SINE_CLOCK, 1, &sine_port[i]);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ /* Add the file port to conference bridge */
+ status = pjmedia_conf_add_port( conf, /* The bridge */
+ pool, /* pool */
+ sine_port[i], /* port to connect */
+ NULL, /* Use port's name */
+ &slot /* ptr for slot # */
+ );
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to add conference port", status);
+ return 1;
+ }
+
+ status = pjmedia_conf_connect_port(conf, slot, 0, 0);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ for (j=0; j<NULL_COUNT; ++j) {
+ status = pjmedia_conf_connect_port(conf, slot, null_slots[j], 0);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+ }
+ }
+
+ /* Create idle ports */
+ printf("Creating %d idle ports..\n", IDLE_COUNT);
+ for (i=0; i<IDLE_COUNT; ++i) {
+ pjmedia_port *dummy;
+ status = pjmedia_null_port_create(pool, CLOCK_RATE, 1, SAMPLES_PER_FRAME, 16, &dummy);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+ status = pjmedia_conf_add_port(conf, pool, dummy, NULL, NULL);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+ }
+
+ /* Create null port */
+ status = pjmedia_null_port_create(pool, CLOCK_RATE, 1, SAMPLES_PER_FRAME, 16,
+ &null_port);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ conf_port = pjmedia_conf_get_master_port(conf);
+
+ /* Create master port */
+ status = pjmedia_master_port_create(pool, null_port, conf_port, 0, &master_port);
+
+
+ pjmedia_master_port_start(master_port);
+
+ puts("Waiting to settle.."); fflush(stdout);
+ pj_thread_sleep(5000);
+
+
+ benchmark();
+
+
+ /* Done. */
+ return 0;
+}
+
+
diff --git a/pjsip-apps/src/samples/confsample.c b/pjsip-apps/src/samples/confsample.c
new file mode 100644
index 0000000..b8eb93f
--- /dev/null
+++ b/pjsip-apps/src/samples/confsample.c
@@ -0,0 +1,609 @@
+/* $Id: confsample.c 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <pjmedia.h>
+#include <pjlib-util.h> /* pj_getopt */
+#include <pjlib.h>
+
+#include <stdlib.h> /* atoi() */
+#include <stdio.h>
+
+#include "util.h"
+
+/**
+ * \page page_pjmedia_samples_confsample_c Samples: Using Conference Bridge
+ *
+ * Sample to mix multiple files in the conference bridge and play the
+ * result to sound device.
+ *
+ * This file is pjsip-apps/src/samples/confsample.c
+ *
+ * \includelineno confsample.c
+ */
+
+
+/* For logging purpose. */
+#define THIS_FILE "confsample.c"
+
+
+/* Shall we put recorder in the conference */
+#define RECORDER 1
+
+
+static const char *desc =
+ " FILE: \n"
+ " \n"
+ " confsample.c \n"
+ " \n"
+ " PURPOSE: \n"
+ " \n"
+ " Demonstrate how to use conference bridge. \n"
+ " \n"
+ " USAGE: \n"
+ " \n"
+ " confsample [options] [file1.wav] [file2.wav] ... \n"
+ " \n"
+ " options: \n"
+ SND_USAGE
+ " \n"
+ " fileN.wav are optional WAV files to be connected to the conference \n"
+ " bridge. The WAV files MUST have single channel (mono) and 16 bit PCM \n"
+ " samples. It can have arbitrary sampling rate. \n"
+ " \n"
+ " DESCRIPTION: \n"
+ " \n"
+ " Here we create a conference bridge, with at least one port (port zero \n"
+ " is always created for the sound device). \n"
+ " \n"
+ " If WAV files are specified, the WAV file player ports will be connected \n"
+ " to slot starting from number one in the bridge. The WAV files can have \n"
+ " arbitrary sampling rate; the bridge will convert it to its clock rate. \n"
+ " However, the files MUST have a single audio channel only (i.e. mono). \n";
+
+
+
+/*
+ * Prototypes:
+ */
+
+/* List the ports in the conference bridge */
+static void conf_list(pjmedia_conf *conf, pj_bool_t detail);
+
+/* Display VU meter */
+static void monitor_level(pjmedia_conf *conf, int slot, int dir, int dur);
+
+
+/* Show usage */
+static void usage(void)
+{
+ puts("");
+ puts(desc);
+}
+
+
+
+/* Input simple string */
+static pj_bool_t input(const char *title, char *buf, pj_size_t len)
+{
+ char *p;
+
+ printf("%s (empty to cancel): ", title); fflush(stdout);
+ if (fgets(buf, len, stdin) == NULL)
+ return PJ_FALSE;
+
+ /* Remove trailing newlines. */
+ for (p=buf; ; ++p) {
+ if (*p=='\r' || *p=='\n') *p='\0';
+ else if (!*p) break;
+ }
+
+ if (!*buf)
+ return PJ_FALSE;
+
+ return PJ_TRUE;
+}
+
+
+/*****************************************************************************
+ * main()
+ */
+int main(int argc, char *argv[])
+{
+ int dev_id = -1;
+ int clock_rate = CLOCK_RATE;
+ int channel_count = NCHANNELS;
+ int samples_per_frame = NSAMPLES;
+ int bits_per_sample = NBITS;
+
+ pj_caching_pool cp;
+ pjmedia_endpt *med_endpt;
+ pj_pool_t *pool;
+ pjmedia_conf *conf;
+
+ int i, port_count, file_count;
+ pjmedia_port **file_port; /* Array of file ports */
+ pjmedia_port *rec_port = NULL; /* Wav writer port */
+
+ char tmp[10];
+ pj_status_t status;
+
+
+ /* Must init PJLIB first: */
+ status = pj_init();
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ /* Get command line options. */
+ if (get_snd_options(THIS_FILE, argc, argv, &dev_id, &clock_rate,
+ &channel_count, &samples_per_frame, &bits_per_sample))
+ {
+ usage();
+ return 1;
+ }
+
+ /* Must create a pool factory before we can allocate any memory. */
+ pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);
+
+ /*
+ * Initialize media endpoint.
+ * This will implicitly initialize PJMEDIA too.
+ */
+ status = pjmedia_endpt_create(&cp.factory, NULL, 1, &med_endpt);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ /* Create memory pool to allocate memory */
+ pool = pj_pool_create( &cp.factory, /* pool factory */
+ "wav", /* pool name. */
+ 4000, /* init size */
+ 4000, /* increment size */
+ NULL /* callback on error */
+ );
+
+
+ file_count = argc - pj_optind;
+ port_count = file_count + 1 + RECORDER;
+
+ /* Create the conference bridge.
+ * With default options (zero), the bridge will create an instance of
+ * sound capture and playback device and connect them to slot zero.
+ */
+ status = pjmedia_conf_create( pool, /* pool to use */
+ port_count,/* number of ports */
+ clock_rate,
+ channel_count,
+ samples_per_frame,
+ bits_per_sample,
+ 0, /* options */
+ &conf /* result */
+ );
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to create conference bridge", status);
+ return 1;
+ }
+
+#if RECORDER
+ status = pjmedia_wav_writer_port_create( pool, "confrecord.wav",
+ clock_rate, channel_count,
+ samples_per_frame,
+ bits_per_sample, 0, 0,
+ &rec_port);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to create WAV writer", status);
+ return 1;
+ }
+
+ pjmedia_conf_add_port(conf, pool, rec_port, NULL, NULL);
+#endif
+
+
+ /* Create file ports. */
+ file_port = pj_pool_alloc(pool, file_count * sizeof(pjmedia_port*));
+
+ for (i=0; i<file_count; ++i) {
+
+ /* Load the WAV file to file port. */
+ status = pjmedia_wav_player_port_create(
+ pool, /* pool. */
+ argv[i+pj_optind], /* filename */
+ 0, /* use default ptime */
+ 0, /* flags */
+ 0, /* buf size */
+ &file_port[i] /* result */
+ );
+ if (status != PJ_SUCCESS) {
+ char title[80];
+ pj_ansi_sprintf(title, "Unable to use %s", argv[i+pj_optind]);
+ app_perror(THIS_FILE, title, status);
+ usage();
+ return 1;
+ }
+
+ /* Add the file port to conference bridge */
+ status = pjmedia_conf_add_port( conf, /* The bridge */
+ pool, /* pool */
+ file_port[i], /* port to connect */
+ NULL, /* Use port's name */
+ NULL /* ptr for slot # */
+ );
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to add conference port", status);
+ return 1;
+ }
+ }
+
+
+ /*
+ * All ports are set up in the conference bridge.
+ * But at this point, no media will be flowing since no ports are
+ * "connected". User must connect the port manually.
+ */
+
+
+ /* Dump memory usage */
+ dump_pool_usage(THIS_FILE, &cp);
+
+ /* Sleep to allow log messages to flush */
+ pj_thread_sleep(100);
+
+
+ /*
+ * UI Menu:
+ */
+ for (;;) {
+ char tmp1[10];
+ char tmp2[10];
+ char *err;
+ int src, dst, level, dur;
+
+ puts("");
+ conf_list(conf, 0);
+ puts("");
+ puts("Menu:");
+ puts(" s Show ports details");
+ puts(" c Connect one port to another");
+ puts(" d Disconnect port connection");
+ puts(" t Adjust signal level transmitted (tx) to a port");
+ puts(" r Adjust signal level received (rx) from a port");
+ puts(" v Display VU meter for a particular port");
+ puts(" q Quit");
+ puts("");
+
+ printf("Enter selection: "); fflush(stdout);
+
+ if (fgets(tmp, sizeof(tmp), stdin) == NULL)
+ break;
+
+ switch (tmp[0]) {
+ case 's':
+ puts("");
+ conf_list(conf, 1);
+ break;
+
+ case 'c':
+ puts("");
+ puts("Connect source port to destination port");
+ if (!input("Enter source port number", tmp1, sizeof(tmp1)) )
+ continue;
+ src = strtol(tmp1, &err, 10);
+ if (*err || src < 0 || src >= port_count) {
+ puts("Invalid slot number");
+ continue;
+ }
+
+ if (!input("Enter destination port number", tmp2, sizeof(tmp2)) )
+ continue;
+ dst = strtol(tmp2, &err, 10);
+ if (*err || dst < 0 || dst >= port_count) {
+ puts("Invalid slot number");
+ continue;
+ }
+
+ status = pjmedia_conf_connect_port(conf, src, dst, 0);
+ if (status != PJ_SUCCESS)
+ app_perror(THIS_FILE, "Error connecting port", status);
+
+ break;
+
+ case 'd':
+ puts("");
+ puts("Disconnect port connection");
+ if (!input("Enter source port number", tmp1, sizeof(tmp1)) )
+ continue;
+ src = strtol(tmp1, &err, 10);
+ if (*err || src < 0 || src >= port_count) {
+ puts("Invalid slot number");
+ continue;
+ }
+
+ if (!input("Enter destination port number", tmp2, sizeof(tmp2)) )
+ continue;
+ dst = strtol(tmp2, &err, 10);
+ if (*err || dst < 0 || dst >= port_count) {
+ puts("Invalid slot number");
+ continue;
+ }
+
+ status = pjmedia_conf_disconnect_port(conf, src, dst);
+ if (status != PJ_SUCCESS)
+ app_perror(THIS_FILE, "Error connecting port", status);
+
+
+ break;
+
+ case 't':
+ puts("");
+ puts("Adjust transmit level of a port");
+ if (!input("Enter port number", tmp1, sizeof(tmp1)) )
+ continue;
+ src = strtol(tmp1, &err, 10);
+ if (*err || src < 0 || src >= port_count) {
+ puts("Invalid slot number");
+ continue;
+ }
+
+ if (!input("Enter level (-128 to >127, 0 for normal)",
+ tmp2, sizeof(tmp2)) )
+ continue;
+ level = strtol(tmp2, &err, 10);
+ if (*err || level < -128) {
+ puts("Invalid level");
+ continue;
+ }
+
+ status = pjmedia_conf_adjust_tx_level( conf, src, level);
+ if (status != PJ_SUCCESS)
+ app_perror(THIS_FILE, "Error adjusting level", status);
+ break;
+
+
+ case 'r':
+ puts("");
+ puts("Adjust receive level of a port");
+ if (!input("Enter port number", tmp1, sizeof(tmp1)) )
+ continue;
+ src = strtol(tmp1, &err, 10);
+ if (*err || src < 0 || src >= port_count) {
+ puts("Invalid slot number");
+ continue;
+ }
+
+ if (!input("Enter level (-128 to >127, 0 for normal)",
+ tmp2, sizeof(tmp2)) )
+ continue;
+ level = strtol(tmp2, &err, 10);
+ if (*err || level < -128) {
+ puts("Invalid level");
+ continue;
+ }
+
+ status = pjmedia_conf_adjust_rx_level( conf, src, level);
+ if (status != PJ_SUCCESS)
+ app_perror(THIS_FILE, "Error adjusting level", status);
+ break;
+
+ case 'v':
+ puts("");
+ puts("Display VU meter");
+ if (!input("Enter port number to monitor", tmp1, sizeof(tmp1)) )
+ continue;
+ src = strtol(tmp1, &err, 10);
+ if (*err || src < 0 || src >= port_count) {
+ puts("Invalid slot number");
+ continue;
+ }
+
+ if (!input("Enter r for rx level or t for tx level", tmp2, sizeof(tmp2)))
+ continue;
+ if (tmp2[0] != 'r' && tmp2[0] != 't') {
+ puts("Invalid option");
+ continue;
+ }
+
+ if (!input("Duration to monitor (in seconds)", tmp1, sizeof(tmp1)) )
+ continue;
+ dur = strtol(tmp1, &err, 10);
+ if (*err) {
+ puts("Invalid duration number");
+ continue;
+ }
+
+ monitor_level(conf, src, tmp2[0], dur);
+ break;
+
+ case 'q':
+ goto on_quit;
+
+ default:
+ printf("Invalid input character '%c'\n", tmp[0]);
+ break;
+ }
+ }
+
+on_quit:
+
+ /* Start deinitialization: */
+
+ /* Destroy conference bridge */
+ status = pjmedia_conf_destroy( conf );
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+
+ /* Destroy file ports */
+ for (i=0; i<file_count; ++i) {
+ status = pjmedia_port_destroy( file_port[i]);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+ }
+
+ /* Destroy recorder port */
+ if (rec_port)
+ pjmedia_port_destroy(rec_port);
+
+ /* Release application pool */
+ pj_pool_release( pool );
+
+ /* Destroy media endpoint. */
+ pjmedia_endpt_destroy( med_endpt );
+
+ /* Destroy pool factory */
+ pj_caching_pool_destroy( &cp );
+
+ /* Shutdown PJLIB */
+ pj_shutdown();
+
+ /* Done. */
+ return 0;
+}
+
+
+/*
+ * List the ports in conference bridge
+ */
+static void conf_list(pjmedia_conf *conf, int detail)
+{
+ enum { MAX_PORTS = 32 };
+ unsigned i, count;
+ pjmedia_conf_port_info info[MAX_PORTS];
+
+ printf("Conference ports:\n");
+
+ count = PJ_ARRAY_SIZE(info);
+ pjmedia_conf_get_ports_info(conf, &count, info);
+
+ for (i=0; i<count; ++i) {
+ char txlist[4*MAX_PORTS];
+ unsigned j;
+ pjmedia_conf_port_info *port_info = &info[i];
+
+ txlist[0] = '\0';
+ for (j=0; j<port_info->listener_cnt; ++j) {
+ char s[10];
+ pj_ansi_sprintf(s, "#%d ", port_info->listener_slots[j]);
+ pj_ansi_strcat(txlist, s);
+
+ }
+
+ if (txlist[0] == '\0') {
+ txlist[0] = '-';
+ txlist[1] = '\0';
+ }
+
+ if (!detail) {
+ printf("Port #%02d %-25.*s transmitting to: %s\n",
+ port_info->slot,
+ (int)port_info->name.slen,
+ port_info->name.ptr,
+ txlist);
+ } else {
+ unsigned tx_level, rx_level;
+
+ pjmedia_conf_get_signal_level(conf, port_info->slot,
+ &tx_level, &rx_level);
+
+ printf("Port #%02d:\n"
+ " Name : %.*s\n"
+ " Sampling rate : %d Hz\n"
+ " Samples per frame : %d\n"
+ " Frame time : %d ms\n"
+ " Signal level adjustment : tx=%d, rx=%d\n"
+ " Current signal level : tx=%u, rx=%u\n"
+ " Transmitting to ports : %s\n\n",
+ port_info->slot,
+ (int)port_info->name.slen,
+ port_info->name.ptr,
+ port_info->clock_rate,
+ port_info->samples_per_frame,
+ port_info->samples_per_frame*1000/port_info->clock_rate,
+ port_info->tx_adj_level,
+ port_info->rx_adj_level,
+ tx_level,
+ rx_level,
+ txlist);
+ }
+
+ }
+ puts("");
+}
+
+
+/*
+ * Display VU meter
+ */
+static void monitor_level(pjmedia_conf *conf, int slot, int dir, int dur)
+{
+ enum { SLEEP = 20, SAMP_CNT = 2};
+ pj_status_t status;
+ int i, total_count;
+ unsigned level, samp_cnt;
+
+
+ puts("");
+ printf("Displaying VU meter for port %d for about %d seconds\n",
+ slot, dur);
+
+ total_count = dur * 1000 / SLEEP;
+
+ level = 0;
+ samp_cnt = 0;
+
+ for (i=0; i<total_count; ++i) {
+ unsigned tx_level, rx_level;
+ int j, length;
+ char meter[21];
+
+ /* Poll the volume every 20 msec */
+ status = pjmedia_conf_get_signal_level(conf, slot,
+ &tx_level, &rx_level);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to read level", status);
+ return;
+ }
+
+ level += (dir=='r' ? rx_level : tx_level);
+ ++samp_cnt;
+
+ /* Accumulate until we have enough samples */
+ if (samp_cnt < SAMP_CNT) {
+ pj_thread_sleep(SLEEP);
+ continue;
+ }
+
+ /* Get average */
+ level = level / samp_cnt;
+
+ /* Draw bar */
+ length = 20 * level / 255;
+ for (j=0; j<length; ++j)
+ meter[j] = '#';
+ for (; j<20; ++j)
+ meter[j] = ' ';
+ meter[20] = '\0';
+
+ printf("Port #%02d %cx level: [%s] %d \r",
+ slot, dir, meter, level);
+
+ /* Next.. */
+ samp_cnt = 0;
+ level = 0;
+
+ pj_thread_sleep(SLEEP);
+ }
+
+ puts("");
+}
+
diff --git a/pjsip-apps/src/samples/debug.c b/pjsip-apps/src/samples/debug.c
new file mode 100644
index 0000000..1d38f9a
--- /dev/null
+++ b/pjsip-apps/src/samples/debug.c
@@ -0,0 +1,32 @@
+/* $Id: debug.c 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * PURPOSE:
+ * The purpose of this file is to allow debugging of a sample application
+ * using MSVC IDE.
+ */
+
+/* To debug a sample application, include the source file here.
+ * E.g.:
+ * #include "playfile.c"
+ */
+#include "icedemo.c"
+
diff --git a/pjsip-apps/src/samples/encdec.c b/pjsip-apps/src/samples/encdec.c
new file mode 100644
index 0000000..9ded990
--- /dev/null
+++ b/pjsip-apps/src/samples/encdec.c
@@ -0,0 +1,263 @@
+/* $Id: encdec.c 3664 2011-07-19 03:42:28Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+ /**
+ * \page page_pjmedia_samples_encdec_c Samples: Encoding and Decoding
+ *
+ * This sample shows how to use codec.
+ *
+ * This file is pjsip-apps/src/samples/encdec.c
+ *
+ * \includelineno encdec.c
+ */
+
+#include <pjlib.h>
+#include <pjmedia.h>
+#include <pjmedia-codec.h>
+
+#define THIS_FILE "encdec.c"
+
+static const char *desc =
+ " encdec \n"
+ " \n"
+ " PURPOSE: \n"
+ " Encode input WAV with a codec, and decode the result to another WAV \n"
+ "\n"
+ "\n"
+ " USAGE: \n"
+ " encdec codec input.wav output.wav \n"
+ "\n"
+ "\n"
+ " where:\n"
+ " codec Set the codec name. \n"
+ " input.wav Set the input WAV filename. \n"
+ " output.wav Set the output WAV filename. \n"
+
+ "\n"
+;
+
+//#undef PJ_TRACE
+//#define PJ_TRACE 1
+
+#ifndef PJ_TRACE
+# define PJ_TRACE 0
+#endif
+
+#if PJ_TRACE
+# define TRACE_(expr) PJ_LOG(4,expr)
+#else
+# define TRACE_(expr)
+#endif
+
+
+static void err(const char *op, pj_status_t status)
+{
+ char errmsg[PJ_ERR_MSG_SIZE];
+ pj_strerror(status, errmsg, sizeof(errmsg));
+ PJ_LOG(3,("", "%s error: %s", op, errmsg));
+}
+
+#define CHECK(op) do { \
+ status = op; \
+ if (status != PJ_SUCCESS) { \
+ err(#op, status); \
+ return status; \
+ } \
+ } \
+ while (0)
+
+static pjmedia_endpt *mept;
+static unsigned file_msec_duration;
+
+static pj_status_t enc_dec_test(const char *codec_id,
+ const char *filein,
+ const char *fileout)
+{
+ pj_pool_t *pool;
+ pjmedia_codec_mgr *cm;
+ pjmedia_codec *codec;
+ const pjmedia_codec_info *pci;
+ pjmedia_codec_param param;
+ unsigned cnt, samples_per_frame;
+ pj_str_t tmp;
+ pjmedia_port *wavin, *wavout;
+ unsigned lost_pct;
+ pj_status_t status;
+
+#define T file_msec_duration/1000, file_msec_duration%1000
+
+ pool = pjmedia_endpt_create_pool(mept, "encdec", 1000, 1000);
+
+ cm = pjmedia_endpt_get_codec_mgr(mept);
+
+#ifdef LOST_PCT
+ lost_pct = LOST_PCT;
+#else
+ lost_pct = 0;
+#endif
+
+ cnt = 1;
+ CHECK( pjmedia_codec_mgr_find_codecs_by_id(cm, pj_cstr(&tmp, codec_id),
+ &cnt, &pci, NULL) );
+ CHECK( pjmedia_codec_mgr_get_default_param(cm, pci, &param) );
+
+ samples_per_frame = param.info.clock_rate * param.info.frm_ptime / 1000;
+
+ /* Control VAD */
+ param.setting.vad = 1;
+
+ /* Open wav for reading */
+ CHECK( pjmedia_wav_player_port_create(pool, filein,
+ param.info.frm_ptime,
+ PJMEDIA_FILE_NO_LOOP, 0, &wavin) );
+
+ /* Open wav for writing */
+ CHECK( pjmedia_wav_writer_port_create(pool, fileout,
+ param.info.clock_rate,
+ param.info.channel_cnt,
+ samples_per_frame,
+ 16, 0, 0, &wavout) );
+
+ /* Alloc codec */
+ CHECK( pjmedia_codec_mgr_alloc_codec(cm, pci, &codec) );
+ CHECK( pjmedia_codec_init(codec, pool) );
+ CHECK( pjmedia_codec_open(codec, &param) );
+
+ for (;;) {
+ pjmedia_frame frm_pcm, frm_bit, out_frm, frames[4];
+ pj_int16_t pcmbuf[320];
+ pj_timestamp ts;
+ pj_uint8_t bitstream[160];
+
+ frm_pcm.buf = (char*)pcmbuf;
+ frm_pcm.size = samples_per_frame * 2;
+
+ /* Read from WAV */
+ if (pjmedia_port_get_frame(wavin, &frm_pcm) != PJ_SUCCESS)
+ break;
+ if (frm_pcm.type != PJMEDIA_FRAME_TYPE_AUDIO)
+ break;;
+
+ /* Update duration */
+ file_msec_duration += samples_per_frame * 1000 /
+ param.info.clock_rate;
+
+ /* Encode */
+ frm_bit.buf = bitstream;
+ frm_bit.size = sizeof(bitstream);
+ CHECK(pjmedia_codec_encode(codec, &frm_pcm, sizeof(bitstream),
+ &frm_bit));
+
+ /* On DTX, write zero frame to wavout to maintain duration */
+ if (frm_bit.size == 0 || frm_bit.type != PJMEDIA_FRAME_TYPE_AUDIO) {
+ out_frm.buf = (char*)pcmbuf;
+ out_frm.size = 160;
+ CHECK( pjmedia_port_put_frame(wavout, &out_frm) );
+ TRACE_((THIS_FILE, "%d.%03d read: %u, enc: %u",
+ T, frm_pcm.size, frm_bit.size));
+ continue;
+ }
+
+ /* Parse the bitstream (not really necessary for this case
+ * since we always decode 1 frame, but it's still good
+ * for testing)
+ */
+ ts.u64 = 0;
+ cnt = PJ_ARRAY_SIZE(frames);
+ CHECK( pjmedia_codec_parse(codec, bitstream, frm_bit.size, &ts, &cnt,
+ frames) );
+ CHECK( (cnt==1 ? PJ_SUCCESS : -1) );
+
+ /* Decode or simulate packet loss */
+ out_frm.buf = (char*)pcmbuf;
+ out_frm.size = sizeof(pcmbuf);
+
+ if ((pj_rand() % 100) < (int)lost_pct) {
+ /* Simulate loss */
+ CHECK( pjmedia_codec_recover(codec, sizeof(pcmbuf), &out_frm) );
+ TRACE_((THIS_FILE, "%d.%03d Packet lost", T));
+ } else {
+ /* Decode */
+ CHECK( pjmedia_codec_decode(codec, &frames[0], sizeof(pcmbuf),
+ &out_frm) );
+ }
+
+ /* Write to WAV */
+ CHECK( pjmedia_port_put_frame(wavout, &out_frm) );
+
+ TRACE_((THIS_FILE, "%d.%03d read: %u, enc: %u, dec/write: %u",
+ T, frm_pcm.size, frm_bit.size, out_frm.size));
+ }
+
+ /* Close wavs */
+ pjmedia_port_destroy(wavout);
+ pjmedia_port_destroy(wavin);
+
+ /* Close codec */
+ pjmedia_codec_close(codec);
+ pjmedia_codec_mgr_dealloc_codec(cm, codec);
+
+ /* Release pool */
+ pj_pool_release(pool);
+
+ return PJ_SUCCESS;
+}
+
+
+int main(int argc, char *argv[])
+{
+ pj_caching_pool cp;
+ pj_time_val t0, t1;
+ pj_status_t status;
+
+ if (argc != 4) {
+ puts(desc);
+ return 1;
+ }
+
+ CHECK( pj_init() );
+
+ pj_caching_pool_init(&cp, NULL, 0);
+
+ CHECK( pjmedia_endpt_create(&cp.factory, NULL, 1, &mept) );
+
+ /* Register all codecs */
+ CHECK( pjmedia_codec_register_audio_codecs(mept, NULL) );
+
+ pj_gettimeofday(&t0);
+ status = enc_dec_test(argv[1], argv[2], argv[3]);
+ pj_gettimeofday(&t1);
+ PJ_TIME_VAL_SUB(t1, t0);
+
+ pjmedia_endpt_destroy(mept);
+ pj_caching_pool_destroy(&cp);
+ pj_shutdown();
+
+ if (status == PJ_SUCCESS) {
+ puts("");
+ puts("Success");
+ printf("Duration: %ds.%03d\n", file_msec_duration/1000,
+ file_msec_duration%1000);
+ printf("Time: %lds.%03ld\n", t1.sec, t1.msec);
+ }
+
+ return 0;
+}
+
diff --git a/pjsip-apps/src/samples/footprint.c b/pjsip-apps/src/samples/footprint.c
new file mode 100644
index 0000000..241ba1e
--- /dev/null
+++ b/pjsip-apps/src/samples/footprint.c
@@ -0,0 +1,654 @@
+/* $Id: footprint.c 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/**
+ * The purpose of this file is to show the typical footprint of
+ * the application when various PJSIP/PJMEDIA components are used.
+ *
+ * This file will not be build as samples, but instead it is build
+ * by get-footprint.py Python script in pjsip-apps/build directory.
+ */
+
+#include <pjsip_ua.h>
+#include <pjsip_simple.h>
+#include <pjsip.h>
+#include <pjmedia.h>
+#include <pjmedia-codec.h>
+#include <pjlib-util.h>
+#include <pjlib.h>
+#include <pjnath.h>
+#include <stdlib.h>
+
+/* All flags: */
+#if 0
+#define HAS_PJLIB
+
+#define HAS_PJLIB_STUN
+#define HAS_PJLIB_GETOPT
+#define HAS_PJLIB_XML
+#define HAS_PJLIB_SCANNER
+#define HAS_PJLIB_DNS
+#define HAS_PJLIB_RESOLVER
+#define HAS_PJLIB_SRV_RESOLVER
+
+#define HAS_PJLIB_CRC32
+#define HAS_PJLIB_HMAC_MD5
+#define HAS_PJLIB_HMAC_SHA1
+
+#define HAS_PJSIP_CORE_MSG_ELEM
+#define HAS_PJSIP_CORE
+#define HAS_PJSIP_CORE_MSG_UTIL
+
+#define HAS_PJSIP_UDP_TRANSPORT
+#define HAS_PJSIP_TCP_TRANSPORT
+#define HAS_PJSIP_TLS_TRANSPORT
+#define HAS_PJSIP_TRANSACTION
+#define HAS_PJSIP_UA_LAYER
+#define HAS_PJMEDIA_SDP
+#define HAS_PJMEDIA_SDP_NEGOTIATOR
+#define HAS_PJSIP_AUTH_CLIENT
+#define HAS_PJSIP_INV_SESSION
+#define HAS_PJSIP_REGC
+#define HAS_PJSIP_EVENT_FRAMEWORK
+#define HAS_PJSIP_CALL_TRANSFER
+#define HAS_PJSIP_PRESENCE
+#define HAS_PJSIP_IS_COMPOSING
+
+#define HAS_PJNATH_STUN
+#define HAS_PJNATH_ICE
+
+#define HAS_PJMEDIA
+#define HAS_PJMEDIA_SND_DEV
+#define HAS_PJMEDIA_EC
+#define HAS_PJMEDIA_SND_PORT
+#define HAS_PJMEDIA_RESAMPLE
+#define HAS_PJMEDIA_SILENCE_DET
+#define HAS_PJMEDIA_PLC
+#define HAS_PJMEDIA_CONFERENCE
+#define HAS_PJMEDIA_MASTER_PORT
+#define HAS_PJMEDIA_RTP
+#define HAS_PJMEDIA_RTCP
+#define HAS_PJMEDIA_JBUF
+#define HAS_PJMEDIA_STREAM
+#define HAS_PJMEDIA_TONEGEN
+#define HAS_PJMEDIA_UDP_TRANSPORT
+#define HAS_PJMEDIA_FILE_PLAYER
+#define HAS_PJMEDIA_FILE_CAPTURE
+#define HAS_PJMEDIA_MEM_PLAYER
+#define HAS_PJMEDIA_MEM_CAPTURE
+#define HAS_PJMEDIA_ICE
+
+#define HAS_PJMEDIA_G711_CODEC
+#define HAS_PJMEDIA_GSM_CODEC
+#define HAS_PJMEDIA_SPEEX_CODEC
+#define HAS_PJMEDIA_ILBC_CODEC
+#endif
+
+
+int dummy_function()
+{
+ pj_caching_pool cp;
+
+ sprintf(NULL, "%d", 0);
+ rand();
+
+#ifdef HAS_PJLIB
+ pj_init();
+ pj_caching_pool_init(&cp, NULL, 0);
+ pj_array_erase(NULL, 0, 0, 0);
+ pj_create_unique_string(NULL, NULL);
+ pj_hash_create(NULL, 0);
+ pj_hash_get(NULL, NULL, 0, NULL);
+ pj_hash_set(NULL, NULL, NULL, 0, 0, NULL);
+ pj_ioqueue_create(NULL, 0, NULL);
+ pj_ioqueue_register_sock(NULL, NULL, 0, NULL, NULL, NULL);
+ pj_pool_alloc(NULL, 0);
+ pj_timer_heap_create(NULL, 0, NULL);
+#endif
+
+#ifdef HAS_PJLIB_STUN
+ pjstun_get_mapped_addr(&cp.factory, 0, NULL, NULL, 80, NULL, 80, NULL);
+#endif
+
+#ifdef HAS_PJLIB_GETOPT
+ pj_getopt_long(0, NULL, NULL, NULL, NULL);
+#endif
+
+#ifdef HAS_PJLIB_XML
+ pj_xml_parse(NULL, NULL, 100);
+ pj_xml_print(NULL, NULL, 10, PJ_FALSE);
+ pj_xml_clone(NULL, NULL);
+ pj_xml_node_new(NULL, NULL);
+ pj_xml_attr_new(NULL, NULL, NULL);
+ pj_xml_add_node(NULL, NULL);
+ pj_xml_add_attr(NULL, NULL);
+ pj_xml_find_node(NULL, NULL);
+ pj_xml_find_next_node(NULL, NULL, NULL);
+ pj_xml_find_attr(NULL, NULL, NULL);
+ pj_xml_find(NULL, NULL, NULL, NULL);
+#endif
+
+#ifdef HAS_PJLIB_SCANNER
+ pj_cis_buf_init(NULL);
+ pj_cis_init(NULL, NULL);
+ pj_cis_dup(NULL, NULL);
+ pj_cis_add_alpha(NULL);
+ pj_cis_add_str(NULL, NULL);
+
+ pj_scan_init(NULL, NULL, 0, 0, NULL);
+ pj_scan_fini(NULL);
+ pj_scan_peek(NULL, NULL, NULL);
+ pj_scan_peek_n(NULL, 0, NULL);
+ pj_scan_peek_until(NULL, NULL, NULL);
+ pj_scan_get(NULL, NULL, NULL);
+ pj_scan_get_unescape(NULL, NULL, NULL);
+ pj_scan_get_quote(NULL, 0, 0, NULL);
+ pj_scan_get_n(NULL, 0, NULL);
+ pj_scan_get_char(NULL);
+ pj_scan_get_until(NULL, NULL, NULL);
+ pj_scan_strcmp(NULL, NULL, 0);
+ pj_scan_stricmp(NULL, NULL, 0);
+ pj_scan_stricmp_alnum(NULL, NULL, 0);
+ pj_scan_get_newline(NULL);
+ pj_scan_restore_state(NULL, NULL);
+#endif
+
+#ifdef HAS_PJLIB_DNS
+ pj_dns_make_query(NULL, NULL, 0, 0, NULL);
+ pj_dns_parse_packet(NULL, NULL, 0, NULL);
+ pj_dns_packet_dup(NULL, NULL, 0, NULL);
+#endif
+
+#ifdef HAS_PJLIB_RESOLVER
+ pj_dns_resolver_create(NULL, NULL, 0, NULL, NULL, NULL);
+ pj_dns_resolver_set_ns(NULL, 0, NULL, NULL);
+ pj_dns_resolver_handle_events(NULL, NULL);
+ pj_dns_resolver_destroy(NULL, 0);
+ pj_dns_resolver_start_query(NULL, NULL, 0, 0, NULL, NULL, NULL);
+ pj_dns_resolver_cancel_query(NULL, 0);
+ pj_dns_resolver_add_entry(NULL, NULL, 0);
+#endif
+
+#ifdef HAS_PJLIB_SRV_RESOLVER
+ pj_dns_srv_resolve(NULL, NULL, 0, NULL, NULL, PJ_FALSE, NULL, NULL);
+#endif
+
+#ifdef HAS_PJLIB_CRC32
+ pj_crc32_init(NULL);
+ pj_crc32_update(NULL, NULL, 0);
+ pj_crc32_final(NULL);
+#endif
+
+#ifdef HAS_PJLIB_HMAC_MD5
+ pj_hmac_md5(NULL, 0, NULL, 0, NULL);
+#endif
+
+#ifdef HAS_PJLIB_HMAC_SHA1
+ pj_hmac_sha1(NULL, 0, NULL, 0, NULL);
+#endif
+
+#ifdef HAS_PJNATH_STUN
+ pj_stun_session_create(NULL, NULL, NULL, PJ_FALSE, NULL);
+ pj_stun_session_destroy(NULL);
+ pj_stun_session_set_credential(NULL, NULL);
+ pj_stun_session_create_req(NULL, 0, NULL, NULL);
+ pj_stun_session_create_ind(NULL, 0, NULL);
+ pj_stun_session_create_res(NULL, NULL, 0, NULL, NULL);
+ pj_stun_session_send_msg(NULL, PJ_FALSE, NULL, 0, NULL);
+#endif
+
+#ifdef HAS_PJNATH_ICE
+ pj_ice_strans_create(NULL, NULL, 0, NULL, NULL, NULL);
+ pj_ice_strans_set_stun_domain(NULL, NULL, NULL);
+ pj_ice_strans_create_comp(NULL, 0, 0, NULL);
+ pj_ice_strans_add_cand(NULL, 0, PJ_ICE_CAND_TYPE_HOST, 0, NULL, PJ_FALSE);
+ pj_ice_strans_init_ice(NULL, PJ_ICE_SESS_ROLE_CONTROLLED, NULL, NULL);
+ pj_ice_strans_start_ice(NULL, NULL, NULL, 0, NULL);
+ pj_ice_strans_stop_ice(NULL);
+ pj_ice_strans_sendto(NULL, 0, NULL, 0, NULL, 0);
+#endif
+
+#ifdef HAS_PJSIP_CORE_MSG_ELEM
+ /* Parameter container */
+ pjsip_param_find(NULL, NULL);
+ pjsip_param_print_on(NULL, NULL, 0, NULL, NULL, 0);
+
+ /* SIP URI */
+ pjsip_sip_uri_create(NULL, 0);
+ pjsip_name_addr_create(NULL);
+
+ /* TEL URI */
+ pjsip_tel_uri_create(NULL);
+
+ /* Message and headers */
+ pjsip_msg_create(NULL, PJSIP_REQUEST_MSG);
+ pjsip_msg_print(NULL, NULL, 0);
+ pjsip_accept_hdr_create(NULL);
+ pjsip_allow_hdr_create(NULL);
+ pjsip_cid_hdr_create(NULL);
+ pjsip_clen_hdr_create(NULL);
+ pjsip_cseq_hdr_create(NULL);
+ pjsip_contact_hdr_create(NULL);
+ pjsip_ctype_hdr_create(NULL);
+ pjsip_expires_hdr_create(NULL, 0);
+ pjsip_from_hdr_create(NULL);
+ pjsip_max_fwd_hdr_create(NULL, 0);
+ pjsip_min_expires_hdr_create(NULL, 0);
+ pjsip_rr_hdr_create(NULL);
+ pjsip_require_hdr_create(NULL);
+ pjsip_retry_after_hdr_create(NULL, 0);
+ pjsip_supported_hdr_create(NULL);
+ pjsip_unsupported_hdr_create(NULL);
+ pjsip_via_hdr_create(NULL);
+ pjsip_warning_hdr_create(NULL, 0, NULL, NULL);
+
+ pjsip_parse_uri(NULL, NULL, 0, 0);
+ pjsip_parse_msg(NULL, NULL, 0, NULL);
+ pjsip_parse_rdata(NULL, 0, NULL);
+ pjsip_find_msg(NULL, 0, 0, NULL);
+#endif
+
+#ifdef HAS_PJSIP_CORE
+ pjsip_endpt_create(NULL, NULL, NULL);
+
+ pjsip_tpmgr_create(NULL, NULL, NULL, NULL, NULL);
+ pjsip_tpmgr_destroy(NULL);
+ pjsip_transport_send(NULL, NULL, NULL, 0, NULL, NULL);
+
+
+#endif
+
+#ifdef HAS_PJSIP_CORE_MSG_UTIL
+ pjsip_endpt_create_request(NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ -1, NULL, NULL);
+ pjsip_endpt_create_request_from_hdr(NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, -1, NULL, NULL);
+ pjsip_endpt_create_response(NULL, NULL, -1, NULL, NULL);
+ pjsip_endpt_create_ack(NULL, NULL, NULL, NULL);
+ pjsip_endpt_create_cancel(NULL, NULL, NULL);
+ pjsip_get_request_dest(NULL, NULL);
+ pjsip_endpt_send_request_stateless(NULL, NULL, NULL, NULL);
+ pjsip_get_response_addr(NULL, NULL, NULL);
+ pjsip_endpt_send_response(NULL, NULL, NULL, NULL, NULL);
+ pjsip_endpt_respond_stateless(NULL, NULL, -1, NULL, NULL, NULL);
+#endif
+
+#ifdef HAS_PJSIP_UDP_TRANSPORT
+ pjsip_udp_transport_start(NULL, NULL, NULL, 1, NULL);
+#endif
+
+#ifdef HAS_PJSIP_TCP_TRANSPORT
+ pjsip_tcp_transport_start(NULL, NULL, 1, NULL);
+#endif
+
+#ifdef HAS_PJSIP_TLS_TRANSPORT
+ pjsip_tls_transport_start(NULL, NULL, NULL, NULL, 0, NULL);
+#endif
+
+#ifdef HAS_PJSIP_TRANSACTION
+ pjsip_tsx_layer_init_module(NULL);
+
+ pjsip_tsx_layer_destroy();
+ pjsip_tsx_create_uac(NULL, NULL, NULL);
+ pjsip_tsx_create_uas(NULL, NULL, NULL);
+ pjsip_tsx_recv_msg(NULL, NULL);
+ pjsip_tsx_send_msg(NULL, NULL);
+ pjsip_tsx_terminate(NULL, 200);
+
+ pjsip_endpt_send_request(NULL, NULL, -1, NULL, NULL);
+ pjsip_endpt_respond(NULL, NULL, NULL, -1, NULL, NULL, NULL, NULL);
+#endif
+
+#ifdef HAS_PJMEDIA_SDP
+ pjmedia_sdp_parse(NULL, NULL, 1024, NULL);
+ pjmedia_sdp_print(NULL, NULL, 1024);
+ pjmedia_sdp_validate(NULL);
+ pjmedia_sdp_session_clone(NULL, NULL);
+ pjmedia_sdp_session_cmp(NULL, NULL, 0);
+ pjmedia_sdp_attr_to_rtpmap(NULL, NULL, NULL);
+ pjmedia_sdp_attr_get_fmtp(NULL, NULL);
+ pjmedia_sdp_attr_get_rtcp(NULL, NULL);
+ pjmedia_sdp_conn_clone(NULL, NULL);
+ pjmedia_sdp_media_clone(NULL, NULL);
+ pjmedia_sdp_media_find_attr(NULL, NULL, NULL);
+#endif
+
+#ifdef HAS_PJMEDIA_SDP_NEGOTIATOR
+ pjmedia_sdp_neg_create_w_local_offer(NULL, NULL, NULL);
+ pjmedia_sdp_neg_create_w_remote_offer(NULL, NULL, NULL, NULL);
+ pjmedia_sdp_neg_get_state(NULL);
+ pjmedia_sdp_neg_negotiate(NULL, NULL, PJ_FALSE);
+#endif
+
+#ifdef HAS_PJSIP_UA_LAYER
+ pjsip_ua_init_module(NULL, NULL);
+ pjsip_ua_destroy();
+ pjsip_dlg_create_uac(NULL, NULL, NULL, NULL, NULL, NULL);
+ pjsip_dlg_create_uas(NULL, NULL, NULL, NULL);
+ pjsip_dlg_terminate(NULL);
+ pjsip_dlg_set_route_set(NULL, NULL);
+ pjsip_dlg_create_request(NULL, NULL, -1, NULL);
+ pjsip_dlg_send_request(NULL, NULL, -1, NULL);
+ pjsip_dlg_create_response(NULL, NULL, -1, NULL, NULL);
+ pjsip_dlg_modify_response(NULL, NULL, -1, NULL);
+ pjsip_dlg_send_response(NULL, NULL, NULL);
+ pjsip_dlg_respond(NULL, NULL, -1, NULL, NULL, NULL);
+#endif
+
+#ifdef HAS_PJSIP_AUTH_CLIENT
+ pjsip_auth_clt_init(NULL, NULL, NULL, 0);
+ pjsip_auth_clt_clone(NULL, NULL, NULL);
+ pjsip_auth_clt_set_credentials(NULL, 0, NULL);
+ pjsip_auth_clt_init_req(NULL, NULL);
+ pjsip_auth_clt_reinit_req(NULL, NULL, NULL, NULL);
+#endif
+
+#ifdef HAS_PJSIP_INV_SESSION
+ pjsip_inv_usage_init(NULL, NULL);
+ pjsip_inv_create_uac(NULL, NULL, 0, NULL);
+ pjsip_inv_verify_request(NULL, NULL, NULL, NULL, NULL, NULL);
+ pjsip_inv_create_uas(NULL, NULL, NULL, 0, NULL);
+ pjsip_inv_terminate(NULL, 200, PJ_FALSE);
+ pjsip_inv_invite(NULL, NULL);
+ pjsip_inv_initial_answer(NULL, NULL, 200, NULL, NULL, NULL);
+ pjsip_inv_answer(NULL, 200, NULL, NULL, NULL);
+ pjsip_inv_end_session(NULL, 200, NULL, NULL);
+ pjsip_inv_reinvite(NULL, NULL, NULL, NULL);
+ pjsip_inv_update(NULL, NULL, NULL, NULL);
+ pjsip_inv_send_msg(NULL, NULL);
+ pjsip_dlg_get_inv_session(NULL);
+ //pjsip_tsx_get_inv_session(NULL);
+ pjsip_inv_state_name(PJSIP_INV_STATE_NULL);
+#endif
+
+#ifdef HAS_PJSIP_REGC
+ //pjsip_regc_get_module();
+ pjsip_regc_create(NULL, NULL, NULL, NULL);
+ pjsip_regc_destroy(NULL);
+ pjsip_regc_get_info(NULL, NULL);
+ pjsip_regc_get_pool(NULL);
+ pjsip_regc_init(NULL, NULL, NULL, NULL, 0, NULL, 600);
+ pjsip_regc_set_credentials(NULL, 1, NULL);
+ pjsip_regc_set_route_set(NULL, NULL);
+ pjsip_regc_register(NULL, PJ_TRUE, NULL);
+ pjsip_regc_unregister(NULL, NULL);
+ pjsip_regc_update_contact(NULL, 10, NULL);
+ pjsip_regc_update_expires(NULL, 600);
+ pjsip_regc_send(NULL, NULL);
+#endif
+
+#ifdef HAS_PJSIP_EVENT_FRAMEWORK
+ pjsip_evsub_init_module(NULL);
+ pjsip_evsub_instance();
+ pjsip_evsub_register_pkg(NULL, NULL, 30, 10, NULL);
+ pjsip_evsub_create_uac(NULL, NULL, NULL, 10, NULL);
+ pjsip_evsub_create_uas(NULL, NULL, NULL, 10, NULL);
+ pjsip_evsub_terminate(NULL, PJ_FALSE);
+ pjsip_evsub_get_state(NULL);
+ pjsip_evsub_get_state_name(NULL);
+ pjsip_evsub_initiate(NULL, NULL, -1, NULL);
+ pjsip_evsub_accept(NULL, NULL, 200, NULL);
+ pjsip_evsub_notify(NULL, PJSIP_EVSUB_STATE_ACTIVE, NULL, NULL, NULL);
+ pjsip_evsub_current_notify(NULL, NULL);
+ pjsip_evsub_send_request(NULL, NULL);
+ pjsip_tsx_get_evsub(NULL);
+ pjsip_evsub_set_mod_data(NULL, 1, NULL);
+ pjsip_evsub_get_mod_data(NULL, 1);
+#endif
+
+#ifdef HAS_PJSIP_CALL_TRANSFER
+ pjsip_xfer_init_module(NULL);
+ pjsip_xfer_create_uac(NULL, NULL, NULL);
+ pjsip_xfer_create_uas(NULL, NULL, NULL, NULL);
+ pjsip_xfer_initiate(NULL, NULL, NULL);
+ pjsip_xfer_accept(NULL, NULL, 200, NULL);
+ pjsip_xfer_notify(NULL, PJSIP_EVSUB_STATE_ACTIVE, 200, NULL, NULL);
+ pjsip_xfer_current_notify(NULL, NULL);
+ pjsip_xfer_send_request(NULL, NULL);
+#endif
+
+#ifdef HAS_PJSIP_PRESENCE
+ pjsip_pres_init_module(NULL, NULL);
+ pjsip_pres_instance();
+ pjsip_pres_create_uac(NULL, NULL, 0, NULL);
+ pjsip_pres_create_uas(NULL, NULL, NULL, NULL);
+ pjsip_pres_terminate(NULL, PJ_FALSE);
+ pjsip_pres_initiate(NULL, 100, NULL);
+ pjsip_pres_accept(NULL, NULL, 200, NULL);
+ pjsip_pres_notify(NULL, PJSIP_EVSUB_STATE_ACTIVE, NULL, NULL, NULL);
+ pjsip_pres_current_notify(NULL, NULL);
+ pjsip_pres_send_request(NULL, NULL);
+ pjsip_pres_get_status(NULL, NULL);
+ pjsip_pres_set_status(NULL, NULL);
+#endif
+
+#ifdef HAS_PJSIP_IS_COMPOSING
+ pjsip_iscomposing_create_xml(NULL, PJ_TRUE, NULL, NULL, 0);
+ pjsip_iscomposing_create_body(NULL, PJ_TRUE, NULL, NULL, 0);
+ pjsip_iscomposing_parse(NULL, NULL, 0, NULL, NULL, NULL, NULL);
+#endif
+
+#ifdef HAS_PJMEDIA
+ pjmedia_endpt_create(NULL, NULL, 1, NULL);
+ pjmedia_endpt_destroy(NULL);
+ pjmedia_endpt_create_sdp(NULL, NULL, 1, NULL, NULL);
+#endif
+
+#ifdef HAS_PJMEDIA_EC
+ pjmedia_echo_create(NULL, 0, 0, 0, 0, 0, NULL);
+ pjmedia_echo_destroy(NULL);
+ pjmedia_echo_playback(NULL, NULL);
+ pjmedia_echo_capture(NULL, NULL, 0);
+ pjmedia_echo_cancel(NULL, NULL, NULL, 0, NULL);
+#endif
+
+#ifdef HAS_PJMEDIA_SND_DEV
+ pjmedia_snd_init(NULL);
+ pjmedia_snd_get_dev_count();
+ pjmedia_snd_get_dev_info(0);
+ pjmedia_snd_open(-1, -1, 8000, 1, 80, 16, NULL, NULL, NULL, NULL);
+ pjmedia_snd_open_rec(-1, 8000, 1, 160, 16, NULL, NULL, NULL);
+ pjmedia_snd_open_player(-1, 8000, 1, 160, 16, NULL, NULL, NULL);
+ pjmedia_snd_stream_start(NULL);
+ pjmedia_snd_stream_stop(NULL);
+ pjmedia_snd_stream_close(NULL);
+ pjmedia_snd_deinit();
+#endif
+
+#ifdef HAS_PJMEDIA_SND_PORT
+ pjmedia_snd_port_create(NULL, -1, -1, 8000, 1, 180, 16, 0, NULL);
+ pjmedia_snd_port_create_rec(NULL, -1, 8000, 1, 160, 16, 0, NULL);
+ pjmedia_snd_port_create_player(NULL, -1, 8000, 1, 160, 16, 0, NULL);
+ pjmedia_snd_port_destroy(NULL);
+ pjmedia_snd_port_get_snd_stream(NULL);
+ pjmedia_snd_port_connect(NULL, NULL);
+ pjmedia_snd_port_get_port(NULL);
+ pjmedia_snd_port_disconnect(NULL);
+#endif
+
+#ifdef HAS_PJMEDIA_RESAMPLE
+ pjmedia_resample_create(NULL, PJ_TRUE, PJ_TRUE, 0, 0, 0, 0, NULL);
+ pjmedia_resample_run(NULL, NULL, NULL);
+#endif
+
+#ifdef HAS_PJMEDIA_SILENCE_DET
+ pjmedia_silence_det_create(NULL, 8000, 80, NULL);
+ pjmedia_silence_det_detect(NULL, NULL, 0, NULL);
+ pjmedia_silence_det_apply(NULL, 0);
+#endif
+
+#ifdef HAS_PJMEDIA_PLC
+ pjmedia_plc_create(NULL, 8000, 80, 0, NULL);
+ pjmedia_plc_save(NULL, NULL);
+ pjmedia_plc_generate(NULL, NULL);
+#endif
+
+#ifdef HAS_PJMEDIA_CONFERENCE
+ pjmedia_conf_create(NULL, 10, 8000, 1, 160, 16, 0, NULL);
+ pjmedia_conf_destroy(NULL);
+ pjmedia_conf_get_master_port(NULL);
+ pjmedia_conf_add_port(NULL, NULL, NULL, NULL, NULL);
+ pjmedia_conf_configure_port(NULL, 1, 0, 0);
+ pjmedia_conf_connect_port(NULL, 0, 0, 0);
+ pjmedia_conf_disconnect_port(NULL, 0, 0);
+ pjmedia_conf_remove_port(NULL, 0);
+ pjmedia_conf_enum_ports(NULL, NULL, NULL);
+ pjmedia_conf_get_port_info(NULL, 0, NULL);
+ pjmedia_conf_get_ports_info(NULL, NULL, NULL);
+ pjmedia_conf_get_signal_level(NULL, 0, NULL, NULL);
+ pjmedia_conf_adjust_rx_level(NULL, 0, 0);
+ pjmedia_conf_adjust_tx_level(NULL, 0, 0);
+#endif
+
+#ifdef HAS_PJMEDIA_MASTER_PORT
+ pjmedia_master_port_create(NULL, NULL, NULL, 0, NULL);
+ pjmedia_master_port_start(NULL);
+ pjmedia_master_port_stop(NULL);
+ pjmedia_master_port_set_uport(NULL, NULL);
+ pjmedia_master_port_get_uport(NULL);
+ pjmedia_master_port_set_dport(NULL, NULL);
+ pjmedia_master_port_get_dport(NULL);
+ pjmedia_master_port_destroy(NULL, PJ_FALSE);
+#endif
+
+#ifdef HAS_PJMEDIA_RTP
+ pjmedia_rtp_session_init(NULL, 0, 0);
+ pjmedia_rtp_encode_rtp(NULL, 0, 0, 0, 0, NULL, NULL);
+ pjmedia_rtp_decode_rtp(NULL, NULL, 0, NULL, NULL, NULL);
+ pjmedia_rtp_session_update(NULL, NULL, NULL);
+#endif
+
+#ifdef HAS_PJMEDIA_RTCP
+ pjmedia_rtcp_init(NULL, NULL, 0, 0, 0);
+ pjmedia_rtcp_get_ntp_time(NULL, NULL);
+ pjmedia_rtcp_fini(NULL);
+ pjmedia_rtcp_rx_rtp(NULL, 0, 0, 0);
+ pjmedia_rtcp_tx_rtp(NULL, 0);
+ pjmedia_rtcp_rx_rtcp(NULL, NULL, 0);
+ pjmedia_rtcp_build_rtcp(NULL, NULL, NULL);
+#endif
+
+#ifdef HAS_PJMEDIA_JBUF
+ pjmedia_jbuf_create(NULL, NULL, 0, 0, 0, NULL);
+ pjmedia_jbuf_set_fixed(NULL, 0);
+ pjmedia_jbuf_set_adaptive(NULL, 0, 0, 0);
+ pjmedia_jbuf_destroy(NULL);
+ pjmedia_jbuf_put_frame(NULL, NULL, 0, 0);
+ pjmedia_jbuf_get_frame(NULL, NULL, NULL);
+#endif
+
+#ifdef HAS_PJMEDIA_STREAM
+ pjmedia_stream_create(NULL, NULL, NULL, NULL, NULL, NULL);
+ pjmedia_stream_destroy(NULL);
+ pjmedia_stream_get_port(NULL, NULL);
+ pjmedia_stream_get_transport(NULL);
+ pjmedia_stream_start(NULL);
+ pjmedia_stream_get_stat(NULL, NULL);
+ pjmedia_stream_pause(NULL, PJMEDIA_DIR_ENCODING);
+ pjmedia_stream_resume(NULL, PJMEDIA_DIR_ENCODING);
+ pjmedia_stream_dial_dtmf(NULL, NULL);
+ pjmedia_stream_check_dtmf(NULL);
+ pjmedia_stream_get_dtmf(NULL, NULL, NULL);
+#endif
+
+#ifdef HAS_PJMEDIA_TONEGEN
+ pjmedia_tonegen_create(NULL, 0, 0, 0, 0, 0, NULL);
+ pjmedia_tonegen_is_busy(NULL);
+ pjmedia_tonegen_stop(NULL);
+ pjmedia_tonegen_play(NULL, 0, NULL, 0);
+ pjmedia_tonegen_play_digits(NULL, 0, NULL, 0);
+ pjmedia_tonegen_get_digit_map(NULL, NULL);
+ pjmedia_tonegen_set_digit_map(NULL, NULL);
+#endif
+
+#ifdef HAS_PJMEDIA_UDP_TRANSPORT
+ pjmedia_transport_udp_create(NULL, NULL, 0, 0, NULL);
+ pjmedia_transport_udp_close(NULL);
+#endif
+
+#ifdef HAS_PJMEDIA_FILE_PLAYER
+ pjmedia_wav_player_port_create(NULL, NULL, 0, 0, 0, NULL);
+ pjmedia_wav_player_port_set_pos(NULL, 0);
+ pjmedia_wav_player_port_get_pos(NULL);
+ pjmedia_wav_player_set_eof_cb(NULL, NULL, NULL);
+#endif
+
+#ifdef HAS_PJMEDIA_FILE_CAPTURE
+ pjmedia_wav_writer_port_create(NULL, NULL, 8000, 1, 80, 16, 0, 0, NULL);
+ pjmedia_wav_writer_port_get_pos(NULL);
+ pjmedia_wav_writer_port_set_cb(NULL, 0, NULL, NULL);
+#endif
+
+#ifdef HAS_PJMEDIA_MEM_PLAYER
+ pjmedia_mem_player_create(NULL, NULL, 1000, 8000, 1, 80, 16, 0, NULL);
+#endif
+
+#ifdef HAS_PJMEDIA_MEM_CAPTURE
+ pjmedia_mem_capture_create(NULL, NULL, 1000, 8000, 1, 80, 16, 0, NULL);
+#endif
+
+#ifdef HAS_PJMEDIA_ICE
+ pjmedia_ice_create(NULL, NULL, 0, NULL, NULL);
+ pjmedia_ice_destroy(NULL);
+ pjmedia_ice_start_init(NULL, 0, NULL, NULL, NULL);
+ pjmedia_ice_init_ice(NULL, PJ_ICE_SESS_ROLE_CONTROLLED, NULL, NULL);
+ pjmedia_ice_modify_sdp(NULL, NULL, NULL);
+ pjmedia_ice_start_ice(NULL, NULL, NULL, 0);
+ pjmedia_ice_stop_ice(NULL);
+#endif
+
+#ifdef HAS_PJMEDIA_G711_CODEC
+ pjmedia_codec_g711_init(NULL);
+ pjmedia_codec_g711_deinit();
+#endif
+
+#ifdef HAS_PJMEDIA_GSM_CODEC
+ pjmedia_codec_gsm_init(NULL);
+ pjmedia_codec_gsm_deinit();
+#endif
+
+#ifdef HAS_PJMEDIA_SPEEX_CODEC
+ pjmedia_codec_speex_init(NULL, 0, 0, 0);
+ pjmedia_codec_speex_deinit();
+#endif
+
+#ifdef HAS_PJMEDIA_ILBC_CODEC
+ pjmedia_codec_ilbc_init(NULL, 0);
+ pjmedia_codec_ilbc_deinit();
+#endif
+
+ return 0;
+}
+
+
+int test_main()
+{
+ return dummy_function();
+}
+
+#if defined(PJ_RTEMS) && PJ_RTEMS!=0
+# include "../../pjlib/src/pjlib-test/main_rtems.c"
+#else
+int main()
+{
+ return test_main();
+}
+#endif
+
diff --git a/pjsip-apps/src/samples/httpdemo.c b/pjsip-apps/src/samples/httpdemo.c
new file mode 100644
index 0000000..6b2bf8e
--- /dev/null
+++ b/pjsip-apps/src/samples/httpdemo.c
@@ -0,0 +1,183 @@
+/* $Id: httpdemo.c 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/**
+ * \page page_httpdemo_c Samples: HTTP Client demo
+ *
+ * This file is pjsip-apps/src/samples/httpdemo.c
+ *
+ * \includelineno httpdemo.c
+ */
+
+#include <pjlib.h>
+#include <pjlib-util.h>
+#include <pjlib-util/http_client.h>
+#include <pjsip.h>
+#include <pjmedia.h>
+#include <pjnath.h>
+#include <pjsip_simple.h>
+
+static pj_timer_heap_t *timer_heap;
+static pj_ioqueue_t *ioqueue;
+static pj_pool_t *pool;
+static pj_http_req *http_req;
+static pj_pool_factory *mem;
+static FILE *f = NULL;
+
+//#define VERBOSE
+#define THIS_FILE "http_demo"
+
+static void on_response(pj_http_req *http_req, const pj_http_resp *resp)
+{
+ unsigned i;
+
+ PJ_UNUSED_ARG(http_req);
+ PJ_LOG(3,(THIS_FILE, "%.*s %d %.*s", (int)resp->version.slen, resp->version.ptr,
+ resp->status_code,
+ (int)resp->reason.slen, resp->reason.ptr));
+
+ for (i=0; i<resp->headers.count; ++i) {
+ const pj_http_header_elmt *h = &resp->headers.header[i];
+
+ if (!pj_stricmp2(&h->name, "Content-Length") ||
+ !pj_stricmp2(&h->name, "Content-Type"))
+ {
+ PJ_LOG(3,(THIS_FILE, "%.*s: %.*s",
+ (int)h->name.slen, h->name.ptr,
+ (int)h->value.slen, h->value.ptr));
+ }
+ }
+}
+
+static void on_send_data(pj_http_req *http_req, void **data, pj_size_t *size)
+{
+ PJ_UNUSED_ARG(http_req);
+ PJ_UNUSED_ARG(size);
+ PJ_UNUSED_ARG(data);
+}
+
+static void on_data_read(pj_http_req *hreq, void *data, pj_size_t size)
+{
+ PJ_UNUSED_ARG(hreq);
+
+ if (size > 0) {
+ fwrite(data, 1, size, f);
+ fflush(f);
+#ifdef VERBOSE
+ PJ_LOG(3, (THIS_FILE, "Data received: %d bytes", size));
+ printf("%.*s\n", (int)size, (char *)data);
+#endif
+ }
+}
+
+static void on_complete(pj_http_req *hreq, pj_status_t status,
+ const pj_http_resp *resp)
+{
+ PJ_UNUSED_ARG(hreq);
+
+ if (status != PJ_SUCCESS) {
+ PJ_PERROR(1, (THIS_FILE, status, "HTTP request completed with error"));
+ return;
+ }
+ PJ_LOG(3, (THIS_FILE, "Data completed: %d bytes", resp->size));
+ if (resp->size > 0 && resp->data) {
+#ifdef VERBOSE
+ printf("%.*s\n", (int)resp->size, (char *)resp->data);
+#endif
+ }
+}
+
+pj_status_t getURL(const char *curl)
+{
+ pj_str_t url;
+ pj_http_req_callback hcb;
+ pj_status_t status;
+
+ pj_bzero(&hcb, sizeof(hcb));
+ hcb.on_complete = &on_complete;
+ hcb.on_data_read = &on_data_read;
+ hcb.on_send_data = &on_send_data;
+ hcb.on_response = &on_response;
+
+ /* Create pool, timer, and ioqueue */
+ pool = pj_pool_create(mem, NULL, 8192, 4096, NULL);
+ if (pj_timer_heap_create(pool, 16, &timer_heap))
+ return -31;
+ if (pj_ioqueue_create(pool, 16, &ioqueue))
+ return -32;
+
+ pj_strdup2(pool, &url, curl);
+
+ if ((status = pj_http_req_create(pool, &url, timer_heap, ioqueue,
+ NULL, &hcb, &http_req)) != PJ_SUCCESS)
+ return status;
+
+ if ((status = pj_http_req_start(http_req)) != PJ_SUCCESS)
+ return status;
+
+ while (pj_http_req_is_running(http_req)) {
+ pj_time_val delay = {0, 50};
+ pj_ioqueue_poll(ioqueue, &delay);
+ pj_timer_heap_poll(timer_heap, NULL);
+ }
+
+ pj_http_req_destroy(http_req);
+ pj_ioqueue_destroy(ioqueue);
+ pj_timer_heap_destroy(timer_heap);
+ pj_pool_release(pool);
+
+ return PJ_SUCCESS;
+}
+/*
+ * main()
+ */
+int main(int argc, char *argv[])
+{
+ pj_caching_pool cp;
+ pj_status_t status;
+
+ if (argc < 2 || argc > 3) {
+ puts("Usage: httpdemo URL [output-filename]");
+ return 1;
+ }
+
+ pj_log_set_level(5);
+
+ pj_init();
+ pj_caching_pool_init(&cp, NULL, 0);
+ mem = &cp.factory;
+ pjlib_util_init();
+
+ if (argc > 2)
+ f = fopen(argv[2], "wb");
+ else
+ f = stdout;
+
+ status = getURL(argv[1]);
+ if (status != PJ_SUCCESS) {
+ PJ_PERROR(1, (THIS_FILE, status, "Error"));
+ }
+
+ if (f != stdout)
+ fclose(f);
+
+ pj_caching_pool_destroy(&cp);
+ pj_shutdown();
+ return 0;
+}
diff --git a/pjsip-apps/src/samples/icedemo.c b/pjsip-apps/src/samples/icedemo.c
new file mode 100644
index 0000000..08292ee
--- /dev/null
+++ b/pjsip-apps/src/samples/icedemo.c
@@ -0,0 +1,1276 @@
+/* $Id: icedemo.c 3841 2011-10-24 09:28:13Z ming $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <pjlib.h>
+#include <pjlib-util.h>
+#include <pjnath.h>
+
+
+#define THIS_FILE "icedemo.c"
+
+/* For this demo app, configure longer STUN keep-alive time
+ * so that it does't clutter the screen output.
+ */
+#define KA_INTERVAL 300
+
+
+/* This is our global variables */
+static struct app_t
+{
+ /* Command line options are stored here */
+ struct options
+ {
+ unsigned comp_cnt;
+ pj_str_t ns;
+ int max_host;
+ pj_bool_t regular;
+ pj_str_t stun_srv;
+ pj_str_t turn_srv;
+ pj_bool_t turn_tcp;
+ pj_str_t turn_username;
+ pj_str_t turn_password;
+ pj_bool_t turn_fingerprint;
+ const char *log_file;
+ } opt;
+
+ /* Our global variables */
+ pj_caching_pool cp;
+ pj_pool_t *pool;
+ pj_thread_t *thread;
+ pj_bool_t thread_quit_flag;
+ pj_ice_strans_cfg ice_cfg;
+ pj_ice_strans *icest;
+ FILE *log_fhnd;
+
+ /* Variables to store parsed remote ICE info */
+ struct rem_info
+ {
+ char ufrag[80];
+ char pwd[80];
+ unsigned comp_cnt;
+ pj_sockaddr def_addr[PJ_ICE_MAX_COMP];
+ unsigned cand_cnt;
+ pj_ice_sess_cand cand[PJ_ICE_ST_MAX_CAND];
+ } rem;
+
+} icedemo;
+
+/* Utility to display error messages */
+static void icedemo_perror(const char *title, pj_status_t status)
+{
+ char errmsg[PJ_ERR_MSG_SIZE];
+
+ pj_strerror(status, errmsg, sizeof(errmsg));
+ PJ_LOG(1,(THIS_FILE, "%s: %s", title, errmsg));
+}
+
+/* Utility: display error message and exit application (usually
+ * because of fatal error.
+ */
+static void err_exit(const char *title, pj_status_t status)
+{
+ if (status != PJ_SUCCESS) {
+ icedemo_perror(title, status);
+ }
+ PJ_LOG(3,(THIS_FILE, "Shutting down.."));
+
+ if (icedemo.icest)
+ pj_ice_strans_destroy(icedemo.icest);
+
+ pj_thread_sleep(500);
+
+ icedemo.thread_quit_flag = PJ_TRUE;
+ if (icedemo.thread) {
+ pj_thread_join(icedemo.thread);
+ pj_thread_destroy(icedemo.thread);
+ }
+
+ if (icedemo.ice_cfg.stun_cfg.ioqueue)
+ pj_ioqueue_destroy(icedemo.ice_cfg.stun_cfg.ioqueue);
+
+ if (icedemo.ice_cfg.stun_cfg.timer_heap)
+ pj_timer_heap_destroy(icedemo.ice_cfg.stun_cfg.timer_heap);
+
+ pj_caching_pool_destroy(&icedemo.cp);
+
+ pj_shutdown();
+
+ if (icedemo.log_fhnd) {
+ fclose(icedemo.log_fhnd);
+ icedemo.log_fhnd = NULL;
+ }
+
+ exit(status != PJ_SUCCESS);
+}
+
+#define CHECK(expr) status=expr; \
+ if (status!=PJ_SUCCESS) { \
+ err_exit(#expr, status); \
+ }
+
+/*
+ * This function checks for events from both timer and ioqueue (for
+ * network events). It is invoked by the worker thread.
+ */
+static pj_status_t handle_events(unsigned max_msec, unsigned *p_count)
+{
+ enum { MAX_NET_EVENTS = 1 };
+ pj_time_val max_timeout = {0, 0};
+ pj_time_val timeout = { 0, 0};
+ unsigned count = 0, net_event_count = 0;
+ int c;
+
+ max_timeout.msec = max_msec;
+
+ /* Poll the timer to run it and also to retrieve the earliest entry. */
+ timeout.sec = timeout.msec = 0;
+ c = pj_timer_heap_poll( icedemo.ice_cfg.stun_cfg.timer_heap, &timeout );
+ if (c > 0)
+ count += c;
+
+ /* timer_heap_poll should never ever returns negative value, or otherwise
+ * ioqueue_poll() will block forever!
+ */
+ pj_assert(timeout.sec >= 0 && timeout.msec >= 0);
+ if (timeout.msec >= 1000) timeout.msec = 999;
+
+ /* compare the value with the timeout to wait from timer, and use the
+ * minimum value.
+ */
+ if (PJ_TIME_VAL_GT(timeout, max_timeout))
+ timeout = max_timeout;
+
+ /* Poll ioqueue.
+ * Repeat polling the ioqueue while we have immediate events, because
+ * timer heap may process more than one events, so if we only process
+ * one network events at a time (such as when IOCP backend is used),
+ * the ioqueue may have trouble keeping up with the request rate.
+ *
+ * For example, for each send() request, one network event will be
+ * reported by ioqueue for the send() completion. If we don't poll
+ * the ioqueue often enough, the send() completion will not be
+ * reported in timely manner.
+ */
+ do {
+ c = pj_ioqueue_poll( icedemo.ice_cfg.stun_cfg.ioqueue, &timeout);
+ if (c < 0) {
+ pj_status_t err = pj_get_netos_error();
+ pj_thread_sleep(PJ_TIME_VAL_MSEC(timeout));
+ if (p_count)
+ *p_count = count;
+ return err;
+ } else if (c == 0) {
+ break;
+ } else {
+ net_event_count += c;
+ timeout.sec = timeout.msec = 0;
+ }
+ } while (c > 0 && net_event_count < MAX_NET_EVENTS);
+
+ count += net_event_count;
+ if (p_count)
+ *p_count = count;
+
+ return PJ_SUCCESS;
+
+}
+
+/*
+ * This is the worker thread that polls event in the background.
+ */
+static int icedemo_worker_thread(void *unused)
+{
+ PJ_UNUSED_ARG(unused);
+
+ while (!icedemo.thread_quit_flag) {
+ handle_events(500, NULL);
+ }
+
+ return 0;
+}
+
+/*
+ * This is the callback that is registered to the ICE stream transport to
+ * receive notification about incoming data. By "data" it means application
+ * data such as RTP/RTCP, and not packets that belong to ICE signaling (such
+ * as STUN connectivity checks or TURN signaling).
+ */
+static void cb_on_rx_data(pj_ice_strans *ice_st,
+ unsigned comp_id,
+ void *pkt, pj_size_t size,
+ const pj_sockaddr_t *src_addr,
+ unsigned src_addr_len)
+{
+ char ipstr[PJ_INET6_ADDRSTRLEN+10];
+
+ PJ_UNUSED_ARG(ice_st);
+ PJ_UNUSED_ARG(src_addr_len);
+ PJ_UNUSED_ARG(pkt);
+
+ // Don't do this! It will ruin the packet buffer in case TCP is used!
+ //((char*)pkt)[size] = '\0';
+
+ PJ_LOG(3,(THIS_FILE, "Component %d: received %d bytes data from %s: \"%.*s\"",
+ comp_id, size,
+ pj_sockaddr_print(src_addr, ipstr, sizeof(ipstr), 3),
+ (unsigned)size,
+ (char*)pkt));
+}
+
+/*
+ * This is the callback that is registered to the ICE stream transport to
+ * receive notification about ICE state progression.
+ */
+static void cb_on_ice_complete(pj_ice_strans *ice_st,
+ pj_ice_strans_op op,
+ pj_status_t status)
+{
+ const char *opname =
+ (op==PJ_ICE_STRANS_OP_INIT? "initialization" :
+ (op==PJ_ICE_STRANS_OP_NEGOTIATION ? "negotiation" : "unknown_op"));
+
+ if (status == PJ_SUCCESS) {
+ PJ_LOG(3,(THIS_FILE, "ICE %s successful", opname));
+ } else {
+ char errmsg[PJ_ERR_MSG_SIZE];
+
+ pj_strerror(status, errmsg, sizeof(errmsg));
+ PJ_LOG(1,(THIS_FILE, "ICE %s failed: %s", opname, errmsg));
+ pj_ice_strans_destroy(ice_st);
+ icedemo.icest = NULL;
+ }
+}
+
+/* log callback to write to file */
+static void log_func(int level, const char *data, int len)
+{
+ pj_log_write(level, data, len);
+ if (icedemo.log_fhnd) {
+ if (fwrite(data, len, 1, icedemo.log_fhnd) != 1)
+ return;
+ }
+}
+
+/*
+ * This is the main application initialization function. It is called
+ * once (and only once) during application initialization sequence by
+ * main().
+ */
+static pj_status_t icedemo_init(void)
+{
+ pj_status_t status;
+
+ if (icedemo.opt.log_file) {
+ icedemo.log_fhnd = fopen(icedemo.opt.log_file, "a");
+ pj_log_set_log_func(&log_func);
+ }
+
+ /* Initialize the libraries before anything else */
+ CHECK( pj_init() );
+ CHECK( pjlib_util_init() );
+ CHECK( pjnath_init() );
+
+ /* Must create pool factory, where memory allocations come from */
+ pj_caching_pool_init(&icedemo.cp, NULL, 0);
+
+ /* Init our ICE settings with null values */
+ pj_ice_strans_cfg_default(&icedemo.ice_cfg);
+
+ icedemo.ice_cfg.stun_cfg.pf = &icedemo.cp.factory;
+
+ /* Create application memory pool */
+ icedemo.pool = pj_pool_create(&icedemo.cp.factory, "icedemo",
+ 512, 512, NULL);
+
+ /* Create timer heap for timer stuff */
+ CHECK( pj_timer_heap_create(icedemo.pool, 100,
+ &icedemo.ice_cfg.stun_cfg.timer_heap) );
+
+ /* and create ioqueue for network I/O stuff */
+ CHECK( pj_ioqueue_create(icedemo.pool, 16,
+ &icedemo.ice_cfg.stun_cfg.ioqueue) );
+
+ /* something must poll the timer heap and ioqueue,
+ * unless we're on Symbian where the timer heap and ioqueue run
+ * on themselves.
+ */
+ CHECK( pj_thread_create(icedemo.pool, "icedemo", &icedemo_worker_thread,
+ NULL, 0, 0, &icedemo.thread) );
+
+ icedemo.ice_cfg.af = pj_AF_INET();
+
+ /* Create DNS resolver if nameserver is set */
+ if (icedemo.opt.ns.slen) {
+ CHECK( pj_dns_resolver_create(&icedemo.cp.factory,
+ "resolver",
+ 0,
+ icedemo.ice_cfg.stun_cfg.timer_heap,
+ icedemo.ice_cfg.stun_cfg.ioqueue,
+ &icedemo.ice_cfg.resolver) );
+
+ CHECK( pj_dns_resolver_set_ns(icedemo.ice_cfg.resolver, 1,
+ &icedemo.opt.ns, NULL) );
+ }
+
+ /* -= Start initializing ICE stream transport config =- */
+
+ /* Maximum number of host candidates */
+ if (icedemo.opt.max_host != -1)
+ icedemo.ice_cfg.stun.max_host_cands = icedemo.opt.max_host;
+
+ /* Nomination strategy */
+ if (icedemo.opt.regular)
+ icedemo.ice_cfg.opt.aggressive = PJ_FALSE;
+ else
+ icedemo.ice_cfg.opt.aggressive = PJ_TRUE;
+
+ /* Configure STUN/srflx candidate resolution */
+ if (icedemo.opt.stun_srv.slen) {
+ char *pos;
+
+ /* Command line option may contain port number */
+ if ((pos=pj_strchr(&icedemo.opt.stun_srv, ':')) != NULL) {
+ icedemo.ice_cfg.stun.server.ptr = icedemo.opt.stun_srv.ptr;
+ icedemo.ice_cfg.stun.server.slen = (pos - icedemo.opt.stun_srv.ptr);
+
+ icedemo.ice_cfg.stun.port = (pj_uint16_t)atoi(pos+1);
+ } else {
+ icedemo.ice_cfg.stun.server = icedemo.opt.stun_srv;
+ icedemo.ice_cfg.stun.port = PJ_STUN_PORT;
+ }
+
+ /* For this demo app, configure longer STUN keep-alive time
+ * so that it does't clutter the screen output.
+ */
+ icedemo.ice_cfg.stun.cfg.ka_interval = KA_INTERVAL;
+ }
+
+ /* Configure TURN candidate */
+ if (icedemo.opt.turn_srv.slen) {
+ char *pos;
+
+ /* Command line option may contain port number */
+ if ((pos=pj_strchr(&icedemo.opt.turn_srv, ':')) != NULL) {
+ icedemo.ice_cfg.turn.server.ptr = icedemo.opt.turn_srv.ptr;
+ icedemo.ice_cfg.turn.server.slen = (pos - icedemo.opt.turn_srv.ptr);
+
+ icedemo.ice_cfg.turn.port = (pj_uint16_t)atoi(pos+1);
+ } else {
+ icedemo.ice_cfg.turn.server = icedemo.opt.turn_srv;
+ icedemo.ice_cfg.turn.port = PJ_STUN_PORT;
+ }
+
+ /* TURN credential */
+ icedemo.ice_cfg.turn.auth_cred.type = PJ_STUN_AUTH_CRED_STATIC;
+ icedemo.ice_cfg.turn.auth_cred.data.static_cred.username = icedemo.opt.turn_username;
+ icedemo.ice_cfg.turn.auth_cred.data.static_cred.data_type = PJ_STUN_PASSWD_PLAIN;
+ icedemo.ice_cfg.turn.auth_cred.data.static_cred.data = icedemo.opt.turn_password;
+
+ /* Connection type to TURN server */
+ if (icedemo.opt.turn_tcp)
+ icedemo.ice_cfg.turn.conn_type = PJ_TURN_TP_TCP;
+ else
+ icedemo.ice_cfg.turn.conn_type = PJ_TURN_TP_UDP;
+
+ /* For this demo app, configure longer keep-alive time
+ * so that it does't clutter the screen output.
+ */
+ icedemo.ice_cfg.turn.alloc_param.ka_interval = KA_INTERVAL;
+ }
+
+ /* -= That's it for now, initialization is complete =- */
+ return PJ_SUCCESS;
+}
+
+
+/*
+ * Create ICE stream transport instance, invoked from the menu.
+ */
+static void icedemo_create_instance(void)
+{
+ pj_ice_strans_cb icecb;
+ pj_status_t status;
+
+ if (icedemo.icest != NULL) {
+ puts("ICE instance already created, destroy it first");
+ return;
+ }
+
+ /* init the callback */
+ pj_bzero(&icecb, sizeof(icecb));
+ icecb.on_rx_data = cb_on_rx_data;
+ icecb.on_ice_complete = cb_on_ice_complete;
+
+ /* create the instance */
+ status = pj_ice_strans_create("icedemo", /* object name */
+ &icedemo.ice_cfg, /* settings */
+ icedemo.opt.comp_cnt, /* comp_cnt */
+ NULL, /* user data */
+ &icecb, /* callback */
+ &icedemo.icest) /* instance ptr */
+ ;
+ if (status != PJ_SUCCESS)
+ icedemo_perror("error creating ice", status);
+ else
+ PJ_LOG(3,(THIS_FILE, "ICE instance successfully created"));
+}
+
+/* Utility to nullify parsed remote info */
+static void reset_rem_info(void)
+{
+ pj_bzero(&icedemo.rem, sizeof(icedemo.rem));
+}
+
+
+/*
+ * Destroy ICE stream transport instance, invoked from the menu.
+ */
+static void icedemo_destroy_instance(void)
+{
+ if (icedemo.icest == NULL) {
+ PJ_LOG(1,(THIS_FILE, "Error: No ICE instance, create it first"));
+ return;
+ }
+
+ pj_ice_strans_destroy(icedemo.icest);
+ icedemo.icest = NULL;
+
+ reset_rem_info();
+
+ PJ_LOG(3,(THIS_FILE, "ICE instance destroyed"));
+}
+
+
+/*
+ * Create ICE session, invoked from the menu.
+ */
+static void icedemo_init_session(unsigned rolechar)
+{
+ pj_ice_sess_role role = (pj_tolower((pj_uint8_t)rolechar)=='o' ?
+ PJ_ICE_SESS_ROLE_CONTROLLING :
+ PJ_ICE_SESS_ROLE_CONTROLLED);
+ pj_status_t status;
+
+ if (icedemo.icest == NULL) {
+ PJ_LOG(1,(THIS_FILE, "Error: No ICE instance, create it first"));
+ return;
+ }
+
+ if (pj_ice_strans_has_sess(icedemo.icest)) {
+ PJ_LOG(1,(THIS_FILE, "Error: Session already created"));
+ return;
+ }
+
+ status = pj_ice_strans_init_ice(icedemo.icest, role, NULL, NULL);
+ if (status != PJ_SUCCESS)
+ icedemo_perror("error creating session", status);
+ else
+ PJ_LOG(3,(THIS_FILE, "ICE session created"));
+
+ reset_rem_info();
+}
+
+
+/*
+ * Stop/destroy ICE session, invoked from the menu.
+ */
+static void icedemo_stop_session(void)
+{
+ pj_status_t status;
+
+ if (icedemo.icest == NULL) {
+ PJ_LOG(1,(THIS_FILE, "Error: No ICE instance, create it first"));
+ return;
+ }
+
+ if (!pj_ice_strans_has_sess(icedemo.icest)) {
+ PJ_LOG(1,(THIS_FILE, "Error: No ICE session, initialize first"));
+ return;
+ }
+
+ status = pj_ice_strans_stop_ice(icedemo.icest);
+ if (status != PJ_SUCCESS)
+ icedemo_perror("error stopping session", status);
+ else
+ PJ_LOG(3,(THIS_FILE, "ICE session stopped"));
+
+ reset_rem_info();
+}
+
+#define PRINT(fmt, arg0, arg1, arg2, arg3, arg4, arg5) \
+ printed = pj_ansi_snprintf(p, maxlen - (p-buffer), \
+ fmt, arg0, arg1, arg2, arg3, arg4, arg5); \
+ if (printed <= 0) return -PJ_ETOOSMALL; \
+ p += printed
+
+
+/* Utility to create a=candidate SDP attribute */
+static int print_cand(char buffer[], unsigned maxlen,
+ const pj_ice_sess_cand *cand)
+{
+ char ipaddr[PJ_INET6_ADDRSTRLEN];
+ char *p = buffer;
+ int printed;
+
+ PRINT("a=candidate:%.*s %u UDP %u %s %u typ ",
+ (int)cand->foundation.slen,
+ cand->foundation.ptr,
+ (unsigned)cand->comp_id,
+ cand->prio,
+ pj_sockaddr_print(&cand->addr, ipaddr,
+ sizeof(ipaddr), 0),
+ (unsigned)pj_sockaddr_get_port(&cand->addr));
+
+ PRINT("%s\n",
+ pj_ice_get_cand_type_name(cand->type),
+ 0, 0, 0, 0, 0);
+
+ if (p == buffer+maxlen)
+ return -PJ_ETOOSMALL;
+
+ *p = '\0';
+
+ return p-buffer;
+}
+
+/*
+ * Encode ICE information in SDP.
+ */
+static int encode_session(char buffer[], unsigned maxlen)
+{
+ char *p = buffer;
+ unsigned comp;
+ int printed;
+ pj_str_t local_ufrag, local_pwd;
+ pj_status_t status;
+
+ /* Write "dummy" SDP v=, o=, s=, and t= lines */
+ PRINT("v=0\no=- 3414953978 3414953978 IN IP4 localhost\ns=ice\nt=0 0\n",
+ 0, 0, 0, 0, 0, 0);
+
+ /* Get ufrag and pwd from current session */
+ pj_ice_strans_get_ufrag_pwd(icedemo.icest, &local_ufrag, &local_pwd,
+ NULL, NULL);
+
+ /* Write the a=ice-ufrag and a=ice-pwd attributes */
+ PRINT("a=ice-ufrag:%.*s\na=ice-pwd:%.*s\n",
+ (int)local_ufrag.slen,
+ local_ufrag.ptr,
+ (int)local_pwd.slen,
+ local_pwd.ptr,
+ 0, 0);
+
+ /* Write each component */
+ for (comp=0; comp<icedemo.opt.comp_cnt; ++comp) {
+ unsigned j, cand_cnt;
+ pj_ice_sess_cand cand[PJ_ICE_ST_MAX_CAND];
+ char ipaddr[PJ_INET6_ADDRSTRLEN];
+
+ /* Get default candidate for the component */
+ status = pj_ice_strans_get_def_cand(icedemo.icest, comp+1, &cand[0]);
+ if (status != PJ_SUCCESS)
+ return -status;
+
+ /* Write the default address */
+ if (comp==0) {
+ /* For component 1, default address is in m= and c= lines */
+ PRINT("m=audio %d RTP/AVP 0\n"
+ "c=IN IP4 %s\n",
+ (int)pj_sockaddr_get_port(&cand[0].addr),
+ pj_sockaddr_print(&cand[0].addr, ipaddr,
+ sizeof(ipaddr), 0),
+ 0, 0, 0, 0);
+ } else if (comp==1) {
+ /* For component 2, default address is in a=rtcp line */
+ PRINT("a=rtcp:%d IN IP4 %s\n",
+ (int)pj_sockaddr_get_port(&cand[0].addr),
+ pj_sockaddr_print(&cand[0].addr, ipaddr,
+ sizeof(ipaddr), 0),
+ 0, 0, 0, 0);
+ } else {
+ /* For other components, we'll just invent this.. */
+ PRINT("a=Xice-defcand:%d IN IP4 %s\n",
+ (int)pj_sockaddr_get_port(&cand[0].addr),
+ pj_sockaddr_print(&cand[0].addr, ipaddr,
+ sizeof(ipaddr), 0),
+ 0, 0, 0, 0);
+ }
+
+ /* Enumerate all candidates for this component */
+ status = pj_ice_strans_enum_cands(icedemo.icest, comp+1,
+ &cand_cnt, cand);
+ if (status != PJ_SUCCESS)
+ return -status;
+
+ /* And encode the candidates as SDP */
+ for (j=0; j<cand_cnt; ++j) {
+ printed = print_cand(p, maxlen - (p-buffer), &cand[j]);
+ if (printed < 0)
+ return -PJ_ETOOSMALL;
+ p += printed;
+ }
+ }
+
+ if (p == buffer+maxlen)
+ return -PJ_ETOOSMALL;
+
+ *p = '\0';
+ return p - buffer;
+}
+
+
+/*
+ * Show information contained in the ICE stream transport. This is
+ * invoked from the menu.
+ */
+static void icedemo_show_ice(void)
+{
+ static char buffer[1000];
+ int len;
+
+ if (icedemo.icest == NULL) {
+ PJ_LOG(1,(THIS_FILE, "Error: No ICE instance, create it first"));
+ return;
+ }
+
+ puts("General info");
+ puts("---------------");
+ printf("Component count : %d\n", icedemo.opt.comp_cnt);
+ printf("Status : ");
+ if (pj_ice_strans_sess_is_complete(icedemo.icest))
+ puts("negotiation complete");
+ else if (pj_ice_strans_sess_is_running(icedemo.icest))
+ puts("negotiation is in progress");
+ else if (pj_ice_strans_has_sess(icedemo.icest))
+ puts("session ready");
+ else
+ puts("session not created");
+
+ if (!pj_ice_strans_has_sess(icedemo.icest)) {
+ puts("Create the session first to see more info");
+ return;
+ }
+
+ printf("Negotiated comp_cnt: %d\n",
+ pj_ice_strans_get_running_comp_cnt(icedemo.icest));
+ printf("Role : %s\n",
+ pj_ice_strans_get_role(icedemo.icest)==PJ_ICE_SESS_ROLE_CONTROLLED ?
+ "controlled" : "controlling");
+
+ len = encode_session(buffer, sizeof(buffer));
+ if (len < 0)
+ err_exit("not enough buffer to show ICE status", -len);
+
+ puts("");
+ printf("Local SDP (paste this to remote host):\n"
+ "--------------------------------------\n"
+ "%s\n", buffer);
+
+
+ puts("");
+ puts("Remote info:\n"
+ "----------------------");
+ if (icedemo.rem.cand_cnt==0) {
+ puts("No remote info yet");
+ } else {
+ unsigned i;
+
+ printf("Remote ufrag : %s\n", icedemo.rem.ufrag);
+ printf("Remote password : %s\n", icedemo.rem.pwd);
+ printf("Remote cand. cnt. : %d\n", icedemo.rem.cand_cnt);
+
+ for (i=0; i<icedemo.rem.cand_cnt; ++i) {
+ len = print_cand(buffer, sizeof(buffer), &icedemo.rem.cand[i]);
+ if (len < 0)
+ err_exit("not enough buffer to show ICE status", -len);
+
+ printf(" %s", buffer);
+ }
+ }
+}
+
+
+/*
+ * Input and parse SDP from the remote (containing remote's ICE information)
+ * and save it to global variables.
+ */
+static void icedemo_input_remote(void)
+{
+ char linebuf[80];
+ unsigned media_cnt = 0;
+ unsigned comp0_port = 0;
+ char comp0_addr[80];
+ pj_bool_t done = PJ_FALSE;
+
+ puts("Paste SDP from remote host, end with empty line");
+
+ reset_rem_info();
+
+ comp0_addr[0] = '\0';
+
+ while (!done) {
+ int len;
+ char *line;
+
+ printf(">");
+ if (stdout) fflush(stdout);
+
+ if (fgets(linebuf, sizeof(linebuf), stdin)==NULL)
+ break;
+
+ len = strlen(linebuf);
+ while (len && (linebuf[len-1] == '\r' || linebuf[len-1] == '\n'))
+ linebuf[--len] = '\0';
+
+ line = linebuf;
+ while (len && pj_isspace(*line))
+ ++line, --len;
+
+ if (len==0)
+ break;
+
+ /* Ignore subsequent media descriptors */
+ if (media_cnt > 1)
+ continue;
+
+ switch (line[0]) {
+ case 'm':
+ {
+ int cnt;
+ char media[32], portstr[32];
+
+ ++media_cnt;
+ if (media_cnt > 1) {
+ puts("Media line ignored");
+ break;
+ }
+
+ cnt = sscanf(line+2, "%s %s RTP/", media, portstr);
+ if (cnt != 2) {
+ PJ_LOG(1,(THIS_FILE, "Error parsing media line"));
+ goto on_error;
+ }
+
+ comp0_port = atoi(portstr);
+
+ }
+ break;
+ case 'c':
+ {
+ int cnt;
+ char c[32], net[32], ip[80];
+
+ cnt = sscanf(line+2, "%s %s %s", c, net, ip);
+ if (cnt != 3) {
+ PJ_LOG(1,(THIS_FILE, "Error parsing connection line"));
+ goto on_error;
+ }
+
+ strcpy(comp0_addr, ip);
+ }
+ break;
+ case 'a':
+ {
+ char *attr = strtok(line+2, ": \t\r\n");
+ if (strcmp(attr, "ice-ufrag")==0) {
+ strcpy(icedemo.rem.ufrag, attr+strlen(attr)+1);
+ } else if (strcmp(attr, "ice-pwd")==0) {
+ strcpy(icedemo.rem.pwd, attr+strlen(attr)+1);
+ } else if (strcmp(attr, "rtcp")==0) {
+ char *val = attr+strlen(attr)+1;
+ int af, cnt;
+ int port;
+ char net[32], ip[64];
+ pj_str_t tmp_addr;
+ pj_status_t status;
+
+ cnt = sscanf(val, "%d IN %s %s", &port, net, ip);
+ if (cnt != 3) {
+ PJ_LOG(1,(THIS_FILE, "Error parsing rtcp attribute"));
+ goto on_error;
+ }
+
+ if (strchr(ip, ':'))
+ af = pj_AF_INET6();
+ else
+ af = pj_AF_INET();
+
+ pj_sockaddr_init(af, &icedemo.rem.def_addr[1], NULL, 0);
+ tmp_addr = pj_str(ip);
+ status = pj_sockaddr_set_str_addr(af, &icedemo.rem.def_addr[1],
+ &tmp_addr);
+ if (status != PJ_SUCCESS) {
+ PJ_LOG(1,(THIS_FILE, "Invalid IP address"));
+ goto on_error;
+ }
+ pj_sockaddr_set_port(&icedemo.rem.def_addr[1], (pj_uint16_t)port);
+
+ } else if (strcmp(attr, "candidate")==0) {
+ char *sdpcand = attr+strlen(attr)+1;
+ int af, cnt;
+ char foundation[32], transport[12], ipaddr[80], type[32];
+ pj_str_t tmpaddr;
+ int comp_id, prio, port;
+ pj_ice_sess_cand *cand;
+ pj_status_t status;
+
+ cnt = sscanf(sdpcand, "%s %d %s %d %s %d typ %s",
+ foundation,
+ &comp_id,
+ transport,
+ &prio,
+ ipaddr,
+ &port,
+ type);
+ if (cnt != 7) {
+ PJ_LOG(1, (THIS_FILE, "error: Invalid ICE candidate line"));
+ goto on_error;
+ }
+
+ cand = &icedemo.rem.cand[icedemo.rem.cand_cnt];
+ pj_bzero(cand, sizeof(*cand));
+
+ if (strcmp(type, "host")==0)
+ cand->type = PJ_ICE_CAND_TYPE_HOST;
+ else if (strcmp(type, "srflx")==0)
+ cand->type = PJ_ICE_CAND_TYPE_SRFLX;
+ else if (strcmp(type, "relay")==0)
+ cand->type = PJ_ICE_CAND_TYPE_RELAYED;
+ else {
+ PJ_LOG(1, (THIS_FILE, "Error: invalid candidate type '%s'",
+ type));
+ goto on_error;
+ }
+
+ cand->comp_id = (pj_uint8_t)comp_id;
+ pj_strdup2(icedemo.pool, &cand->foundation, foundation);
+ cand->prio = prio;
+
+ if (strchr(ipaddr, ':'))
+ af = pj_AF_INET6();
+ else
+ af = pj_AF_INET();
+
+ tmpaddr = pj_str(ipaddr);
+ pj_sockaddr_init(af, &cand->addr, NULL, 0);
+ status = pj_sockaddr_set_str_addr(af, &cand->addr, &tmpaddr);
+ if (status != PJ_SUCCESS) {
+ PJ_LOG(1,(THIS_FILE, "Error: invalid IP address '%s'",
+ ipaddr));
+ goto on_error;
+ }
+
+ pj_sockaddr_set_port(&cand->addr, (pj_uint16_t)port);
+
+ ++icedemo.rem.cand_cnt;
+
+ if (cand->comp_id > icedemo.rem.comp_cnt)
+ icedemo.rem.comp_cnt = cand->comp_id;
+ }
+ }
+ break;
+ }
+ }
+
+ if (icedemo.rem.cand_cnt==0 ||
+ icedemo.rem.ufrag[0]==0 ||
+ icedemo.rem.pwd[0]==0 ||
+ icedemo.rem.comp_cnt == 0)
+ {
+ PJ_LOG(1, (THIS_FILE, "Error: not enough info"));
+ goto on_error;
+ }
+
+ if (comp0_port==0 || comp0_addr[0]=='\0') {
+ PJ_LOG(1, (THIS_FILE, "Error: default address for component 0 not found"));
+ goto on_error;
+ } else {
+ int af;
+ pj_str_t tmp_addr;
+ pj_status_t status;
+
+ if (strchr(comp0_addr, ':'))
+ af = pj_AF_INET6();
+ else
+ af = pj_AF_INET();
+
+ pj_sockaddr_init(af, &icedemo.rem.def_addr[0], NULL, 0);
+ tmp_addr = pj_str(comp0_addr);
+ status = pj_sockaddr_set_str_addr(af, &icedemo.rem.def_addr[0],
+ &tmp_addr);
+ if (status != PJ_SUCCESS) {
+ PJ_LOG(1,(THIS_FILE, "Invalid IP address in c= line"));
+ goto on_error;
+ }
+ pj_sockaddr_set_port(&icedemo.rem.def_addr[0], (pj_uint16_t)comp0_port);
+ }
+
+ PJ_LOG(3, (THIS_FILE, "Done, %d remote candidate(s) added",
+ icedemo.rem.cand_cnt));
+ return;
+
+on_error:
+ reset_rem_info();
+}
+
+
+/*
+ * Start ICE negotiation! This function is invoked from the menu.
+ */
+static void icedemo_start_nego(void)
+{
+ pj_str_t rufrag, rpwd;
+ pj_status_t status;
+
+ if (icedemo.icest == NULL) {
+ PJ_LOG(1,(THIS_FILE, "Error: No ICE instance, create it first"));
+ return;
+ }
+
+ if (!pj_ice_strans_has_sess(icedemo.icest)) {
+ PJ_LOG(1,(THIS_FILE, "Error: No ICE session, initialize first"));
+ return;
+ }
+
+ if (icedemo.rem.cand_cnt == 0) {
+ PJ_LOG(1,(THIS_FILE, "Error: No remote info, input remote info first"));
+ return;
+ }
+
+ PJ_LOG(3,(THIS_FILE, "Starting ICE negotiation.."));
+
+ status = pj_ice_strans_start_ice(icedemo.icest,
+ pj_cstr(&rufrag, icedemo.rem.ufrag),
+ pj_cstr(&rpwd, icedemo.rem.pwd),
+ icedemo.rem.cand_cnt,
+ icedemo.rem.cand);
+ if (status != PJ_SUCCESS)
+ icedemo_perror("Error starting ICE", status);
+ else
+ PJ_LOG(3,(THIS_FILE, "ICE negotiation started"));
+}
+
+
+/*
+ * Send application data to remote agent.
+ */
+static void icedemo_send_data(unsigned comp_id, const char *data)
+{
+ pj_status_t status;
+
+ if (icedemo.icest == NULL) {
+ PJ_LOG(1,(THIS_FILE, "Error: No ICE instance, create it first"));
+ return;
+ }
+
+ if (!pj_ice_strans_has_sess(icedemo.icest)) {
+ PJ_LOG(1,(THIS_FILE, "Error: No ICE session, initialize first"));
+ return;
+ }
+
+ /*
+ if (!pj_ice_strans_sess_is_complete(icedemo.icest)) {
+ PJ_LOG(1,(THIS_FILE, "Error: ICE negotiation has not been started or is in progress"));
+ return;
+ }
+ */
+
+ if (comp_id<1||comp_id>pj_ice_strans_get_running_comp_cnt(icedemo.icest)) {
+ PJ_LOG(1,(THIS_FILE, "Error: invalid component ID"));
+ return;
+ }
+
+ status = pj_ice_strans_sendto(icedemo.icest, comp_id, data, strlen(data),
+ &icedemo.rem.def_addr[comp_id-1],
+ pj_sockaddr_get_len(&icedemo.rem.def_addr[comp_id-1]));
+ if (status != PJ_SUCCESS)
+ icedemo_perror("Error sending data", status);
+ else
+ PJ_LOG(3,(THIS_FILE, "Data sent"));
+}
+
+
+/*
+ * Display help for the menu.
+ */
+static void icedemo_help_menu(void)
+{
+ puts("");
+ puts("-= Help on using ICE and this icedemo program =-");
+ puts("");
+ puts("This application demonstrates how to use ICE in pjnath without having\n"
+ "to use the SIP protocol. To use this application, you will need to run\n"
+ "two instances of this application, to simulate two ICE agents.\n");
+
+ puts("Basic ICE flow:\n"
+ " create instance [menu \"c\"]\n"
+ " repeat these steps as wanted:\n"
+ " - init session as offerer or answerer [menu \"i\"]\n"
+ " - display our SDP [menu \"s\"]\n"
+ " - \"send\" our SDP from the \"show\" output above to remote, by\n"
+ " copy-pasting the SDP to the other icedemo application\n"
+ " - parse remote SDP, by pasting SDP generated by the other icedemo\n"
+ " instance [menu \"r\"]\n"
+ " - begin ICE negotiation in our end [menu \"b\"], and \n"
+ " - immediately begin ICE negotiation in the other icedemo instance\n"
+ " - ICE negotiation will run, and result will be printed to screen\n"
+ " - send application data to remote [menu \"x\"]\n"
+ " - end/stop ICE session [menu \"e\"]\n"
+ " destroy instance [menu \"d\"]\n"
+ "");
+
+ puts("");
+ puts("This concludes the help screen.");
+ puts("");
+}
+
+
+/*
+ * Display console menu
+ */
+static void icedemo_print_menu(void)
+{
+ puts("");
+ puts("+----------------------------------------------------------------------+");
+ puts("| M E N U |");
+ puts("+---+------------------------------------------------------------------+");
+ puts("| c | create Create the instance |");
+ puts("| d | destroy Destroy the instance |");
+ puts("| i | init o|a Initialize ICE session as offerer or answerer |");
+ puts("| e | stop End/stop ICE session |");
+ puts("| s | show Display local ICE info |");
+ puts("| r | remote Input remote ICE info |");
+ puts("| b | start Begin ICE negotiation |");
+ puts("| x | send <compid> .. Send data to remote |");
+ puts("+---+------------------------------------------------------------------+");
+ puts("| h | help * Help! * |");
+ puts("| q | quit Quit |");
+ puts("+----------------------------------------------------------------------+");
+}
+
+
+/*
+ * Main console loop.
+ */
+static void icedemo_console(void)
+{
+ pj_bool_t app_quit = PJ_FALSE;
+
+ while (!app_quit) {
+ char input[80], *cmd;
+ const char *SEP = " \t\r\n";
+ int len;
+
+ icedemo_print_menu();
+
+ printf("Input: ");
+ if (stdout) fflush(stdout);
+
+ pj_bzero(input, sizeof(input));
+ if (fgets(input, sizeof(input), stdin) == NULL)
+ break;
+
+ len = strlen(input);
+ while (len && (input[len-1]=='\r' || input[len-1]=='\n'))
+ input[--len] = '\0';
+
+ cmd = strtok(input, SEP);
+ if (!cmd)
+ continue;
+
+ if (strcmp(cmd, "create")==0 || strcmp(cmd, "c")==0) {
+
+ icedemo_create_instance();
+
+ } else if (strcmp(cmd, "destroy")==0 || strcmp(cmd, "d")==0) {
+
+ icedemo_destroy_instance();
+
+ } else if (strcmp(cmd, "init")==0 || strcmp(cmd, "i")==0) {
+
+ char *role = strtok(NULL, SEP);
+ if (role)
+ icedemo_init_session(*role);
+ else
+ puts("error: Role required");
+
+ } else if (strcmp(cmd, "stop")==0 || strcmp(cmd, "e")==0) {
+
+ icedemo_stop_session();
+
+ } else if (strcmp(cmd, "show")==0 || strcmp(cmd, "s")==0) {
+
+ icedemo_show_ice();
+
+ } else if (strcmp(cmd, "remote")==0 || strcmp(cmd, "r")==0) {
+
+ icedemo_input_remote();
+
+ } else if (strcmp(cmd, "start")==0 || strcmp(cmd, "b")==0) {
+
+ icedemo_start_nego();
+
+ } else if (strcmp(cmd, "send")==0 || strcmp(cmd, "x")==0) {
+
+ char *comp = strtok(NULL, SEP);
+
+ if (!comp) {
+ PJ_LOG(1,(THIS_FILE, "Error: component ID required"));
+ } else {
+ char *data = comp + strlen(comp) + 1;
+ if (!data)
+ data = "";
+ icedemo_send_data(atoi(comp), data);
+ }
+
+ } else if (strcmp(cmd, "help")==0 || strcmp(cmd, "h")==0) {
+
+ icedemo_help_menu();
+
+ } else if (strcmp(cmd, "quit")==0 || strcmp(cmd, "q")==0) {
+
+ app_quit = PJ_TRUE;
+
+ } else {
+
+ printf("Invalid command '%s'\n", cmd);
+
+ }
+ }
+}
+
+
+/*
+ * Display program usage.
+ */
+static void icedemo_usage()
+{
+ puts("Usage: icedemo [optons]");
+ printf("icedemo v%s by pjsip.org\n", pj_get_version());
+ puts("");
+ puts("General options:");
+ puts(" --comp-cnt, -c N Component count (default=1)");
+ puts(" --nameserver, -n IP Configure nameserver to activate DNS SRV");
+ puts(" resolution");
+ puts(" --max-host, -H N Set max number of host candidates to N");
+ puts(" --regular, -R Use regular nomination (default aggressive)");
+ puts(" --log-file, -L FILE Save output to log FILE");
+ puts(" --help, -h Display this screen.");
+ puts("");
+ puts("STUN related options:");
+ puts(" --stun-srv, -s HOSTDOM Enable srflx candidate by resolving to STUN server.");
+ puts(" HOSTDOM may be a \"host_or_ip[:port]\" or a domain");
+ puts(" name if DNS SRV resolution is used.");
+ puts("");
+ puts("TURN related options:");
+ puts(" --turn-srv, -t HOSTDOM Enable relayed candidate by using this TURN server.");
+ puts(" HOSTDOM may be a \"host_or_ip[:port]\" or a domain");
+ puts(" name if DNS SRV resolution is used.");
+ puts(" --turn-tcp, -T Use TCP to connect to TURN server");
+ puts(" --turn-username, -u UID Set TURN username of the credential to UID");
+ puts(" --turn-password, -p PWD Set password of the credential to WPWD");
+ puts(" --turn-fingerprint, -F Use fingerprint for outgoing TURN requests");
+ puts("");
+}
+
+
+/*
+ * And here's the main()
+ */
+int main(int argc, char *argv[])
+{
+ struct pj_getopt_option long_options[] = {
+ { "comp-cnt", 1, 0, 'c'},
+ { "nameserver", 1, 0, 'n'},
+ { "max-host", 1, 0, 'H'},
+ { "help", 0, 0, 'h'},
+ { "stun-srv", 1, 0, 's'},
+ { "turn-srv", 1, 0, 't'},
+ { "turn-tcp", 0, 0, 'T'},
+ { "turn-username", 1, 0, 'u'},
+ { "turn-password", 1, 0, 'p'},
+ { "turn-fingerprint", 0, 0, 'F'},
+ { "regular", 0, 0, 'R'},
+ { "log-file", 1, 0, 'L'},
+ };
+ int c, opt_id;
+ pj_status_t status;
+
+ icedemo.opt.comp_cnt = 1;
+ icedemo.opt.max_host = -1;
+
+ while((c=pj_getopt_long(argc,argv, "c:n:s:t:u:p:H:L:hTFR", long_options, &opt_id))!=-1) {
+ switch (c) {
+ case 'c':
+ icedemo.opt.comp_cnt = atoi(pj_optarg);
+ if (icedemo.opt.comp_cnt < 1 || icedemo.opt.comp_cnt >= PJ_ICE_MAX_COMP) {
+ puts("Invalid component count value");
+ return 1;
+ }
+ break;
+ case 'n':
+ icedemo.opt.ns = pj_str(pj_optarg);
+ break;
+ case 'H':
+ icedemo.opt.max_host = atoi(pj_optarg);
+ break;
+ case 'h':
+ icedemo_usage();
+ return 0;
+ case 's':
+ icedemo.opt.stun_srv = pj_str(pj_optarg);
+ break;
+ case 't':
+ icedemo.opt.turn_srv = pj_str(pj_optarg);
+ break;
+ case 'T':
+ icedemo.opt.turn_tcp = PJ_TRUE;
+ break;
+ case 'u':
+ icedemo.opt.turn_username = pj_str(pj_optarg);
+ break;
+ case 'p':
+ icedemo.opt.turn_password = pj_str(pj_optarg);
+ break;
+ case 'F':
+ icedemo.opt.turn_fingerprint = PJ_TRUE;
+ break;
+ case 'R':
+ icedemo.opt.regular = PJ_TRUE;
+ break;
+ case 'L':
+ icedemo.opt.log_file = pj_optarg;
+ break;
+ default:
+ printf("Argument \"%s\" is not valid. Use -h to see help",
+ argv[pj_optind]);
+ return 1;
+ }
+ }
+
+ status = icedemo_init();
+ if (status != PJ_SUCCESS)
+ return 1;
+
+ icedemo_console();
+
+ err_exit("Quitting..", PJ_SUCCESS);
+ return 0;
+}
diff --git a/pjsip-apps/src/samples/invtester.c b/pjsip-apps/src/samples/invtester.c
new file mode 100644
index 0000000..a1eb413
--- /dev/null
+++ b/pjsip-apps/src/samples/invtester.c
@@ -0,0 +1,295 @@
+/* $Id: invtester.c 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/**
+ * invtester.c
+ *
+ * Send INVITE/re-INVITE without SDP.
+ */
+
+
+/* Include all headers. */
+#include <pjsip.h>
+#include <pjlib-util.h>
+#include <pjlib.h>
+
+#define THIS_FILE "invtester.c"
+
+#define PORT 50060
+#define PORT_STR ":50060"
+#define SAME_BRANCH 0
+#define ACK_HAS_SDP 1
+
+static pjsip_endpoint *sip_endpt;
+static pj_bool_t quit_flag;
+static pjsip_dialog *dlg;
+
+
+/* Callback to handle incoming requests. */
+static void on_tsx_state(pjsip_transaction *tsx, pjsip_event *event);
+
+static pjsip_module mod_app =
+{
+ NULL, NULL, /* prev, next. */
+ { "mod-app", 7 }, /* Name. */
+ -1, /* Id */
+ PJSIP_MOD_PRIORITY_APPLICATION, /* Priority */
+ NULL, /* load() */
+ NULL, /* start() */
+ NULL, /* stop() */
+ NULL, /* unload() */
+ NULL, /* on_rx_request() */
+ NULL, /* on_rx_response() */
+ NULL, /* on_tx_request. */
+ NULL, /* on_tx_response() */
+ &on_tsx_state /* on_tsx_state() */
+};
+
+
+/* Worker thread */
+static int worker_thread(void *arg)
+{
+ PJ_UNUSED_ARG(arg);
+
+ while (!quit_flag) {
+ pj_time_val timeout = {0, 500};
+ pjsip_endpt_handle_events(sip_endpt, &timeout);
+ }
+
+ return 0;
+}
+
+/* Send request */
+static void send_request(const pjsip_method *method,
+ int cseq,
+ const pj_str_t *branch,
+ pj_bool_t with_offer)
+{
+ pjsip_tx_data *tdata;
+ pj_str_t dummy_sdp_str =
+ {
+ "v=0\r\n"
+ "o=- 3360842071 3360842071 IN IP4 192.168.0.68\r\n"
+ "s=pjmedia\r\n"
+ "c=IN IP4 192.168.0.68\r\n"
+ "t=0 0\r\n"
+ "m=audio 4000 RTP/AVP 0 101\r\n"
+ "a=rtcp:4001 IN IP4 192.168.0.68\r\n"
+ "a=rtpmap:0 PCMU/8000\r\n"
+ "a=sendrecv\r\n"
+ "a=rtpmap:101 telephone-event/8000\r\n"
+ "a=fmtp:101 0-15\r\n",
+ 0
+ };
+ pj_status_t status;
+
+ status = pjsip_dlg_create_request(dlg, method, cseq, &tdata);
+ pj_assert(status == PJ_SUCCESS);
+
+ if (branch) {
+ pjsip_via_hdr *via;
+
+ via = (pjsip_via_hdr*) pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL);
+ pj_strdup(tdata->pool, &via->branch_param, branch);
+ }
+
+ if (with_offer) {
+ pjsip_msg_body *body;
+ pj_str_t mime_application = { "application", 11};
+ pj_str_t mime_sdp = {"sdp", 3};
+
+
+ dummy_sdp_str.slen = pj_ansi_strlen(dummy_sdp_str.ptr);
+ body = pjsip_msg_body_create(tdata->pool,
+ &mime_application, &mime_sdp,
+ &dummy_sdp_str);
+ tdata->msg->body = body;
+ }
+
+ status = pjsip_dlg_send_request(dlg, tdata, -1, NULL);
+ pj_assert(status == PJ_SUCCESS);
+}
+
+/* Callback to handle incoming requests. */
+static void on_tsx_state(pjsip_transaction *tsx, pjsip_event *event)
+{
+ if (tsx->role == PJSIP_ROLE_UAC) {
+ if (tsx->method.id == PJSIP_INVITE_METHOD && tsx->state == PJSIP_TSX_STATE_TERMINATED) {
+#if SAME_BRANCH
+ send_request(&pjsip_ack_method, tsx->cseq, &tsx->branch, ACK_HAS_SDP);
+#else
+ send_request(&pjsip_ack_method, tsx->cseq, NULL, ACK_HAS_SDP);
+#endif
+ }
+
+ } else {
+ if (event->type == PJSIP_EVENT_RX_MSG && tsx->state == PJSIP_TSX_STATE_TRYING) {
+ pjsip_tx_data *tdata;
+
+ pjsip_dlg_create_response(dlg, event->body.tsx_state.src.rdata,
+ 200, NULL, &tdata);
+ pjsip_dlg_send_response(dlg, tsx, tdata);
+ }
+ }
+}
+
+/* make call */
+void make_call(char *uri, pj_bool_t with_offer)
+{
+ pj_str_t local = pj_str("sip:localhost" PORT_STR);
+ pj_str_t remote = pj_str(uri);
+ pj_status_t status;
+
+ status = pjsip_dlg_create_uac(pjsip_ua_instance(),
+ &local, &local, &remote, &remote, &dlg);
+ pj_assert(status == PJ_SUCCESS);
+
+ pjsip_dlg_inc_lock(dlg);
+
+ status = pjsip_dlg_add_usage(dlg, &mod_app, NULL);
+ pj_assert(status == PJ_SUCCESS);
+
+ pjsip_dlg_inc_session(dlg, &mod_app);
+
+ send_request(&pjsip_invite_method, -1, NULL, with_offer);
+
+ pjsip_dlg_dec_lock(dlg);
+}
+
+/* reinvite */
+void reinvite(pj_bool_t with_offer)
+{
+ send_request(&pjsip_invite_method, -1, NULL, with_offer);
+}
+
+/* hangup call */
+void hangup(void)
+{
+ send_request(&pjsip_bye_method, -1, NULL, PJ_FALSE);
+ pjsip_dlg_dec_session(dlg, &mod_app);
+}
+
+/*
+ * main()
+ *
+ */
+int main(int argc, char *argv[])
+{
+ pj_caching_pool cp;
+ pj_thread_t *thread;
+ pj_pool_t *pool;
+ pj_status_t status;
+
+ if (argc != 2) {
+ puts("Error: destination URL needed");
+ return 0;
+ }
+
+ /* Must init PJLIB first: */
+ status = pj_init();
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+
+ /* Then init PJLIB-UTIL: */
+ status = pjlib_util_init();
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ /* Must create a pool factory before we can allocate any memory. */
+ pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);
+
+
+ /* Create the endpoint: */
+ status = pjsip_endpt_create(&cp.factory, "sipstateless",
+ &sip_endpt);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ /*
+ * Add UDP transport, with hard-coded port
+ */
+ {
+ pj_sockaddr_in addr;
+
+ addr.sin_family = pj_AF_INET();
+ addr.sin_addr.s_addr = 0;
+ addr.sin_port = pj_htons(PORT);
+
+ status = pjsip_udp_transport_start( sip_endpt, &addr, NULL, 1, NULL);
+ if (status != PJ_SUCCESS) {
+ PJ_LOG(3,(THIS_FILE,
+ "Error starting UDP transport (port in use?)"));
+ return 1;
+ }
+ }
+
+ status = pjsip_tsx_layer_init_module(sip_endpt);
+ pj_assert(status == PJ_SUCCESS);
+
+ status = pjsip_ua_init_module(sip_endpt, NULL);
+ pj_assert(status == PJ_SUCCESS);
+
+ /*
+ * Register our module to receive incoming requests.
+ */
+ status = pjsip_endpt_register_module( sip_endpt, &mod_app);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ pool = pjsip_endpt_create_pool(sip_endpt, "", 1000, 1000);
+
+ status = pj_thread_create(pool, "", &worker_thread, NULL, 0, 0, &thread);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ printf("Destination URL: %s\n", argv[1]);
+
+ for (;;) {
+ char line[10];
+
+ fgets(line, sizeof(line), stdin);
+
+ switch (line[0]) {
+ case 'm':
+ make_call(argv[1], PJ_FALSE);
+ break;
+ case 'M':
+ make_call(argv[1], PJ_TRUE);
+ break;
+ case 'r':
+ reinvite(PJ_FALSE);
+ break;
+ case 'R':
+ reinvite(PJ_TRUE);
+ break;
+ case 'h':
+ hangup();
+ break;
+ case 'q':
+ goto on_quit;
+ }
+ }
+
+on_quit:
+ quit_flag = 1;
+ pj_thread_join(thread);
+
+ pjsip_endpt_destroy(sip_endpt);
+ pj_caching_pool_destroy(&cp);
+ pj_shutdown();
+ return 0;
+}
+
diff --git a/pjsip-apps/src/samples/jbsim.c b/pjsip-apps/src/samples/jbsim.c
new file mode 100644
index 0000000..510f67c
--- /dev/null
+++ b/pjsip-apps/src/samples/jbsim.c
@@ -0,0 +1,1141 @@
+/* $Id: jbsim.c 3664 2011-07-19 03:42:28Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* jbsim:
+
+ This program emulates various system and network impairment
+ conditions as well as application parameters and apply it to
+ an input WAV file. The output is another WAV file as well as
+ a detailed log file (in CSV format) for troubleshooting.
+ */
+
+
+/* Include PJMEDIA and PJLIB */
+#include <pjmedia.h>
+#include <pjmedia-codec.h>
+#include <pjlib.h>
+#include <pjlib-util.h>
+
+#define THIS_FILE "jbsim.c"
+
+/* Timer resolution in ms (must be NONZERO!) */
+#define WALL_CLOCK_TICK 1
+
+/* Defaults settings */
+#define CODEC "PCMU"
+#define LOG_FILE "jbsim.csv"
+#define WAV_REF "../../tests/pjsua/wavs/input.8.wav"
+#define WAV_OUT "jbsim.wav"
+#define DURATION 60
+#define DTX PJ_TRUE
+#define PLC PJ_TRUE
+#define MIN_LOST_BURST 0
+#define MAX_LOST_BURST 20
+#define LOSS_CORR 0
+#define LOSS_EXTRA 2
+#define SILENT 1
+
+/*
+ Test setup:
+
+ Input WAV --> TX Stream --> Loop transport --> RX Stream --> Out WAV
+ */
+
+/* Stream settings */
+struct stream_cfg
+{
+ const char *name; /* for logging purposes */
+ pjmedia_dir dir; /* stream direction */
+ pj_str_t codec; /* codec name */
+ unsigned ptime; /* zero for default */
+ pj_bool_t dtx; /* DTX enabled? */
+ pj_bool_t plc; /* PLC enabled? */
+};
+
+/* Stream instance. We will instantiate two streams, TX and RX */
+struct stream
+{
+ pj_pool_t *pool;
+ pjmedia_stream *strm;
+ pjmedia_port *port;
+
+ /*
+ * Running states:
+ */
+ union {
+ /* TX stream state */
+ struct {
+ pj_time_val next_schedule; /* Time to send next packet */
+ unsigned total_tx; /* # of TX packets so far */
+ int total_lost; /* # of dropped pkts so far */
+ unsigned cur_lost_burst; /* current # of lost bursts */
+ unsigned drop_prob; /* drop probability value */
+
+ } tx;
+
+ /* RX stream state */
+ struct {
+ pj_time_val next_schedule; /* Time to fetch next pkt */
+ } rx;
+ } state;
+};
+
+/*
+ * Logging
+ */
+
+/* Events names */
+#define EVENT_LOG ""
+#define EVENT_TX "TX/PUT"
+#define EVENT_TX_DROP "*** LOSS ***"
+#define EVENT_GET_PRE "GET (pre)"
+#define EVENT_GET_POST "GET (post)"
+
+
+/* Logging entry */
+struct log_entry
+{
+ pj_time_val wall_clock; /* Wall clock time */
+ const char *event; /* Event name */
+ pjmedia_jb_state *jb_state; /* JB state, optional */
+ pjmedia_rtcp_stat *stat; /* Stream stat, optional */
+ const char *log; /* Log message, optional */
+};
+
+/* Test settings, taken from command line */
+struct test_cfg
+{
+ /* General options */
+ pj_bool_t silent; /* Write little to stdout */
+ const char *log_file; /* The output log file */
+
+ /* Test settings */
+ pj_str_t codec; /* Codec to be used */
+ unsigned duration_msec; /* Test duration */
+
+ /* Transmitter setting */
+ const char *tx_wav_in; /* Input/reference WAV */
+ unsigned tx_ptime; /* TX stream ptime */
+ unsigned tx_min_jitter; /* Minimum jitter in ms */
+ unsigned tx_max_jitter; /* Max jitter in ms */
+ unsigned tx_dtx; /* DTX enabled? */
+ unsigned tx_pct_avg_lost; /* Average loss in percent */
+ unsigned tx_min_lost_burst; /* Min lost burst in #pkt */
+ unsigned tx_max_lost_burst; /* Max lost burst in #pkt */
+ unsigned tx_pct_loss_corr; /* Loss correlation in pct */
+
+ /* Receiver setting */
+ const char *rx_wav_out; /* Output WAV file */
+ unsigned rx_ptime; /* RX stream ptime */
+ unsigned rx_snd_burst; /* RX sound burst */
+ pj_bool_t rx_plc; /* RX PLC enabled? */
+ int rx_jb_init; /* if > 0 will enable prefetch (ms) */
+ int rx_jb_min_pre; /* JB minimum prefetch (ms) */
+ int rx_jb_max_pre; /* JB maximum prefetch (ms) */
+ int rx_jb_max; /* JB maximum size (ms) */
+};
+
+/*
+ * Global var
+ */
+struct global_app
+{
+ pj_caching_pool cp;
+ pj_pool_t *pool;
+ pj_int16_t *framebuf;
+ pjmedia_endpt *endpt;
+ pjmedia_transport *loop;
+
+ pj_oshandle_t log_fd;
+
+ struct test_cfg cfg;
+
+ struct stream *tx;
+ pjmedia_port *tx_wav;
+
+ struct stream *rx;
+ pjmedia_port *rx_wav;
+
+ pj_time_val wall_clock;
+};
+
+static struct global_app g_app;
+
+
+#ifndef MAX
+# define MAX(a,b) (a<b ? b : a)
+#endif
+
+#ifndef MIN
+# define MIN(a,b) (a<b ? a : b)
+#endif
+
+/*****************************************************************************
+ * Logging
+ */
+static void write_log(struct log_entry *entry, pj_bool_t to_stdout)
+{
+ /* Format (CSV): */
+ const char *format = "TIME;EVENT;#RX packets;#packets lost;#JB prefetch;#JB size;#JBDISCARD;#JBEMPTY;Log Message";
+ static char log[2000];
+ enum { D = 20 };
+ char s_jbprefetch[D],
+ s_jbsize[D],
+ s_rxpkt[D],
+ s_losspkt[D],
+ s_jbdiscard[D],
+ s_jbempty[D];
+ static pj_bool_t header_written;
+
+ if (!header_written) {
+ pj_ansi_snprintf(log, sizeof(log),
+ "%s\n", format);
+ if (g_app.log_fd != NULL) {
+ pj_ssize_t size = strlen(log);
+ pj_file_write(g_app.log_fd, log, &size);
+ }
+ if (to_stdout && !g_app.cfg.silent)
+ printf("%s", log);
+ header_written = PJ_TRUE;
+ }
+
+ if (entry->jb_state) {
+ sprintf(s_jbprefetch, "%d", entry->jb_state->prefetch);
+ sprintf(s_jbsize, "%d", entry->jb_state->size);
+ sprintf(s_jbdiscard, "%d", entry->jb_state->discard);
+ sprintf(s_jbempty, "%d", entry->jb_state->empty);
+ } else {
+ strcpy(s_jbprefetch, "");
+ strcpy(s_jbsize, "");
+ strcpy(s_jbdiscard, "");
+ strcpy(s_jbempty, "");
+ }
+
+ if (entry->stat) {
+ sprintf(s_rxpkt, "%d", entry->stat->rx.pkt);
+ sprintf(s_losspkt, "%d", entry->stat->rx.loss);
+ } else {
+ strcpy(s_rxpkt, "");
+ strcpy(s_losspkt, "");
+ }
+
+ if (entry->log == NULL)
+ entry->log = "";
+
+ pj_ansi_snprintf(log, sizeof(log),
+ "'%d.%03d;" /* time */
+ "%s;" /* event */
+ "%s;" /* rxpkt */
+ "%s;" /* jb prefetch */
+ "%s;" /* jbsize */
+ "%s;" /* losspkt */
+ "%s;" /* jbdiscard */
+ "%s;" /* jbempty */
+ "%s\n" /* logmsg */,
+
+ (int)entry->wall_clock.sec, (int)entry->wall_clock.msec, /* time */
+ entry->event,
+ s_rxpkt,
+ s_losspkt,
+ s_jbprefetch,
+ s_jbsize,
+ s_jbdiscard,
+ s_jbempty,
+ entry->log
+ );
+ if (g_app.log_fd != NULL) {
+ pj_ssize_t size = strlen(log);
+ pj_file_write(g_app.log_fd, log, &size);
+ }
+
+ if (to_stdout && !g_app.cfg.silent)
+ printf("%s", log);
+}
+
+static void log_cb(int level, const char *data, int len)
+{
+ struct log_entry entry;
+
+ /* Write to stdout */
+ pj_log_write(level, data, len);
+ puts("");
+
+ /* Also add to CSV file */
+ pj_bzero(&entry, sizeof(entry));
+ entry.event = EVENT_LOG;
+ entry.log = data;
+ entry.wall_clock = g_app.wall_clock;
+ write_log(&entry, PJ_FALSE);
+}
+
+static void jbsim_perror(const char *title, pj_status_t status)
+{
+ char errmsg[PJ_ERR_MSG_SIZE];
+
+ pj_strerror(status, errmsg, sizeof(errmsg));
+ PJ_LOG(1,(THIS_FILE, "%s: %s", title, errmsg));
+}
+
+/*****************************************************************************
+ * stream
+ */
+
+static void stream_destroy(struct stream *stream)
+{
+ if (stream->strm)
+ pjmedia_stream_destroy(stream->strm);
+ if (stream->pool)
+ pj_pool_release(stream->pool);
+}
+
+static pj_status_t stream_init(const struct stream_cfg *cfg, struct stream **p_stream)
+{
+ pj_pool_t *pool = NULL;
+ struct stream *stream = NULL;
+ pjmedia_codec_mgr *cm;
+ unsigned count;
+ const pjmedia_codec_info *ci;
+ pjmedia_stream_info si;
+ pj_status_t status;
+
+ /* Create instance */
+ pool = pj_pool_create(&g_app.cp.factory, cfg->name, 512, 512, NULL);
+ stream = PJ_POOL_ZALLOC_T(pool, struct stream);
+ stream->pool = pool;
+
+ /* Create stream info */
+ pj_bzero(&si, sizeof(si));
+ si.type = PJMEDIA_TYPE_AUDIO;
+ si.proto = PJMEDIA_TP_PROTO_RTP_AVP;
+ si.dir = cfg->dir;
+ pj_sockaddr_in_init(&si.rem_addr.ipv4, NULL, 4000); /* dummy */
+ pj_sockaddr_in_init(&si.rem_rtcp.ipv4, NULL, 4001); /* dummy */
+
+ /* Apply JB settings if this is RX direction */
+ if (cfg->dir == PJMEDIA_DIR_DECODING) {
+ si.jb_init = g_app.cfg.rx_jb_init;
+ si.jb_min_pre = g_app.cfg.rx_jb_min_pre;
+ si.jb_max_pre = g_app.cfg.rx_jb_max_pre;
+ si.jb_max = g_app.cfg.rx_jb_max;
+ }
+
+ /* Get the codec info and param */
+ cm = pjmedia_endpt_get_codec_mgr(g_app.endpt);
+ count = 1;
+ status = pjmedia_codec_mgr_find_codecs_by_id(cm, &cfg->codec, &count, &ci, NULL);
+ if (status != PJ_SUCCESS) {
+ jbsim_perror("Unable to find codec", status);
+ goto on_error;
+ }
+
+ pj_memcpy(&si.fmt, ci, sizeof(*ci));
+
+ si.param = PJ_POOL_ALLOC_T(pool, struct pjmedia_codec_param);
+ status = pjmedia_codec_mgr_get_default_param(cm, &si.fmt, si.param);
+ if (status != PJ_SUCCESS) {
+ jbsim_perror("Unable to get codec defaults", status);
+ goto on_error;
+ }
+
+ si.tx_pt = si.fmt.pt;
+
+ /* Apply ptime setting */
+ if (cfg->ptime) {
+ si.param->setting.frm_per_pkt = (pj_uint8_t)
+ ((cfg->ptime + si.param->info.frm_ptime - 1) /
+ si.param->info.frm_ptime);
+ }
+ /* Apply DTX setting */
+ si.param->setting.vad = cfg->dtx;
+
+ /* Apply PLC setting */
+ si.param->setting.plc = cfg->plc;
+
+ /* Create stream */
+ status = pjmedia_stream_create(g_app.endpt, pool, &si, g_app.loop, NULL, &stream->strm);
+ if (status != PJ_SUCCESS) {
+ jbsim_perror("Error creating stream", status);
+ goto on_error;
+ }
+
+ status = pjmedia_stream_get_port(stream->strm, &stream->port);
+ if (status != PJ_SUCCESS) {
+ jbsim_perror("Error retrieving stream", status);
+ goto on_error;
+ }
+
+ /* Start stream */
+ status = pjmedia_stream_start(stream->strm);
+ if (status != PJ_SUCCESS) {
+ jbsim_perror("Error starting stream", status);
+ goto on_error;
+ }
+
+ /* Done */
+ *p_stream = stream;
+ return PJ_SUCCESS;
+
+on_error:
+ if (stream) {
+ stream_destroy(stream);
+ } else {
+ if (pool)
+ pj_pool_release(pool);
+ }
+ return status;
+}
+
+
+/*****************************************************************************
+ * The test session
+ */
+static void test_destroy(void)
+{
+ if (g_app.tx)
+ stream_destroy(g_app.tx);
+ if (g_app.tx_wav)
+ pjmedia_port_destroy(g_app.tx_wav);
+ if (g_app.rx)
+ stream_destroy(g_app.rx);
+ if (g_app.rx_wav)
+ pjmedia_port_destroy(g_app.rx_wav);
+ if (g_app.loop)
+ pjmedia_transport_close(g_app.loop);
+ if (g_app.endpt)
+ pjmedia_endpt_destroy( g_app.endpt );
+ if (g_app.log_fd) {
+ pj_log_set_log_func(&pj_log_write);
+ pj_log_set_decor(pj_log_get_decor() | PJ_LOG_HAS_NEWLINE);
+ pj_file_close(g_app.log_fd);
+ g_app.log_fd = NULL;
+ }
+ if (g_app.pool)
+ pj_pool_release(g_app.pool);
+ pj_caching_pool_destroy( &g_app.cp );
+ pj_shutdown();
+}
+
+
+static pj_status_t test_init(void)
+{
+ struct stream_cfg strm_cfg;
+ pj_status_t status;
+
+ /* Must init PJLIB first: */
+ status = pj_init();
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+ /* Must create a pool factory before we can allocate any memory. */
+ pj_caching_pool_init(&g_app.cp, &pj_pool_factory_default_policy, 0);
+
+ /* Pool */
+ g_app.pool = pj_pool_create(&g_app.cp.factory, "g_app", 512, 512, NULL);
+
+ /* Log file */
+ if (g_app.cfg.log_file) {
+ status = pj_file_open(g_app.pool, g_app.cfg.log_file,
+ PJ_O_WRONLY,
+ &g_app.log_fd);
+ if (status != PJ_SUCCESS) {
+ jbsim_perror("Error writing output file", status);
+ goto on_error;
+ }
+
+ pj_log_set_decor(PJ_LOG_HAS_SENDER | PJ_LOG_HAS_COLOR | PJ_LOG_HAS_LEVEL_TEXT);
+ pj_log_set_log_func(&log_cb);
+ }
+
+ /*
+ * Initialize media endpoint.
+ * This will implicitly initialize PJMEDIA too.
+ */
+ status = pjmedia_endpt_create(&g_app.cp.factory, NULL, 0, &g_app.endpt);
+ if (status != PJ_SUCCESS) {
+ jbsim_perror("Error creating media endpoint", status);
+ goto on_error;
+ }
+
+ /* Register codecs */
+ pjmedia_codec_register_audio_codecs(g_app.endpt, NULL);
+
+ /* Create the loop transport */
+ status = pjmedia_transport_loop_create(g_app.endpt, &g_app.loop);
+ if (status != PJ_SUCCESS) {
+ jbsim_perror("Error creating loop transport", status);
+ goto on_error;
+ }
+
+ /* Create transmitter stream */
+ pj_bzero(&strm_cfg, sizeof(strm_cfg));
+ strm_cfg.name = "tx";
+ strm_cfg.dir = PJMEDIA_DIR_ENCODING;
+ strm_cfg.codec = g_app.cfg.codec;
+ strm_cfg.ptime = g_app.cfg.tx_ptime;
+ strm_cfg.dtx = g_app.cfg.tx_dtx;
+ strm_cfg.plc = PJ_TRUE;
+ status = stream_init(&strm_cfg, &g_app.tx);
+ if (status != PJ_SUCCESS)
+ goto on_error;
+
+ /* Create transmitter WAV */
+ status = pjmedia_wav_player_port_create(g_app.pool,
+ g_app.cfg.tx_wav_in,
+ g_app.cfg.tx_ptime,
+ 0,
+ 0,
+ &g_app.tx_wav);
+ if (status != PJ_SUCCESS) {
+ jbsim_perror("Error reading input WAV file", status);
+ goto on_error;
+ }
+
+ /* Make sure stream and WAV parameters match */
+ if (PJMEDIA_PIA_SRATE(&g_app.tx_wav->info) != PJMEDIA_PIA_SRATE(&g_app.tx->port->info) ||
+ PJMEDIA_PIA_CCNT(&g_app.tx_wav->info) != PJMEDIA_PIA_CCNT(&g_app.tx->port->info))
+ {
+ jbsim_perror("Error: Input WAV file has different clock rate "
+ "or number of channels than the codec", PJ_SUCCESS);
+ goto on_error;
+ }
+
+
+ /* Create receiver */
+ pj_bzero(&strm_cfg, sizeof(strm_cfg));
+ strm_cfg.name = "rx";
+ strm_cfg.dir = PJMEDIA_DIR_DECODING;
+ strm_cfg.codec = g_app.cfg.codec;
+ strm_cfg.ptime = g_app.cfg.rx_ptime;
+ strm_cfg.dtx = PJ_TRUE;
+ strm_cfg.plc = g_app.cfg.rx_plc;
+ status = stream_init(&strm_cfg, &g_app.rx);
+ if (status != PJ_SUCCESS)
+ goto on_error;
+
+ /* Create receiver WAV */
+ status = pjmedia_wav_writer_port_create(g_app.pool,
+ g_app.cfg.rx_wav_out,
+ PJMEDIA_PIA_SRATE(&g_app.rx->port->info),
+ PJMEDIA_PIA_CCNT(&g_app.rx->port->info),
+ PJMEDIA_PIA_SPF(&g_app.rx->port->info),
+ PJMEDIA_PIA_BITS(&g_app.rx->port->info),
+ 0,
+ 0,
+ &g_app.rx_wav);
+ if (status != PJ_SUCCESS) {
+ jbsim_perror("Error creating output WAV file", status);
+ goto on_error;
+ }
+
+
+ /* Frame buffer */
+ g_app.framebuf = (pj_int16_t*)
+ pj_pool_alloc(g_app.pool,
+ MAX(PJMEDIA_PIA_SPF(&g_app.rx->port->info),
+ PJMEDIA_PIA_SPF(&g_app.tx->port->info)) * sizeof(pj_int16_t));
+
+
+ /* Set the receiver in the loop transport */
+ pjmedia_transport_loop_disable_rx(g_app.loop, g_app.tx->strm, PJ_TRUE);
+
+ /* Done */
+ return PJ_SUCCESS;
+
+on_error:
+ test_destroy();
+ return status;
+}
+
+static void run_one_frame(pjmedia_port *src, pjmedia_port *dst,
+ pj_bool_t *has_frame)
+{
+ pjmedia_frame frame;
+ pj_status_t status;
+
+ pj_bzero(&frame, sizeof(frame));
+ frame.type = PJMEDIA_FRAME_TYPE_AUDIO;
+ frame.buf = g_app.framebuf;
+ frame.size = PJMEDIA_PIA_SPF(&dst->info) * 2;
+
+ status = pjmedia_port_get_frame(src, &frame);
+ pj_assert(status == PJ_SUCCESS);
+
+ if (status!= PJ_SUCCESS || frame.type != PJMEDIA_FRAME_TYPE_AUDIO) {
+ frame.buf = g_app.framebuf;
+ pjmedia_zero_samples(g_app.framebuf, PJMEDIA_PIA_SPF(&src->info));
+ frame.size = PJMEDIA_PIA_SPF(&src->info) * 2;
+ if (has_frame)
+ *has_frame = PJ_FALSE;
+ } else {
+ if (has_frame)
+ *has_frame = PJ_TRUE;
+ }
+
+
+ status = pjmedia_port_put_frame(dst, &frame);
+ pj_assert(status == PJ_SUCCESS);
+}
+
+
+/* This is the transmission "tick".
+ * This function is called periodically every "tick" milliseconds, and
+ * it will determine whether to transmit packet(s) (or to drop it).
+ */
+static void tx_tick(const pj_time_val *t)
+{
+ struct stream *strm = g_app.tx;
+ static char log_msg[120];
+ pjmedia_port *port = g_app.tx->port;
+ long pkt_interval;
+
+ /* packet interval, without jitter */
+ pkt_interval = PJMEDIA_PIA_SPF(&port->info) * 1000 /
+ PJMEDIA_PIA_SRATE(&port->info);
+
+ while (PJ_TIME_VAL_GTE(*t, strm->state.tx.next_schedule)) {
+ struct log_entry entry;
+ pj_bool_t drop_this_pkt = PJ_FALSE;
+ int jitter;
+
+ /* Init log entry */
+ pj_bzero(&entry, sizeof(entry));
+ entry.wall_clock = *t;
+
+ /*
+ * Determine whether to drop this packet
+ */
+ if (strm->state.tx.cur_lost_burst) {
+ /* We are currently dropping packet */
+
+ /* Make it comply to minimum lost burst */
+ if (strm->state.tx.cur_lost_burst < g_app.cfg.tx_min_lost_burst) {
+ drop_this_pkt = PJ_TRUE;
+ }
+
+ /* Correlate the next packet loss */
+ if (!drop_this_pkt &&
+ strm->state.tx.cur_lost_burst < g_app.cfg.tx_max_lost_burst &&
+ MAX(strm->state.tx.total_lost-LOSS_EXTRA,0) * 100 / MAX(strm->state.tx.total_tx,1) < g_app.cfg.tx_pct_avg_lost
+ )
+ {
+ strm->state.tx.drop_prob = ((g_app.cfg.tx_pct_loss_corr * strm->state.tx.drop_prob) +
+ ((100-g_app.cfg.tx_pct_loss_corr) * (pj_rand()%100))
+ ) / 100;
+ if (strm->state.tx.drop_prob >= 100)
+ strm->state.tx.drop_prob = 99;
+
+ if (strm->state.tx.drop_prob >= 100 - g_app.cfg.tx_pct_avg_lost)
+ drop_this_pkt = PJ_TRUE;
+ }
+ }
+
+ /* If we're not dropping packet then use randomly distributed loss */
+ if (!drop_this_pkt &&
+ MAX(strm->state.tx.total_lost-LOSS_EXTRA,0) * 100 / MAX(strm->state.tx.total_tx,1) < g_app.cfg.tx_pct_avg_lost)
+ {
+ strm->state.tx.drop_prob = pj_rand() % 100;
+
+ if (strm->state.tx.drop_prob >= 100 - g_app.cfg.tx_pct_avg_lost)
+ drop_this_pkt = PJ_TRUE;
+ }
+
+ if (drop_this_pkt) {
+ /* Drop the frame */
+ pjmedia_transport_simulate_lost(g_app.loop, PJMEDIA_DIR_ENCODING, 100);
+ run_one_frame(g_app.tx_wav, g_app.tx->port, NULL);
+ pjmedia_transport_simulate_lost(g_app.loop, PJMEDIA_DIR_ENCODING, 0);
+
+ entry.event = EVENT_TX_DROP;
+ entry.log = "** This packet was lost **";
+
+ ++strm->state.tx.total_lost;
+ ++strm->state.tx.cur_lost_burst;
+
+ } else {
+ pjmedia_rtcp_stat stat;
+ pjmedia_jb_state jstate;
+ unsigned last_discard;
+
+ pjmedia_stream_get_stat_jbuf(g_app.rx->strm, &jstate);
+ last_discard = jstate.discard;
+
+ run_one_frame(g_app.tx_wav, g_app.tx->port, NULL);
+
+ pjmedia_stream_get_stat(g_app.rx->strm, &stat);
+ pjmedia_stream_get_stat_jbuf(g_app.rx->strm, &jstate);
+
+ entry.event = EVENT_TX;
+ entry.jb_state = &jstate;
+ entry.stat = &stat;
+ entry.log = log_msg;
+
+ if (jstate.discard > last_discard)
+ strcat(log_msg, "** Note: packet was discarded by jitter buffer **");
+
+ strm->state.tx.cur_lost_burst = 0;
+ }
+
+ write_log(&entry, PJ_TRUE);
+
+ ++strm->state.tx.total_tx;
+
+ /* Calculate next schedule */
+ strm->state.tx.next_schedule.sec = 0;
+ strm->state.tx.next_schedule.msec = (strm->state.tx.total_tx + 1) * pkt_interval;
+
+ /* Apply jitter */
+ if (g_app.cfg.tx_max_jitter || g_app.cfg.tx_min_jitter) {
+
+ if (g_app.cfg.tx_max_jitter == g_app.cfg.tx_min_jitter) {
+ /* Fixed jitter */
+ switch (pj_rand() % 3) {
+ case 0:
+ jitter = 0 - g_app.cfg.tx_min_jitter;
+ break;
+ case 2:
+ jitter = g_app.cfg.tx_min_jitter;
+ break;
+ default:
+ jitter = 0;
+ break;
+ }
+ } else {
+ int jitter_range;
+ jitter_range = (g_app.cfg.tx_max_jitter-g_app.cfg.tx_min_jitter)*2;
+ jitter = pj_rand() % jitter_range;
+ if (jitter < jitter_range/2) {
+ jitter = 0 - g_app.cfg.tx_min_jitter - (jitter/2);
+ } else {
+ jitter = g_app.cfg.tx_min_jitter + (jitter/2);
+ }
+ }
+
+ } else {
+ jitter = 0;
+ }
+
+ pj_time_val_normalize(&strm->state.tx.next_schedule);
+
+ sprintf(log_msg, "** Packet #%u tick is at %d.%03d, %d ms jitter applied **",
+ strm->state.tx.total_tx+1,
+ (int)strm->state.tx.next_schedule.sec, (int)strm->state.tx.next_schedule.msec,
+ jitter);
+
+ strm->state.tx.next_schedule.msec += jitter;
+ pj_time_val_normalize(&strm->state.tx.next_schedule);
+
+ } /* while */
+}
+
+
+/* This is the RX "tick".
+ * This function is called periodically every "tick" milliseconds, and
+ * it will determine whether to call get_frame() from the RX stream.
+ */
+static void rx_tick(const pj_time_val *t)
+{
+ struct stream *strm = g_app.rx;
+ pjmedia_port *port = g_app.rx->port;
+ long pkt_interval;
+
+ pkt_interval = PJMEDIA_PIA_SPF(&port->info) * 1000 /
+ PJMEDIA_PIA_SRATE(&port->info) *
+ g_app.cfg.rx_snd_burst;
+
+ if (PJ_TIME_VAL_GTE(*t, strm->state.rx.next_schedule)) {
+ unsigned i;
+ for (i=0; i<g_app.cfg.rx_snd_burst; ++i) {
+ struct log_entry entry;
+ pjmedia_rtcp_stat stat;
+ pjmedia_jb_state jstate;
+ pj_bool_t has_frame;
+ char msg[120];
+ unsigned last_empty;
+
+ pjmedia_stream_get_stat(g_app.rx->strm, &stat);
+ pjmedia_stream_get_stat_jbuf(g_app.rx->strm, &jstate);
+ last_empty = jstate.empty;
+
+ /* Pre GET event */
+ pj_bzero(&entry, sizeof(entry));
+ entry.event = EVENT_GET_PRE;
+ entry.wall_clock = *t;
+ entry.stat = &stat;
+ entry.jb_state = &jstate;
+
+ write_log(&entry, PJ_TRUE);
+
+ /* GET */
+ run_one_frame(g_app.rx->port, g_app.rx_wav, &has_frame);
+
+ /* Post GET event */
+ pjmedia_stream_get_stat(g_app.rx->strm, &stat);
+ pjmedia_stream_get_stat_jbuf(g_app.rx->strm, &jstate);
+
+ pj_bzero(&entry, sizeof(entry));
+ entry.event = EVENT_GET_POST;
+ entry.wall_clock = *t;
+ entry.stat = &stat;
+ entry.jb_state = &jstate;
+
+ msg[0] = '\0';
+ entry.log = msg;
+
+ if (jstate.empty > last_empty)
+ strcat(msg, "** JBUF was empty **");
+ if (!has_frame)
+ strcat(msg, "** NULL frame was returned **");
+
+ write_log(&entry, PJ_TRUE);
+
+ }
+
+
+ strm->state.rx.next_schedule.msec += pkt_interval;
+ pj_time_val_normalize(&strm->state.rx.next_schedule);
+ }
+
+}
+
+static void test_loop(long duration)
+{
+ g_app.wall_clock.sec = 0;
+ g_app.wall_clock.msec = 0;
+
+ while (PJ_TIME_VAL_MSEC(g_app.wall_clock) <= duration) {
+
+ /* Run TX tick */
+ tx_tick(&g_app.wall_clock);
+
+ /* Run RX tick */
+ rx_tick(&g_app.wall_clock);
+
+ /* Increment tick */
+ g_app.wall_clock.msec += WALL_CLOCK_TICK;
+ pj_time_val_normalize(&g_app.wall_clock);
+ }
+}
+
+
+/*****************************************************************************
+ * usage()
+ */
+enum {
+ OPT_CODEC = 'c',
+ OPT_INPUT = 'i',
+ OPT_OUTPUT = 'o',
+ OPT_DURATION = 'd',
+ OPT_LOG_FILE = 'l',
+ OPT_LOSS = 'x',
+ OPT_MIN_JITTER = 'j',
+ OPT_MAX_JITTER = 'J',
+ OPT_SND_BURST = 'b',
+ OPT_TX_PTIME = 't',
+ OPT_RX_PTIME = 'r',
+ OPT_NO_VAD = 'U',
+ OPT_NO_PLC = 'p',
+ OPT_JB_PREFETCH = 'P',
+ OPT_JB_MIN_PRE = 'm',
+ OPT_JB_MAX_PRE = 'M',
+ OPT_JB_MAX = 'X',
+ OPT_HELP = 'h',
+ OPT_MIN_LOST_BURST = 1,
+ OPT_MAX_LOST_BURST,
+ OPT_LOSS_CORR,
+};
+
+
+static void usage(void)
+{
+ printf("jbsim - System and network impairments simulator\n");
+ printf("Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)\n");
+ printf("\n");
+ printf("This program emulates various system and network impairment\n");
+ printf("conditions as well as application parameters and apply it to\n");
+ printf("an input WAV file. The output is another WAV file as well as\n");
+ printf("a detailed log file (in CSV format) for troubleshooting.\n");
+ printf("\n");
+ printf("Usage:\n");
+ printf(" jbsim [OPTIONS]\n");
+ printf("\n");
+ printf("General OPTIONS:\n");
+ printf(" --codec, -%c NAME Set the audio codec\n", OPT_CODEC);
+ printf(" Default: %s\n", CODEC);
+ printf(" --input, -%c FILE Set WAV reference file to FILE\n", OPT_INPUT);
+ printf(" Default: " WAV_REF "\n");
+ printf(" --output, -%c FILE Set WAV output file to FILE\n", OPT_OUTPUT);
+ printf(" Default: " WAV_OUT "\n");
+ printf(" --duration, -%c SEC Set test duration to SEC seconds\n", OPT_DURATION);
+ printf(" Default: %d\n", DURATION);
+ printf(" --log-file, -%c FILE Save simulation log file to FILE\n", OPT_LOG_FILE);
+ printf(" Note: FILE will be in CSV format with semicolon separator\n");
+ printf(" Default: %s\n", LOG_FILE);
+ printf(" --help, -h Display this screen\n");
+ printf("\n");
+ printf("Simulation OPTIONS:\n");
+ printf(" --loss, -%c PCT Set packet average loss to PCT percent\n", OPT_LOSS);
+ printf(" Default: 0\n");
+ printf(" --loss-corr PCT Set the loss correlation to PCT percent. Default: 0\n");
+ printf(" --min-lost-burst N Set minimum packet lost burst (default:%d)\n", MIN_LOST_BURST);
+ printf(" --max-lost-burst N Set maximum packet lost burst (default:%d)\n", MAX_LOST_BURST);
+ printf(" --min-jitter, -%c MSEC Set minimum network jitter to MSEC\n", OPT_MIN_JITTER);
+ printf(" Default: 0\n");
+ printf(" --max-jitter, -%c MSEC Set maximum network jitter to MSEC\n", OPT_MAX_JITTER);
+ printf(" Default: 0\n");
+ printf(" --snd-burst, -%c VAL Set RX sound burst value to VAL frames.\n", OPT_SND_BURST);
+ printf(" Default: 1\n");
+ printf(" --tx-ptime, -%c MSEC Set transmitter ptime to MSEC\n", OPT_TX_PTIME);
+ printf(" Default: 0 (not set, use default)\n");
+ printf(" --rx-ptime, -%c MSEC Set receiver ptime to MSEC\n", OPT_RX_PTIME);
+ printf(" Default: 0 (not set, use default)\n");
+ printf(" --no-vad, -%c Disable VAD/DTX in transmitter\n", OPT_NO_VAD);
+ printf(" --no-plc, -%c Disable PLC in receiver\n", OPT_NO_PLC);
+ printf(" --jb-prefetch, -%c Enable prefetch bufferring in jitter buffer\n", OPT_JB_PREFETCH);
+ printf(" --jb-min-pre, -%c MSEC Jitter buffer minimum prefetch delay in msec\n", OPT_JB_MIN_PRE);
+ printf(" --jb-max-pre, -%c MSEC Jitter buffer maximum prefetch delay in msec\n", OPT_JB_MAX_PRE);
+ printf(" --jb-max, -%c MSEC Set maximum delay that can be accomodated by the\n", OPT_JB_MAX);
+ printf(" jitter buffer msec.\n");
+}
+
+
+static int init_options(int argc, char *argv[])
+{
+ struct pj_getopt_option long_options[] = {
+ { "codec", 1, 0, OPT_CODEC },
+ { "input", 1, 0, OPT_INPUT },
+ { "output", 1, 0, OPT_OUTPUT },
+ { "duration", 1, 0, OPT_DURATION },
+ { "log-file", 1, 0, OPT_LOG_FILE},
+ { "loss", 1, 0, OPT_LOSS },
+ { "min-lost-burst", 1, 0, OPT_MIN_LOST_BURST},
+ { "max-lost-burst", 1, 0, OPT_MAX_LOST_BURST},
+ { "loss-corr", 1, 0, OPT_LOSS_CORR},
+ { "min-jitter", 1, 0, OPT_MIN_JITTER },
+ { "max-jitter", 1, 0, OPT_MAX_JITTER },
+ { "snd-burst", 1, 0, OPT_SND_BURST },
+ { "tx-ptime", 1, 0, OPT_TX_PTIME },
+ { "rx-ptime", 1, 0, OPT_RX_PTIME },
+ { "no-vad", 0, 0, OPT_NO_VAD },
+ { "no-plc", 0, 0, OPT_NO_PLC },
+ { "jb-prefetch", 0, 0, OPT_JB_PREFETCH },
+ { "jb-min-pre", 1, 0, OPT_JB_MIN_PRE },
+ { "jb-max-pre", 1, 0, OPT_JB_MAX_PRE },
+ { "jb-max", 1, 0, OPT_JB_MAX },
+ { "help", 0, 0, OPT_HELP},
+ { NULL, 0, 0, 0 },
+ };
+ int c;
+ int option_index;
+ char format[128];
+
+ /* Init default config */
+ g_app.cfg.codec = pj_str(CODEC);
+ g_app.cfg.duration_msec = DURATION * 1000;
+ g_app.cfg.silent = SILENT;
+ g_app.cfg.log_file = LOG_FILE;
+ g_app.cfg.tx_wav_in = WAV_REF;
+ g_app.cfg.tx_ptime = 0;
+ g_app.cfg.tx_min_jitter = 0;
+ g_app.cfg.tx_max_jitter = 0;
+ g_app.cfg.tx_dtx = DTX;
+ g_app.cfg.tx_pct_avg_lost = 0;
+ g_app.cfg.tx_min_lost_burst = MIN_LOST_BURST;
+ g_app.cfg.tx_max_lost_burst = MAX_LOST_BURST;
+ g_app.cfg.tx_pct_loss_corr = LOSS_CORR;
+
+ g_app.cfg.rx_wav_out = WAV_OUT;
+ g_app.cfg.rx_ptime = 0;
+ g_app.cfg.rx_plc = PLC;
+ g_app.cfg.rx_snd_burst = 1;
+ g_app.cfg.rx_jb_init = -1;
+ g_app.cfg.rx_jb_min_pre = -1;
+ g_app.cfg.rx_jb_max_pre = -1;
+ g_app.cfg.rx_jb_max = -1;
+
+ /* Build format */
+ format[0] = '\0';
+ for (c=0; c<PJ_ARRAY_SIZE(long_options)-1; ++c) {
+ if (long_options[c].has_arg) {
+ char cmd[10];
+ pj_ansi_snprintf(cmd, sizeof(cmd), "%c:", long_options[c].val);
+ pj_ansi_strcat(format, cmd);
+ }
+ }
+ for (c=0; c<PJ_ARRAY_SIZE(long_options)-1; ++c) {
+ if (long_options[c].has_arg == 0) {
+ char cmd[10];
+ pj_ansi_snprintf(cmd, sizeof(cmd), "%c", long_options[c].val);
+ pj_ansi_strcat(format, cmd);
+ }
+ }
+
+ /* Parse options */
+ pj_optind = 0;
+ while((c=pj_getopt_long(argc,argv, format,
+ long_options, &option_index))!=-1)
+ {
+ switch (c) {
+ case OPT_CODEC:
+ g_app.cfg.codec = pj_str(pj_optarg);
+ break;
+ case OPT_INPUT:
+ g_app.cfg.tx_wav_in = pj_optarg;
+ break;
+ case OPT_OUTPUT:
+ g_app.cfg.rx_wav_out = pj_optarg;
+ break;
+ case OPT_DURATION:
+ g_app.cfg.duration_msec = atoi(pj_optarg) * 1000;
+ break;
+ case OPT_LOG_FILE:
+ g_app.cfg.log_file = pj_optarg;
+ break;
+ case OPT_LOSS:
+ g_app.cfg.tx_pct_avg_lost = atoi(pj_optarg);
+ if (g_app.cfg.tx_pct_avg_lost > 100) {
+ puts("Error: Invalid loss value?");
+ return 1;
+ }
+ break;
+ case OPT_MIN_LOST_BURST:
+ g_app.cfg.tx_min_lost_burst = atoi(pj_optarg);
+ break;
+ case OPT_MAX_LOST_BURST:
+ g_app.cfg.tx_max_lost_burst = atoi(pj_optarg);
+ break;
+ case OPT_LOSS_CORR:
+ g_app.cfg.tx_pct_loss_corr = atoi(pj_optarg);
+ if (g_app.cfg.tx_pct_avg_lost > 100) {
+ puts("Error: Loss correlation is in percentage, value is not valid?");
+ return 1;
+ }
+ break;
+ case OPT_MIN_JITTER:
+ g_app.cfg.tx_min_jitter = atoi(pj_optarg);
+ break;
+ case OPT_MAX_JITTER:
+ g_app.cfg.tx_max_jitter = atoi(pj_optarg);
+ break;
+ case OPT_SND_BURST:
+ g_app.cfg.rx_snd_burst = atoi(pj_optarg);
+ break;
+ case OPT_TX_PTIME:
+ g_app.cfg.tx_ptime = atoi(pj_optarg);
+ break;
+ case OPT_RX_PTIME:
+ g_app.cfg.rx_ptime = atoi(pj_optarg);
+ break;
+ case OPT_NO_VAD:
+ g_app.cfg.tx_dtx = PJ_FALSE;
+ break;
+ case OPT_NO_PLC:
+ g_app.cfg.rx_plc = PJ_FALSE;
+ break;
+ case OPT_JB_PREFETCH:
+ g_app.cfg.rx_jb_init = 1;
+ break;
+ case OPT_JB_MIN_PRE:
+ g_app.cfg.rx_jb_min_pre = atoi(pj_optarg);
+ break;
+ case OPT_JB_MAX_PRE:
+ g_app.cfg.rx_jb_max_pre = atoi(pj_optarg);
+ break;
+ case OPT_JB_MAX:
+ g_app.cfg.rx_jb_max = atoi(pj_optarg);
+ break;
+ case OPT_HELP:
+ usage();
+ return 1;
+ default:
+ usage();
+ return 1;
+ }
+ }
+
+ /* Check for orphaned params */
+ if (pj_optind < argc) {
+ usage();
+ return 1;
+ }
+
+ /* Normalize options */
+ if (g_app.cfg.rx_jb_init < g_app.cfg.rx_jb_min_pre)
+ g_app.cfg.rx_jb_init = g_app.cfg.rx_jb_min_pre;
+ else if (g_app.cfg.rx_jb_init > g_app.cfg.rx_jb_max_pre)
+ g_app.cfg.rx_jb_init = g_app.cfg.rx_jb_max_pre;
+
+ if (g_app.cfg.tx_max_jitter < g_app.cfg.tx_min_jitter)
+ g_app.cfg.tx_max_jitter = g_app.cfg.tx_min_jitter;
+ return 0;
+}
+
+/*****************************************************************************
+ * main()
+ */
+int main(int argc, char *argv[])
+{
+ pj_status_t status;
+
+ if (init_options(argc, argv) != 0)
+ return 1;
+
+
+ /* Init */
+ status = test_init();
+ if (status != PJ_SUCCESS)
+ return 1;
+
+ /* Print parameters */
+ PJ_LOG(3,(THIS_FILE, "Starting simulation. Parameters: "));
+ PJ_LOG(3,(THIS_FILE, " Codec=%.*s, tx_ptime=%d, rx_ptime=%d",
+ (int)g_app.cfg.codec.slen,
+ g_app.cfg.codec.ptr,
+ g_app.cfg.tx_ptime,
+ g_app.cfg.rx_ptime));
+ PJ_LOG(3,(THIS_FILE, " Loss avg=%d%%, min_burst=%d, max_burst=%d",
+ g_app.cfg.tx_pct_avg_lost,
+ g_app.cfg.tx_min_lost_burst,
+ g_app.cfg.tx_max_lost_burst));
+ PJ_LOG(3,(THIS_FILE, " TX jitter min=%dms, max=%dms",
+ g_app.cfg.tx_min_jitter,
+ g_app.cfg.tx_max_jitter));
+ PJ_LOG(3,(THIS_FILE, " RX jb init:%dms, min_pre=%dms, max_pre=%dms, max=%dms",
+ g_app.cfg.rx_jb_init,
+ g_app.cfg.rx_jb_min_pre,
+ g_app.cfg.rx_jb_max_pre,
+ g_app.cfg.rx_jb_max));
+ PJ_LOG(3,(THIS_FILE, " RX sound burst:%d frames",
+ g_app.cfg.rx_snd_burst));
+ PJ_LOG(3,(THIS_FILE, " DTX=%d, PLC=%d",
+ g_app.cfg.tx_dtx, g_app.cfg.rx_plc));
+
+ /* Run test loop */
+ test_loop(g_app.cfg.duration_msec);
+
+ /* Print statistics */
+ PJ_LOG(3,(THIS_FILE, "Simulation done"));
+ PJ_LOG(3,(THIS_FILE, " TX packets=%u, dropped=%u/%5.1f%%",
+ g_app.tx->state.tx.total_tx,
+ g_app.tx->state.tx.total_lost,
+ (float)(g_app.tx->state.tx.total_lost * 100.0 / g_app.tx->state.tx.total_tx)));
+
+ /* Done */
+ test_destroy();
+
+ return 0;
+}
diff --git a/pjsip-apps/src/samples/latency.c b/pjsip-apps/src/samples/latency.c
new file mode 100644
index 0000000..6193e61
--- /dev/null
+++ b/pjsip-apps/src/samples/latency.c
@@ -0,0 +1,202 @@
+/* $Id: latency.c 3664 2011-07-19 03:42:28Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* See http://trac.pjsip.org/repos/wiki/MeasuringSoundLatency on
+ * how to use this program.
+ */
+
+#include <pjmedia.h>
+#include <pjlib.h>
+
+#include <stdio.h>
+
+#define THIS_FILE "lacency.c"
+
+
+/* Util to display the error message for the specified error code */
+static int app_perror( const char *sender, const char *title,
+ pj_status_t status)
+{
+ char errmsg[PJ_ERR_MSG_SIZE];
+
+ PJ_UNUSED_ARG(sender);
+
+ pj_strerror(status, errmsg, sizeof(errmsg));
+
+ printf("%s: %s [code=%d]\n", title, errmsg, status);
+ return 1;
+}
+
+/*
+ * Find out latency
+ */
+static int calculate_latency(pj_pool_t *pool, pjmedia_port *wav)
+{
+ pjmedia_frame frm;
+ short *buf;
+ unsigned i, samples_per_frame, read, len;
+ unsigned start_pos;
+ pj_status_t status;
+
+ unsigned lat_sum = 0,
+ lat_cnt = 0,
+ lat_min = 10000,
+ lat_max = 0;
+
+ samples_per_frame = PJMEDIA_PIA_SPF(&wav->info);
+ frm.buf = pj_pool_alloc(pool, samples_per_frame * 2);
+ frm.size = samples_per_frame * 2;
+ len = pjmedia_wav_player_get_len(wav);
+ buf = pj_pool_alloc(pool, len + samples_per_frame);
+
+ read = 0;
+ while (read < len/2) {
+ status = pjmedia_port_get_frame(wav, &frm);
+ if (status != PJ_SUCCESS)
+ break;
+
+ pjmedia_copy_samples(buf+read, (short*)frm.buf, samples_per_frame);
+ read += samples_per_frame;
+ }
+
+ if (read < 2 * PJMEDIA_PIA_SRATE(&wav->info)) {
+ puts("Error: too short");
+ return -1;
+ }
+
+ start_pos = 0;
+ while (start_pos < len/2 - PJMEDIA_PIA_SRATE(&wav->info)) {
+ int max_signal = 0;
+ unsigned max_signal_pos = start_pos;
+ unsigned max_echo_pos = 0;
+ unsigned pos;
+ unsigned lat;
+
+ /* Get the largest signal in the next 0.7s */
+ for (i=start_pos; i<start_pos + PJMEDIA_PIA_SRATE(&wav->info) * 700 / 1000; ++i) {
+ if (abs(buf[i]) > max_signal) {
+ max_signal = abs(buf[i]);
+ max_signal_pos = i;
+ }
+ }
+
+ /* Advance 10ms from max_signal_pos */
+ pos = max_signal_pos + 10 * PJMEDIA_PIA_SRATE(&wav->info) / 1000;
+
+ /* Get the largest signal in the next 500ms */
+ max_signal = 0;
+ max_echo_pos = pos;
+ for (i=pos; i<pos+PJMEDIA_PIA_SRATE(&wav->info)/2; ++i) {
+ if (abs(buf[i]) > max_signal) {
+ max_signal = abs(buf[i]);
+ max_echo_pos = i;
+ }
+ }
+
+ lat = (max_echo_pos - max_signal_pos) * 1000 / PJMEDIA_PIA_SRATE(&wav->info);
+
+#if 0
+ printf("Latency = %u\n", lat);
+#endif
+
+ lat_sum += lat;
+ lat_cnt++;
+ if (lat < lat_min)
+ lat_min = lat;
+ if (lat > lat_max)
+ lat_max = lat;
+
+ /* Advance next loop */
+ start_pos += PJMEDIA_PIA_SRATE(&wav->info);
+ }
+
+ printf("Latency average = %u\n", lat_sum / lat_cnt);
+ printf("Latency minimum = %u\n", lat_min);
+ printf("Latency maximum = %u\n", lat_max);
+ printf("Number of data = %u\n", lat_cnt);
+ return 0;
+}
+
+
+/*
+ * main()
+ */
+int main(int argc, char *argv[])
+{
+ enum { NSAMPLES = 160, COUNT=100 };
+ pj_caching_pool cp;
+ pj_pool_t *pool;
+ pjmedia_port *wav;
+ pj_status_t status;
+
+
+ /* Verify cmd line arguments. */
+ if (argc != 2) {
+ puts("Error: missing argument(s)");
+ puts("Usage: latency REV.WAV");
+ return 1;
+ }
+
+ pj_log_set_level(0);
+
+ status = pj_init();
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);
+
+ pool = pj_pool_create( &cp.factory, /* pool factory */
+ "wav", /* pool name. */
+ 4000, /* init size */
+ 4000, /* increment size */
+ NULL /* callback on error */
+ );
+
+ status = pj_register_strerror(PJMEDIA_ERRNO_START, PJ_ERRNO_SPACE_SIZE,
+ &pjmedia_strerror);
+ pj_assert(status == PJ_SUCCESS);
+
+ /* Wav */
+ status = pjmedia_wav_player_port_create( pool, /* memory pool */
+ argv[1], /* file to play */
+ 0, /* use default ptime*/
+ 0, /* flags */
+ 0, /* default buffer */
+ &wav /* returned port */
+ );
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, argv[1], status);
+ return 1;
+ }
+
+ status = calculate_latency(pool, wav);
+ if (status != PJ_SUCCESS)
+ return 1;
+
+ status = pjmedia_port_destroy( wav );
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ pj_pool_release( pool );
+ pj_caching_pool_destroy( &cp );
+ pj_shutdown();
+
+ /* Done. */
+ return 0;
+}
+
diff --git a/pjsip-apps/src/samples/level.c b/pjsip-apps/src/samples/level.c
new file mode 100644
index 0000000..59bbb96
--- /dev/null
+++ b/pjsip-apps/src/samples/level.c
@@ -0,0 +1,179 @@
+/* $Id: level.c 3664 2011-07-19 03:42:28Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+/**
+ * \page page_pjmedia_samples_level_c Samples: Reading from WAV File
+ *
+ * This is a very simple example to use the @ref PJMEDIA_FILE_PLAY, to
+ * directly read the samples from the file.
+ *
+ * This file is pjsip-apps/src/samples/level.c
+ *
+ * \includelineno level.c
+ */
+
+
+static const char *desc =
+ " FILE: \n"
+ " level.c \n"
+ " \n"
+ " PURPOSE: \n"
+ " Read PCM WAV file and display the audio level the first 100 frames. \n"
+ " Each frame is assumed to have 160 samples. \n"
+ " \n"
+ " USAGE: \n"
+ " level file.wav \n"
+ " \n"
+ " The WAV file SHOULD have a 16bit mono samples. ";
+
+#include <pjmedia.h>
+#include <pjlib.h>
+
+#include <stdio.h>
+
+/* For logging purpose. */
+#define THIS_FILE "level.c"
+
+
+/* Util to display the error message for the specified error code */
+static int app_perror( const char *sender, const char *title,
+ pj_status_t status)
+{
+ char errmsg[PJ_ERR_MSG_SIZE];
+
+ PJ_UNUSED_ARG(sender);
+
+ pj_strerror(status, errmsg, sizeof(errmsg));
+
+ printf("%s: %s [code=%d]\n", title, errmsg, status);
+ return 1;
+}
+
+
+/*
+ * main()
+ */
+int main(int argc, char *argv[])
+{
+ enum { NSAMPLES = 640, COUNT=100 };
+ pj_caching_pool cp;
+ pjmedia_endpt *med_endpt;
+ pj_pool_t *pool;
+ pjmedia_port *file_port;
+ int i;
+ pj_status_t status;
+
+
+ /* Verify cmd line arguments. */
+ if (argc != 2) {
+ puts("");
+ puts(desc);
+ return 1;
+ }
+
+ /* Must init PJLIB first: */
+ status = pj_init();
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ /* Must create a pool factory before we can allocate any memory. */
+ pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);
+
+ /*
+ * Initialize media endpoint.
+ * This will implicitly initialize PJMEDIA too.
+ */
+ status = pjmedia_endpt_create(&cp.factory, NULL, 1, &med_endpt);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ /* Create memory pool for our file player */
+ pool = pj_pool_create( &cp.factory, /* pool factory */
+ "wav", /* pool name. */
+ 4000, /* init size */
+ 4000, /* increment size */
+ NULL /* callback on error */
+ );
+
+ /* Create file media port from the WAV file */
+ status = pjmedia_wav_player_port_create( pool, /* memory pool */
+ argv[1], /* file to play */
+ 0, /* use default ptime*/
+ 0, /* flags */
+ 0, /* default buffer */
+ &file_port/* returned port */
+ );
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to use WAV file", status);
+ return 1;
+ }
+
+ if (PJMEDIA_PIA_SPF(&file_port->info) > NSAMPLES) {
+ app_perror(THIS_FILE, "WAV clock rate is too big", PJ_EINVAL);
+ return 1;
+ }
+
+ puts("Time\tPCMU\tLinear");
+ puts("------------------------");
+
+ for (i=0; i<COUNT; ++i) {
+ pj_int16_t framebuf[NSAMPLES];
+ pjmedia_frame frm;
+ pj_int32_t level32;
+ unsigned ms;
+ int level;
+
+ frm.buf = framebuf;
+ frm.size = sizeof(framebuf);
+
+ pjmedia_port_get_frame(file_port, &frm);
+
+ level32 = pjmedia_calc_avg_signal(framebuf,
+ PJMEDIA_PIA_SPF(&file_port->info));
+ level = pjmedia_linear2ulaw(level32) ^ 0xFF;
+
+ ms = i * 1000 * PJMEDIA_PIA_SPF(&file_port->info) /
+ PJMEDIA_PIA_SRATE(&file_port->info);
+ printf("%03d.%03d\t%7d\t%7d\n",
+ ms/1000, ms%1000, level, level32);
+ }
+ puts("");
+
+
+ /* Destroy file port */
+ status = pjmedia_port_destroy( file_port );
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ /* Release application pool */
+ pj_pool_release( pool );
+
+ /* Destroy media endpoint. */
+ pjmedia_endpt_destroy( med_endpt );
+
+ /* Destroy pool factory */
+ pj_caching_pool_destroy( &cp );
+
+ /* Shutdown PJLIB */
+ pj_shutdown();
+
+
+ /* Done. */
+ return 0;
+}
+
diff --git a/pjsip-apps/src/samples/main_rtems.c b/pjsip-apps/src/samples/main_rtems.c
new file mode 100644
index 0000000..d26605a
--- /dev/null
+++ b/pjsip-apps/src/samples/main_rtems.c
@@ -0,0 +1,12 @@
+
+/*
+ * !! OIY OIY !!
+ *
+ * The purpose of this file is only to get the executable linked. I haven't
+ * actually tried to run this on RTEMS!!
+ *
+ */
+
+#include "../../pjlib/src/pjlib-test/main_rtems.c"
+
+
diff --git a/pjsip-apps/src/samples/mix.c b/pjsip-apps/src/samples/mix.c
new file mode 100644
index 0000000..c8e224f
--- /dev/null
+++ b/pjsip-apps/src/samples/mix.c
@@ -0,0 +1,237 @@
+/* $Id: mix.c 3664 2011-07-19 03:42:28Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+ /**
+ * \page page_pjmedia_samples_mix_c Samples: Mixing WAV files
+ *
+ * This file is pjsip-apps/src/samples/mix.c
+ *
+ * \includelineno mix.c
+ */
+
+#include <pjlib.h>
+#include <pjlib-util.h>
+#include <pjmedia.h>
+
+#define THIS_FILE "mix.c"
+
+static const char *desc =
+ " mix\n"
+ "\n"
+ " PURPOSE:\n"
+ " Mix input WAV files and save it to output WAV. Input WAV can have\n"
+ " different clock rate.\n"
+ "\n"
+ "\n"
+ " USAGE:\n"
+ " mix [options] output.wav input1.wav [input2.wav] ...\n"
+ "\n"
+ " arguments:\n"
+ " output.wav Set the output WAV filename.\n"
+ " input1.wav Set the input WAV filename.\n"
+ " input2.wav Set the input WAV filename.\n"
+ "\n"
+ " options:\n"
+ " -c N Set clock rate to N Hz (default 16000)\n"
+ " -f Force write (overwrite output without warning\n"
+;
+
+#define MAX_WAV 16
+#define PTIME 20
+#define APPEND 1000
+
+struct wav_input
+{
+ const char *fname;
+ pjmedia_port *port;
+ unsigned slot;
+};
+
+static int err_ret(const char *title, pj_status_t status)
+{
+ char errmsg[PJ_ERR_MSG_SIZE];
+ pj_strerror(status, errmsg, sizeof(errmsg));
+ PJ_LOG(3,(THIS_FILE, "%s error: %s", title, errmsg));
+ return 1;
+}
+
+static void usage(void)
+{
+ puts(desc);
+}
+
+int main(int argc, char *argv[])
+{
+ pj_caching_pool cp;
+ pj_pool_t *pool;
+ pjmedia_endpt *med_ept;
+ unsigned clock_rate = 16000;
+ int c, force=0;
+ const char *out_fname;
+ pjmedia_conf *conf;
+ pjmedia_port *wavout;
+ struct wav_input wav_input[MAX_WAV];
+ pj_size_t longest = 0, processed;
+ unsigned i, input_cnt = 0;
+ pj_status_t status;
+
+#define CHECK(op) do { \
+ status = op; \
+ if (status != PJ_SUCCESS) \
+ return err_ret(#op, status); \
+ } while (0)
+
+
+ /* Parse arguments */
+ while ((c=pj_getopt(argc, argv, "c:f")) != -1) {
+ switch (c) {
+ case 'c':
+ clock_rate = atoi(pj_optarg);
+ if (clock_rate < 1000) {
+ puts("Error: invalid clock rate");
+ usage();
+ return -1;
+ }
+ break;
+ case 'f':
+ force = 1;
+ break;
+ }
+ }
+
+ /* Get output WAV name */
+ if (pj_optind == argc) {
+ puts("Error: no WAV output is specified");
+ usage();
+ return 1;
+ }
+
+ out_fname = argv[pj_optind++];
+ if (force==0 && pj_file_exists(out_fname)) {
+ char in[8];
+
+ printf("File %s exists, overwrite? [Y/N] ", out_fname);
+ fflush(stdout);
+ if (fgets(in, sizeof(in), stdin) == NULL)
+ return 1;
+ if (pj_tolower(in[0]) != 'y')
+ return 1;
+ }
+
+ /* Scan input file names */
+ for (input_cnt=0 ; pj_optind<argc && input_cnt<MAX_WAV;
+ ++pj_optind, ++input_cnt)
+ {
+ if (!pj_file_exists(argv[pj_optind])) {
+ printf("Error: input file %s doesn't exist\n",
+ argv[pj_optind]);
+ return 1;
+ }
+ wav_input[input_cnt].fname = argv[pj_optind];
+ wav_input[input_cnt].port = NULL;
+ wav_input[input_cnt].slot = 0;
+ }
+
+ if (input_cnt == 0) {
+ puts("Error: no input WAV is specified");
+ return 0;
+ }
+
+ /* Initialialize */
+ CHECK( pj_init() );
+ CHECK( pjlib_util_init() );
+ pj_caching_pool_init(&cp, NULL, 0);
+ CHECK( pjmedia_endpt_create(&cp.factory, NULL, 1, &med_ept) );
+
+ pool = pj_pool_create(&cp.factory, "mix", 1000, 1000, NULL);
+
+ /* Create the bridge */
+ CHECK( pjmedia_conf_create(pool, MAX_WAV+4, clock_rate, 1,
+ clock_rate * PTIME / 1000, 16,
+ PJMEDIA_CONF_NO_DEVICE, &conf) );
+
+ /* Create the WAV output */
+ CHECK( pjmedia_wav_writer_port_create(pool, out_fname, clock_rate, 1,
+ clock_rate * PTIME / 1000,
+ 16, 0, 0, &wavout) );
+
+ /* Create and register each WAV input to the bridge */
+ for (i=0; i<input_cnt; ++i) {
+ pj_ssize_t len;
+
+ CHECK( pjmedia_wav_player_port_create(pool, wav_input[i].fname, 20,
+ PJMEDIA_FILE_NO_LOOP, 0,
+ &wav_input[i].port) );
+ len = pjmedia_wav_player_get_len(wav_input[i].port);
+ len = (pj_ssize_t)(len * 1.0 * clock_rate /
+ PJMEDIA_PIA_SRATE(&wav_input[i].port->info));
+ if (len > (pj_ssize_t)longest)
+ longest = len;
+
+ CHECK( pjmedia_conf_add_port(conf, pool, wav_input[i].port,
+ NULL, &wav_input[i].slot));
+
+ CHECK( pjmedia_conf_connect_port(conf, wav_input[i].slot, 0, 0) );
+ }
+
+ /* Loop reading frame from the bridge and write it to WAV */
+ processed = 0;
+ while (processed < longest + clock_rate * APPEND * 2 / 1000) {
+ pj_int16_t framebuf[PTIME * 48000 / 1000];
+ pjmedia_port *cp = pjmedia_conf_get_master_port(conf);
+ pjmedia_frame frame;
+
+ frame.buf = framebuf;
+ frame.size = PJMEDIA_PIA_SPF(&cp->info) * 2;
+ pj_assert(frame.size <= sizeof(framebuf));
+
+ CHECK( pjmedia_port_get_frame(cp, &frame) );
+
+ if (frame.type != PJMEDIA_FRAME_TYPE_AUDIO) {
+ pj_bzero(frame.buf, frame.size);
+ frame.type = PJMEDIA_FRAME_TYPE_AUDIO;
+ }
+
+ CHECK( pjmedia_port_put_frame(wavout, &frame));
+
+ processed += frame.size;
+ }
+
+ PJ_LOG(3,(THIS_FILE, "Done. Output duration: %d.%03d",
+ (processed >> 2)/clock_rate,
+ ((processed >> 2)*1000/clock_rate) % 1000));
+
+ /* Shutdown everything */
+ CHECK( pjmedia_port_destroy(wavout) );
+ for (i=0; i<input_cnt; ++i) {
+ CHECK( pjmedia_conf_remove_port(conf, wav_input[i].slot) );
+ CHECK( pjmedia_port_destroy(wav_input[i].port) );
+ }
+
+ CHECK(pjmedia_conf_destroy(conf));
+ CHECK(pjmedia_endpt_destroy(med_ept));
+
+ pj_pool_release(pool);
+ pj_caching_pool_destroy(&cp);
+ pj_shutdown();
+
+ return 0;
+}
+
diff --git a/pjsip-apps/src/samples/pcaputil.c b/pjsip-apps/src/samples/pcaputil.c
new file mode 100644
index 0000000..1c26484
--- /dev/null
+++ b/pjsip-apps/src/samples/pcaputil.c
@@ -0,0 +1,540 @@
+/* $Id: pcaputil.c 3841 2011-10-24 09:28:13Z ming $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <pjlib.h>
+#include <pjlib-util.h>
+#include <pjmedia.h>
+#include <pjmedia-codec.h>
+
+static const char *USAGE =
+"pcaputil [options] INPUT OUTPUT\n"
+"\n"
+" Convert captured RTP packets in PCAP file to WAV file or play it\n"
+" to audio device.\n"
+"\n"
+" INPUT is the PCAP file name/path.\n"
+" OUTPUT is the WAV file name/path to store the output, or set to \"-\",\n"
+" to play the output to audio device. The program will decode\n"
+" the RTP contents using codec that is available in PJMEDIA,\n"
+" and optionally decrypt the content using the SRTP crypto and\n"
+" keys below.\n"
+"\n"
+"Options to filter packets from PCAP file:\n"
+"(you can always select the relevant packets from Wireshark of course!)\n"
+" --src-ip=IP Only include packets from this source address\n"
+" --dst-ip=IP Only include packets destined to this address\n"
+" --src-port=port Only include packets from this source port number\n"
+" --dst-port=port Only include packets destined to this port number\n"
+"\n"
+"Options for RTP packet processing:\n"
+""
+" --codec=codec_id The codec ID formatted \"name/clock-rate/channel-count\"\n"
+" must be specified for codec with dynamic PT,\n"
+" e.g: \"Speex/8000\"\n"
+" --srtp-crypto=TAG, -c Set crypto to be used to decrypt SRTP packets. Valid\n"
+" tags are: \n"
+" AES_CM_128_HMAC_SHA1_80 \n"
+" AES_CM_128_HMAC_SHA1_32\n"
+" --srtp-key=KEY, -k Set the base64 key to decrypt SRTP packets.\n"
+"\n"
+"Options for playing to audio device:\n"
+""
+" --play-dev-id=dev_id Audio device ID for playback.\n"
+"\n"
+" Example:\n"
+" pcaputil file.pcap output.wav\n"
+" pcaputil -c AES_CM_128_HMAC_SHA1_80 \\\n"
+" -k VLDONbsbGl2Puqy+0PV7w/uGfpSPKFevDpxGsxN3 \\\n"
+" file.pcap output.wav\n"
+"\n"
+;
+
+static struct app
+{
+ pj_caching_pool cp;
+ pj_pool_t *pool;
+ pjmedia_endpt *mept;
+ pj_pcap_file *pcap;
+ pjmedia_port *wav;
+ pjmedia_codec *codec;
+ pjmedia_aud_stream *aud_strm;
+ unsigned pt;
+ pjmedia_transport *srtp;
+ pjmedia_rtp_session rtp_sess;
+ pj_bool_t rtp_sess_init;
+} app;
+
+
+static void cleanup()
+{
+ if (app.srtp) pjmedia_transport_close(app.srtp);
+ if (app.wav) {
+ pj_ssize_t pos = pjmedia_wav_writer_port_get_pos(app.wav);
+ if (pos >= 0) {
+ unsigned msec;
+ msec = pos / 2 * 1000 / PJMEDIA_PIA_SRATE(&app.wav->info);
+ printf("Written: %dm:%02ds.%03d\n",
+ msec / 1000 / 60,
+ (msec / 1000) % 60,
+ msec % 1000);
+ }
+ pjmedia_port_destroy(app.wav);
+ }
+ if (app.pcap) pj_pcap_close(app.pcap);
+ if (app.codec) {
+ pjmedia_codec_mgr *cmgr;
+ pjmedia_codec_close(app.codec);
+ cmgr = pjmedia_endpt_get_codec_mgr(app.mept);
+ pjmedia_codec_mgr_dealloc_codec(cmgr, app.codec);
+ }
+ if (app.aud_strm) {
+ pjmedia_aud_stream_stop(app.aud_strm);
+ pjmedia_aud_stream_destroy(app.aud_strm);
+ }
+ if (app.mept) pjmedia_endpt_destroy(app.mept);
+ if (app.pool) pj_pool_release(app.pool);
+ pj_caching_pool_destroy(&app.cp);
+ pj_shutdown();
+}
+
+static void err_exit(const char *title, pj_status_t status)
+{
+ if (status != PJ_SUCCESS) {
+ char errmsg[PJ_ERR_MSG_SIZE];
+ pj_strerror(status, errmsg, sizeof(errmsg));
+ printf("Error: %s: %s\n", title, errmsg);
+ } else {
+ printf("Error: %s\n", title);
+ }
+ cleanup();
+ exit(1);
+}
+
+#define T(op) do { \
+ status = op; \
+ if (status != PJ_SUCCESS) \
+ err_exit(#op, status); \
+ } while (0)
+
+
+static void read_rtp(pj_uint8_t *buf, pj_size_t bufsize,
+ pjmedia_rtp_hdr **rtp,
+ pj_uint8_t **payload,
+ unsigned *payload_size,
+ pj_bool_t check_pt)
+{
+ pj_status_t status;
+
+ /* Init RTP session */
+ if (!app.rtp_sess_init) {
+ T(pjmedia_rtp_session_init(&app.rtp_sess, 0, 0));
+ app.rtp_sess_init = PJ_TRUE;
+ }
+
+ /* Loop reading until we have a good RTP packet */
+ for (;;) {
+ pj_size_t sz = bufsize;
+ const pjmedia_rtp_hdr *r;
+ const void *p;
+ pjmedia_rtp_status seq_st;
+
+ status = pj_pcap_read_udp(app.pcap, NULL, buf, &sz);
+ if (status != PJ_SUCCESS)
+ err_exit("Error reading PCAP file", status);
+
+ /* Decode RTP packet to make sure that this is an RTP packet.
+ * We will decode it again to get the payload after we do
+ * SRTP decoding
+ */
+ status = pjmedia_rtp_decode_rtp(&app.rtp_sess, buf, sz, &r,
+ &p, payload_size);
+ if (status != PJ_SUCCESS) {
+ char errmsg[PJ_ERR_MSG_SIZE];
+ pj_strerror(status, errmsg, sizeof(errmsg));
+ printf("Not RTP packet, skipping packet: %s\n", errmsg);
+ continue;
+ }
+
+ /* Decrypt SRTP */
+#if PJMEDIA_HAS_SRTP
+ if (app.srtp) {
+ int len = sz;
+ status = pjmedia_transport_srtp_decrypt_pkt(app.srtp, PJ_TRUE,
+ buf, &len);
+ if (status != PJ_SUCCESS) {
+ char errmsg[PJ_ERR_MSG_SIZE];
+ pj_strerror(status, errmsg, sizeof(errmsg));
+ printf("SRTP packet decryption failed, skipping packet: %s\n",
+ errmsg);
+ continue;
+ }
+ sz = len;
+
+ /* Decode RTP packet again */
+ status = pjmedia_rtp_decode_rtp(&app.rtp_sess, buf, sz, &r,
+ &p, payload_size);
+ if (status != PJ_SUCCESS) {
+ char errmsg[PJ_ERR_MSG_SIZE];
+ pj_strerror(status, errmsg, sizeof(errmsg));
+ printf("Not RTP packet, skipping packet: %s\n", errmsg);
+ continue;
+ }
+ }
+#endif
+
+ /* Update RTP session */
+ pjmedia_rtp_session_update2(&app.rtp_sess, r, &seq_st, PJ_FALSE);
+
+ /* Skip out-of-order packet */
+ if (seq_st.diff == 0) {
+ printf("Skipping out of order packet\n");
+ continue;
+ }
+
+ /* Skip if payload type is different */
+ if (check_pt && r->pt != app.pt) {
+ printf("Skipping RTP packet with bad payload type\n");
+ continue;
+ }
+
+ /* Skip bad packet */
+ if (seq_st.status.flag.bad) {
+ printf("Skipping bad RTP\n");
+ continue;
+ }
+
+
+ *rtp = (pjmedia_rtp_hdr*)r;
+ *payload = (pj_uint8_t*)p;
+
+ /* We have good packet */
+ break;
+ }
+}
+
+pjmedia_frame play_frm;
+static pj_bool_t play_frm_copied, play_frm_ready;
+
+static pj_status_t wait_play(pjmedia_frame *f)
+{
+ play_frm_copied = PJ_FALSE;
+ play_frm = *f;
+ play_frm_ready = PJ_TRUE;
+ while (!play_frm_copied) {
+ pj_thread_sleep(1);
+ }
+ play_frm_ready = PJ_FALSE;
+
+ return PJ_SUCCESS;
+}
+
+static pj_status_t play_cb(void *user_data, pjmedia_frame *f)
+{
+ PJ_UNUSED_ARG(user_data);
+
+ if (!play_frm_ready) {
+ PJ_LOG(3, ("play_cb()", "Warning! Play frame not ready"));
+ return PJ_SUCCESS;
+ }
+
+ pj_memcpy(f->buf, play_frm.buf, play_frm.size);
+ f->size = play_frm.size;
+
+ play_frm_copied = PJ_TRUE;
+ return PJ_SUCCESS;
+}
+
+static void pcap2wav(const pj_str_t *codec,
+ const pj_str_t *wav_filename,
+ pjmedia_aud_dev_index dev_id,
+ const pj_str_t *srtp_crypto,
+ const pj_str_t *srtp_key)
+{
+ const pj_str_t WAV = {".wav", 4};
+ struct pkt
+ {
+ pj_uint8_t buffer[320];
+ pjmedia_rtp_hdr *rtp;
+ pj_uint8_t *payload;
+ unsigned payload_len;
+ } pkt0;
+ pjmedia_codec_mgr *cmgr;
+ const pjmedia_codec_info *ci;
+ pjmedia_codec_param param;
+ unsigned samples_per_frame;
+ pj_status_t status;
+
+ /* Initialize all codecs */
+ T( pjmedia_codec_register_audio_codecs(app.mept, NULL) );
+
+ /* Create SRTP transport is needed */
+#if PJMEDIA_HAS_SRTP
+ if (srtp_crypto->slen) {
+ pjmedia_srtp_crypto crypto;
+
+ pj_bzero(&crypto, sizeof(crypto));
+ crypto.key = *srtp_key;
+ crypto.name = *srtp_crypto;
+ T( pjmedia_transport_srtp_create(app.mept, NULL, NULL, &app.srtp) );
+ T( pjmedia_transport_srtp_start(app.srtp, &crypto, &crypto) );
+ }
+#else
+ PJ_UNUSED_ARG(srtp_crypto);
+ PJ_UNUSED_ARG(srtp_key);
+#endif
+
+ /* Read first packet */
+ read_rtp(pkt0.buffer, sizeof(pkt0.buffer), &pkt0.rtp,
+ &pkt0.payload, &pkt0.payload_len, PJ_FALSE);
+
+ cmgr = pjmedia_endpt_get_codec_mgr(app.mept);
+
+ /* Get codec info and param for the specified payload type */
+ app.pt = pkt0.rtp->pt;
+ if (app.pt >=0 && app.pt < 96) {
+ T( pjmedia_codec_mgr_get_codec_info(cmgr, pkt0.rtp->pt, &ci) );
+ } else {
+ unsigned cnt = 2;
+ const pjmedia_codec_info *info[2];
+ T( pjmedia_codec_mgr_find_codecs_by_id(cmgr, codec, &cnt,
+ info, NULL) );
+ if (cnt != 1)
+ err_exit("Codec ID must be specified and unique!", 0);
+
+ ci = info[0];
+ }
+ T( pjmedia_codec_mgr_get_default_param(cmgr, ci, &param) );
+
+ /* Alloc and init codec */
+ T( pjmedia_codec_mgr_alloc_codec(cmgr, ci, &app.codec) );
+ T( pjmedia_codec_init(app.codec, app.pool) );
+ T( pjmedia_codec_open(app.codec, &param) );
+
+ /* Init audio device or WAV file */
+ samples_per_frame = ci->clock_rate * param.info.frm_ptime / 1000;
+ if (pj_strcmp2(wav_filename, "-") == 0) {
+ pjmedia_aud_param aud_param;
+
+ /* Open audio device */
+ T( pjmedia_aud_dev_default_param(dev_id, &aud_param) );
+ aud_param.dir = PJMEDIA_DIR_PLAYBACK;
+ aud_param.channel_count = ci->channel_cnt;
+ aud_param.clock_rate = ci->clock_rate;
+ aud_param.samples_per_frame = samples_per_frame;
+ T( pjmedia_aud_stream_create(&aud_param, NULL, &play_cb,
+ NULL, &app.aud_strm) );
+ T( pjmedia_aud_stream_start(app.aud_strm) );
+ } else if (pj_stristr(wav_filename, &WAV)) {
+ /* Open WAV file */
+ T( pjmedia_wav_writer_port_create(app.pool, wav_filename->ptr,
+ ci->clock_rate, ci->channel_cnt,
+ samples_per_frame,
+ param.info.pcm_bits_per_sample, 0, 0,
+ &app.wav) );
+ } else {
+ err_exit("invalid output file", PJ_EINVAL);
+ }
+
+ /* Loop reading PCAP and writing WAV file */
+ for (;;) {
+ struct pkt pkt1;
+ pj_timestamp ts;
+ pjmedia_frame frames[16], pcm_frame;
+ short pcm[320];
+ unsigned i, frame_cnt;
+ long samples_cnt, ts_gap;
+
+ pj_assert(sizeof(pcm) >= samples_per_frame);
+
+ /* Parse first packet */
+ ts.u64 = 0;
+ frame_cnt = PJ_ARRAY_SIZE(frames);
+ T( pjmedia_codec_parse(app.codec, pkt0.payload, pkt0.payload_len,
+ &ts, &frame_cnt, frames) );
+
+ /* Decode and write to WAV file */
+ samples_cnt = 0;
+ for (i=0; i<frame_cnt; ++i) {
+ pjmedia_frame pcm_frame;
+
+ pcm_frame.buf = pcm;
+ pcm_frame.size = samples_per_frame * 2;
+
+ T( pjmedia_codec_decode(app.codec, &frames[i], pcm_frame.size,
+ &pcm_frame) );
+ if (app.wav) {
+ T( pjmedia_port_put_frame(app.wav, &pcm_frame) );
+ }
+ if (app.aud_strm) {
+ T( wait_play(&pcm_frame) );
+ }
+ samples_cnt += samples_per_frame;
+ }
+
+ /* Read next packet */
+ read_rtp(pkt1.buffer, sizeof(pkt1.buffer), &pkt1.rtp,
+ &pkt1.payload, &pkt1.payload_len, PJ_TRUE);
+
+ /* Fill in the gap (if any) between pkt0 and pkt1 */
+ ts_gap = pj_ntohl(pkt1.rtp->ts) - pj_ntohl(pkt0.rtp->ts) -
+ samples_cnt;
+ while (ts_gap >= (long)samples_per_frame) {
+
+ pcm_frame.buf = pcm;
+ pcm_frame.size = samples_per_frame * 2;
+
+ if (app.codec->op->recover) {
+ T( pjmedia_codec_recover(app.codec, pcm_frame.size,
+ &pcm_frame) );
+ } else {
+ pj_bzero(pcm_frame.buf, pcm_frame.size);
+ }
+
+ if (app.wav) {
+ T( pjmedia_port_put_frame(app.wav, &pcm_frame) );
+ }
+ if (app.aud_strm) {
+ T( wait_play(&pcm_frame) );
+ }
+ ts_gap -= samples_per_frame;
+ }
+
+ /* Next */
+ pkt0 = pkt1;
+ pkt0.rtp = (pjmedia_rtp_hdr*)pkt0.buffer;
+ pkt0.payload = pkt0.buffer + (pkt1.payload - pkt1.buffer);
+ }
+}
+
+
+int main(int argc, char *argv[])
+{
+ pj_str_t input, output, srtp_crypto, srtp_key, codec;
+ pjmedia_aud_dev_index dev_id = PJMEDIA_AUD_DEFAULT_PLAYBACK_DEV;
+ pj_pcap_filter filter;
+ pj_status_t status;
+
+ enum {
+ OPT_SRC_IP = 1, OPT_DST_IP, OPT_SRC_PORT, OPT_DST_PORT,
+ OPT_CODEC, OPT_PLAY_DEV_ID
+ };
+ struct pj_getopt_option long_options[] = {
+ { "srtp-crypto", 1, 0, 'c' },
+ { "srtp-key", 1, 0, 'k' },
+ { "src-ip", 1, 0, OPT_SRC_IP },
+ { "dst-ip", 1, 0, OPT_DST_IP },
+ { "src-port", 1, 0, OPT_SRC_PORT },
+ { "dst-port", 1, 0, OPT_DST_PORT },
+ { "codec", 1, 0, OPT_CODEC },
+ { "play-dev-id", 1, 0, OPT_PLAY_DEV_ID },
+ { NULL, 0, 0, 0}
+ };
+ int c;
+ int option_index;
+ char key_bin[32];
+
+ srtp_crypto.slen = srtp_key.slen = 0;
+ codec.slen = 0;
+
+ pj_pcap_filter_default(&filter);
+ filter.link = PJ_PCAP_LINK_TYPE_ETH;
+ filter.proto = PJ_PCAP_PROTO_TYPE_UDP;
+
+ /* Parse arguments */
+ pj_optind = 0;
+ while((c=pj_getopt_long(argc,argv, "c:k:", long_options, &option_index))!=-1) {
+ switch (c) {
+ case 'c':
+ srtp_crypto = pj_str(pj_optarg);
+ break;
+ case 'k':
+ {
+ int key_len = sizeof(key_bin);
+ srtp_key = pj_str(pj_optarg);
+ if (pj_base64_decode(&srtp_key, (pj_uint8_t*)key_bin, &key_len)) {
+ puts("Error: invalid key");
+ return 1;
+ }
+ srtp_key.ptr = key_bin;
+ srtp_key.slen = key_len;
+ }
+ break;
+ case OPT_SRC_IP:
+ {
+ pj_str_t t = pj_str(pj_optarg);
+ pj_in_addr a = pj_inet_addr(&t);
+ filter.ip_src = a.s_addr;
+ }
+ break;
+ case OPT_DST_IP:
+ {
+ pj_str_t t = pj_str(pj_optarg);
+ pj_in_addr a = pj_inet_addr(&t);
+ filter.ip_dst = a.s_addr;
+ }
+ break;
+ case OPT_SRC_PORT:
+ filter.src_port = pj_htons((pj_uint16_t)atoi(pj_optarg));
+ break;
+ case OPT_DST_PORT:
+ filter.dst_port = pj_htons((pj_uint16_t)atoi(pj_optarg));
+ break;
+ case OPT_CODEC:
+ codec = pj_str(pj_optarg);
+ break;
+ case OPT_PLAY_DEV_ID:
+ dev_id = atoi(pj_optarg);
+ break;
+ default:
+ puts("Error: invalid option");
+ return 1;
+ }
+ }
+
+ if (pj_optind != argc - 2) {
+ puts(USAGE);
+ return 1;
+ }
+
+ if (!(srtp_crypto.slen) != !(srtp_key.slen)) {
+ puts("Error: both SRTP crypto and key must be specified");
+ puts(USAGE);
+ return 1;
+ }
+
+ input = pj_str(argv[pj_optind]);
+ output = pj_str(argv[pj_optind+1]);
+
+ T( pj_init() );
+
+ pj_caching_pool_init(&app.cp, NULL, 0);
+ app.pool = pj_pool_create(&app.cp.factory, "pcaputil", 1000, 1000, NULL);
+
+ T( pjlib_util_init() );
+ T( pjmedia_endpt_create(&app.cp.factory, NULL, 0, &app.mept) );
+
+ T( pj_pcap_open(app.pool, input.ptr, &app.pcap) );
+ T( pj_pcap_set_filter(app.pcap, &filter) );
+
+ pcap2wav(&codec, &output, dev_id, &srtp_crypto, &srtp_key);
+
+ cleanup();
+ return 0;
+}
+
diff --git a/pjsip-apps/src/samples/pjsip-perf.c b/pjsip-apps/src/samples/pjsip-perf.c
new file mode 100644
index 0000000..f1b7cb9
--- /dev/null
+++ b/pjsip-apps/src/samples/pjsip-perf.c
@@ -0,0 +1,1853 @@
+/* $Id: pjsip-perf.c 3664 2011-07-19 03:42:28Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+/**
+ * \page page_pjsip_perf_c Samples: SIP Performance Benchmark
+ *
+ * <b>pjsip-perf</b> is a complete program to measure the
+ * performance of PJSIP or other SIP endpoints. It consists of two
+ * parts:
+ * - the server, to respond incoming requests, and
+ * - the client, who actively submits requests and measure the
+ * performance of the server.
+ *
+ * Both server and client part can run simultaneously, to measure the
+ * performance when both endpoints are co-located in a single program.
+ *
+ * The server accepts both INVITE and non-INVITE requests.
+ * The server exports several different types of URL, which would
+ * control how the request would be handled by the server:
+ * - URL with "0" as the user part will be handled statelessly.
+ * It should not be used with INVITE method.
+ * - URL with "1" as the user part will be handled statefully.
+ * If the request is an INVITE request, INVITE transaction will
+ * be created and 200/OK response will be sent, along with a valid
+ * SDP body. However, the SDP is just a static text body, and
+ * is not a proper SDP generated by PJMEDIA.
+ * - URL with "2" as the user part is only meaningful for INVITE
+ * requests, as it would be handled <b>call-statefully</b> by the
+ * server. For this URL, the server also would generate SDP dynamically
+ * and perform a proper SDP negotiation for the incoming call.
+ * Also for every call, server will limit the call duration to
+ * 10 seconds, on which the call will be terminated if the client
+ * doesn't hangup the call.
+ *
+ *
+ *
+ * This file is pjsip-apps/src/samples/pjsip-perf.c
+ *
+ * \includelineno pjsip-perf.c
+ */
+
+/* Include all headers. */
+#include <pjsip.h>
+#include <pjmedia.h>
+#include <pjmedia-codec.h>
+#include <pjsip_ua.h>
+#include <pjsip_simple.h>
+#include <pjlib-util.h>
+#include <pjlib.h>
+#include <stdio.h>
+
+#if defined(PJ_WIN32) && PJ_WIN32!=0
+# include <windows.h>
+#endif
+
+#define THIS_FILE "pjsip-perf.c"
+#define DEFAULT_COUNT (pjsip_cfg()->tsx.max_count/2>10000?10000:pjsip_cfg()->tsx.max_count/2)
+#define JOB_WINDOW 1000
+#define TERMINATE_TSX(x,c)
+
+
+#ifndef CACHING_POOL_SIZE
+# define CACHING_POOL_SIZE (256*1024*1024)
+#endif
+
+
+/* Static message body for INVITE, when stateful processing is
+ * invoked (instead of call-stateful, where SDP is generated
+ * dynamically.
+ */
+static pj_str_t dummy_sdp_str =
+{
+ "v=0\r\n"
+ "o=- 3360842071 3360842071 IN IP4 192.168.0.68\r\n"
+ "s=pjmedia\r\n"
+ "c=IN IP4 192.168.0.68\r\n"
+ "t=0 0\r\n"
+ "m=audio 4000 RTP/AVP 0 8 3 103 102 101\r\n"
+ "a=rtcp:4001 IN IP4 192.168.0.68\r\n"
+ "a=rtpmap:103 speex/16000\r\n"
+ "a=rtpmap:102 speex/8000\r\n"
+ "a=rtpmap:3 GSM/8000\r\n"
+ "a=rtpmap:0 PCMU/8000\r\n"
+ "a=rtpmap:8 PCMA/8000\r\n"
+ "a=sendrecv\r\n"
+ "a=rtpmap:101 telephone-event/8000\r\n"
+ "a=fmtp:101 0-15\r\n",
+ 0
+};
+
+static pj_str_t mime_application = { "application", 11};
+static pj_str_t mime_sdp = {"sdp", 3};
+
+
+struct srv_state
+{
+ unsigned stateless_cnt;
+ unsigned stateful_cnt;
+ unsigned call_cnt;
+};
+
+
+struct app
+{
+ pj_caching_pool cp;
+ pj_pool_t *pool;
+ pj_bool_t use_tcp;
+ pj_str_t local_addr;
+ int local_port;
+ pjsip_endpoint *sip_endpt;
+ pjmedia_endpt *med_endpt;
+ pj_str_t local_uri;
+ pj_str_t local_contact;
+ unsigned skinfo_cnt;
+ pjmedia_sock_info skinfo[8];
+
+ pj_bool_t thread_quit;
+ unsigned thread_count;
+ pj_thread_t *thread[16];
+
+ pj_bool_t real_sdp;
+ pjmedia_sdp_session *dummy_sdp;
+
+ int log_level;
+
+ struct {
+ pjsip_method method;
+ pj_str_t dst_uri;
+ pj_bool_t stateless;
+ unsigned timeout;
+ unsigned job_count,
+ job_submitted,
+ job_finished,
+ job_window;
+ unsigned stat_max_window;
+ pj_time_val first_request;
+ pj_time_val requests_sent;
+ pj_time_val last_completion;
+ unsigned total_responses;
+ unsigned response_codes[800];
+ } client;
+
+ struct {
+ pj_bool_t send_trying;
+ pj_bool_t send_ringing;
+ unsigned delay;
+ struct srv_state prev_state;
+ struct srv_state cur_state;
+ } server;
+
+
+} app;
+
+struct call
+{
+ pjsip_inv_session *inv;
+ pj_timer_entry ans_timer;
+};
+
+
+static void app_perror(const char *sender, const char *title,
+ pj_status_t status)
+{
+ char errmsg[PJ_ERR_MSG_SIZE];
+
+ pj_strerror(status, errmsg, sizeof(errmsg));
+ PJ_LOG(1,(sender, "%s: %s [code=%d]", title, errmsg, status));
+}
+
+
+/**************************************************************************
+ * STATELESS SERVER
+ */
+static pj_bool_t mod_stateless_on_rx_request(pjsip_rx_data *rdata);
+
+/* Module to handle incoming requests statelessly.
+ */
+static pjsip_module mod_stateless_server =
+{
+ NULL, NULL, /* prev, next. */
+ { "mod-stateless-server", 20 }, /* Name. */
+ -1, /* Id */
+ PJSIP_MOD_PRIORITY_APPLICATION, /* Priority */
+ NULL, /* load() */
+ NULL, /* start() */
+ NULL, /* stop() */
+ NULL, /* unload() */
+ &mod_stateless_on_rx_request, /* on_rx_request() */
+ NULL, /* on_rx_response() */
+ NULL, /* on_tx_request. */
+ NULL, /* on_tx_response() */
+ NULL, /* on_tsx_state() */
+};
+
+
+static pj_bool_t mod_stateless_on_rx_request(pjsip_rx_data *rdata)
+{
+ const pj_str_t stateless_user = { "0", 1 };
+ pjsip_uri *uri;
+ pjsip_sip_uri *sip_uri;
+
+ uri = pjsip_uri_get_uri(rdata->msg_info.msg->line.req.uri);
+
+ /* Only want to receive SIP scheme */
+ if (!PJSIP_URI_SCHEME_IS_SIP(uri))
+ return PJ_FALSE;
+
+ sip_uri = (pjsip_sip_uri*) uri;
+
+ /* Check for matching user part */
+ if (pj_strcmp(&sip_uri->user, &stateless_user)!=0)
+ return PJ_FALSE;
+
+ /*
+ * Yes, this is for us.
+ */
+
+ /* Ignore ACK request */
+ if (rdata->msg_info.msg->line.req.method.id == PJSIP_ACK_METHOD)
+ return PJ_TRUE;
+
+ /*
+ * Respond statelessly with 200/OK.
+ */
+ pjsip_endpt_respond_stateless(app.sip_endpt, rdata, 200, NULL,
+ NULL, NULL);
+ app.server.cur_state.stateless_cnt++;
+ return PJ_TRUE;
+}
+
+
+/**************************************************************************
+ * STATEFUL SERVER
+ */
+static pj_bool_t mod_stateful_on_rx_request(pjsip_rx_data *rdata);
+
+/* Module to handle incoming requests statefully.
+ */
+static pjsip_module mod_stateful_server =
+{
+ NULL, NULL, /* prev, next. */
+ { "mod-stateful-server", 19 }, /* Name. */
+ -1, /* Id */
+ PJSIP_MOD_PRIORITY_APPLICATION, /* Priority */
+ NULL, /* load() */
+ NULL, /* start() */
+ NULL, /* stop() */
+ NULL, /* unload() */
+ &mod_stateful_on_rx_request, /* on_rx_request() */
+ NULL, /* on_rx_response() */
+ NULL, /* on_tx_request. */
+ NULL, /* on_tx_response() */
+ NULL, /* on_tsx_state() */
+};
+
+
+static pj_bool_t mod_stateful_on_rx_request(pjsip_rx_data *rdata)
+{
+ const pj_str_t stateful_user = { "1", 1 };
+ pjsip_uri *uri;
+ pjsip_sip_uri *sip_uri;
+
+ uri = pjsip_uri_get_uri(rdata->msg_info.msg->line.req.uri);
+
+ /* Only want to receive SIP scheme */
+ if (!PJSIP_URI_SCHEME_IS_SIP(uri))
+ return PJ_FALSE;
+
+ sip_uri = (pjsip_sip_uri*) uri;
+
+ /* Check for matching user part */
+ if (pj_strcmp(&sip_uri->user, &stateful_user)!=0)
+ return PJ_FALSE;
+
+ /*
+ * Yes, this is for us.
+ * Respond statefully with 200/OK.
+ */
+ switch (rdata->msg_info.msg->line.req.method.id) {
+ case PJSIP_INVITE_METHOD:
+ {
+ pjsip_msg_body *body;
+
+ if (dummy_sdp_str.slen == 0)
+ dummy_sdp_str.slen = pj_ansi_strlen(dummy_sdp_str.ptr);
+
+ body = pjsip_msg_body_create(rdata->tp_info.pool,
+ &mime_application, &mime_sdp,
+ &dummy_sdp_str);
+ pjsip_endpt_respond(app.sip_endpt, &mod_stateful_server, rdata,
+ 200, NULL, NULL, body, NULL);
+ }
+ break;
+ case PJSIP_ACK_METHOD:
+ return PJ_TRUE;
+ default:
+ pjsip_endpt_respond(app.sip_endpt, &mod_stateful_server, rdata,
+ 200, NULL, NULL, NULL, NULL);
+ break;
+ }
+
+ app.server.cur_state.stateful_cnt++;
+ return PJ_TRUE;
+}
+
+
+/**************************************************************************
+ * CALL SERVER
+ */
+static pj_bool_t mod_call_on_rx_request(pjsip_rx_data *rdata);
+
+/* Module to handle incoming requests callly.
+ */
+static pjsip_module mod_call_server =
+{
+ NULL, NULL, /* prev, next. */
+ { "mod-call-server", 15 }, /* Name. */
+ -1, /* Id */
+ PJSIP_MOD_PRIORITY_APPLICATION, /* Priority */
+ NULL, /* load() */
+ NULL, /* start() */
+ NULL, /* stop() */
+ NULL, /* unload() */
+ &mod_call_on_rx_request, /* on_rx_request() */
+ NULL, /* on_rx_response() */
+ NULL, /* on_tx_request. */
+ NULL, /* on_tx_response() */
+ NULL, /* on_tsx_state() */
+};
+
+
+static pj_status_t send_response(pjsip_inv_session *inv,
+ pjsip_rx_data *rdata,
+ int code,
+ pj_bool_t *has_initial)
+{
+ pjsip_tx_data *tdata;
+ pj_status_t status;
+
+ if (*has_initial) {
+ status = pjsip_inv_answer(inv, code, NULL, NULL, &tdata);
+ } else {
+ status = pjsip_inv_initial_answer(inv, rdata, code,
+ NULL, NULL, &tdata);
+ }
+
+ if (status != PJ_SUCCESS) {
+ if (*has_initial) {
+ status = pjsip_inv_answer(inv, PJSIP_SC_NOT_ACCEPTABLE,
+ NULL, NULL, &tdata);
+ } else {
+ status = pjsip_inv_initial_answer(inv, rdata,
+ PJSIP_SC_NOT_ACCEPTABLE,
+ NULL, NULL, &tdata);
+ }
+
+ if (status == PJ_SUCCESS) {
+ *has_initial = PJ_TRUE;
+ pjsip_inv_send_msg(inv, tdata);
+ } else {
+ pjsip_inv_terminate(inv, 500, PJ_FALSE);
+ return -1;
+ }
+ } else {
+ *has_initial = PJ_TRUE;
+
+ status = pjsip_inv_send_msg(inv, tdata);
+ if (status != PJ_SUCCESS) {
+ pjsip_tx_data_dec_ref(tdata);
+ return status;
+ }
+ }
+
+ return status;
+}
+
+static void answer_timer_cb(pj_timer_heap_t *h, pj_timer_entry *entry)
+{
+ struct call *call = entry->user_data;
+ pj_bool_t has_initial = PJ_TRUE;
+
+ PJ_UNUSED_ARG(h);
+
+ entry->id = 0;
+ send_response(call->inv, NULL, 200, &has_initial);
+}
+
+static pj_bool_t mod_call_on_rx_request(pjsip_rx_data *rdata)
+{
+ const pj_str_t call_user = { "2", 1 };
+ pjsip_uri *uri;
+ pjsip_sip_uri *sip_uri;
+ struct call *call;
+ pjsip_dialog *dlg;
+ pjmedia_sdp_session *sdp;
+ pjsip_tx_data *tdata;
+ pj_bool_t has_initial = PJ_FALSE;
+ pj_status_t status;
+
+ uri = pjsip_uri_get_uri(rdata->msg_info.msg->line.req.uri);
+
+ /* Only want to receive SIP scheme */
+ if (!PJSIP_URI_SCHEME_IS_SIP(uri))
+ return PJ_FALSE;
+
+ sip_uri = (pjsip_sip_uri*) uri;
+
+ /* Only want to handle INVITE requests. */
+ if (rdata->msg_info.msg->line.req.method.id != PJSIP_INVITE_METHOD) {
+ return PJ_FALSE;
+ }
+
+
+ /* Check for matching user part. Incoming requests will be handled
+ * call-statefully if:
+ * - user part is "2", or
+ * - user part is not "0" nor "1" and method is INVITE.
+ */
+ if (pj_strcmp(&sip_uri->user, &call_user) == 0 ||
+ sip_uri->user.slen != 1 ||
+ (*sip_uri->user.ptr != '0' && *sip_uri->user.ptr != '1'))
+ {
+ /* Match */
+
+ } else {
+ return PJ_FALSE;
+ }
+
+
+ /* Verify that we can handle the request. */
+ if (app.real_sdp) {
+ unsigned options = 0;
+ status = pjsip_inv_verify_request(rdata, &options, NULL, NULL,
+ app.sip_endpt, &tdata);
+ if (status != PJ_SUCCESS) {
+
+ /*
+ * No we can't handle the incoming INVITE request.
+ */
+
+ if (tdata) {
+ pjsip_response_addr res_addr;
+
+ pjsip_get_response_addr(tdata->pool, rdata, &res_addr);
+ pjsip_endpt_send_response(app.sip_endpt, &res_addr, tdata,
+ NULL, NULL);
+
+ } else {
+
+ /* Respond with 500 (Internal Server Error) */
+ pjsip_endpt_respond_stateless(app.sip_endpt, rdata, 500, NULL,
+ NULL, NULL);
+ }
+
+ return PJ_TRUE;
+ }
+ }
+
+ /* Create UAS dialog */
+ status = pjsip_dlg_create_uas( pjsip_ua_instance(), rdata,
+ &app.local_contact, &dlg);
+ if (status != PJ_SUCCESS) {
+ const pj_str_t reason = pj_str("Unable to create dialog");
+ pjsip_endpt_respond_stateless( app.sip_endpt, rdata,
+ 500, &reason,
+ NULL, NULL);
+ return PJ_TRUE;
+ }
+
+ /* Alloc call structure. */
+ call = pj_pool_zalloc(dlg->pool, sizeof(struct call));
+
+ /* Create SDP from PJMEDIA */
+ if (app.real_sdp) {
+ status = pjmedia_endpt_create_sdp(app.med_endpt, rdata->tp_info.pool,
+ app.skinfo_cnt, app.skinfo,
+ &sdp);
+ } else {
+ sdp = app.dummy_sdp;
+ }
+
+ /* Create UAS invite session */
+ status = pjsip_inv_create_uas( dlg, rdata, sdp, 0, &call->inv);
+ if (status != PJ_SUCCESS) {
+ pjsip_dlg_create_response(dlg, rdata, 500, NULL, &tdata);
+ pjsip_dlg_send_response(dlg, pjsip_rdata_get_tsx(rdata), tdata);
+ return PJ_TRUE;
+ }
+
+ /* Send 100/Trying if needed */
+ if (app.server.send_trying) {
+ status = send_response(call->inv, rdata, 100, &has_initial);
+ if (status != PJ_SUCCESS)
+ return PJ_TRUE;
+ }
+
+ /* Send 180/Ringing if needed */
+ if (app.server.send_ringing) {
+ status = send_response(call->inv, rdata, 180, &has_initial);
+ if (status != PJ_SUCCESS)
+ return PJ_TRUE;
+ }
+
+ /* Simulate call processing delay */
+ if (app.server.delay) {
+ pj_time_val delay;
+
+ call->ans_timer.id = 1;
+ call->ans_timer.user_data = call;
+ call->ans_timer.cb = &answer_timer_cb;
+
+ delay.sec = 0;
+ delay.msec = app.server.delay;
+ pj_time_val_normalize(&delay);
+
+ pjsip_endpt_schedule_timer(app.sip_endpt, &call->ans_timer, &delay);
+
+ } else {
+ /* Send the 200 response immediately . */
+ status = send_response(call->inv, rdata, 200, &has_initial);
+ PJ_ASSERT_ON_FAIL(status == PJ_SUCCESS, return PJ_TRUE);
+ }
+
+ /* Done */
+ app.server.cur_state.call_cnt++;
+
+ return PJ_TRUE;
+}
+
+
+
+/**************************************************************************
+ * Default handler when incoming request is not handled by any other
+ * modules.
+ */
+static pj_bool_t mod_responder_on_rx_request(pjsip_rx_data *rdata);
+
+/* Module to handle incoming requests statelessly.
+ */
+static pjsip_module mod_responder =
+{
+ NULL, NULL, /* prev, next. */
+ { "mod-responder", 13 }, /* Name. */
+ -1, /* Id */
+ PJSIP_MOD_PRIORITY_APPLICATION+1, /* Priority */
+ NULL, /* load() */
+ NULL, /* start() */
+ NULL, /* stop() */
+ NULL, /* unload() */
+ &mod_responder_on_rx_request, /* on_rx_request() */
+ NULL, /* on_rx_response() */
+ NULL, /* on_tx_request. */
+ NULL, /* on_tx_response() */
+ NULL, /* on_tsx_state() */
+};
+
+
+static pj_bool_t mod_responder_on_rx_request(pjsip_rx_data *rdata)
+{
+ const pj_str_t reason = pj_str("Not expecting request at this URI");
+
+ /*
+ * Respond any requests (except ACK!) with 500.
+ */
+ if (rdata->msg_info.msg->line.req.method.id != PJSIP_ACK_METHOD) {
+ pjsip_endpt_respond_stateless(app.sip_endpt, rdata, 500, &reason,
+ NULL, NULL);
+ }
+
+ return PJ_TRUE;
+}
+
+
+
+/*****************************************************************************
+ * Below is a simple module to log all incoming and outgoing SIP messages
+ */
+
+
+/* Notification on incoming messages */
+static pj_bool_t logger_on_rx_msg(pjsip_rx_data *rdata)
+{
+ PJ_LOG(3,(THIS_FILE, "RX %d bytes %s from %s %s:%d:\n"
+ "%.*s\n"
+ "--end msg--",
+ rdata->msg_info.len,
+ pjsip_rx_data_get_info(rdata),
+ rdata->tp_info.transport->type_name,
+ rdata->pkt_info.src_name,
+ rdata->pkt_info.src_port,
+ (int)rdata->msg_info.len,
+ rdata->msg_info.msg_buf));
+
+ /* Always return false, otherwise messages will not get processed! */
+ return PJ_FALSE;
+}
+
+/* Notification on outgoing messages */
+static pj_status_t logger_on_tx_msg(pjsip_tx_data *tdata)
+{
+
+ /* Important note:
+ * tp_info field is only valid after outgoing messages has passed
+ * transport layer. So don't try to access tp_info when the module
+ * has lower priority than transport layer.
+ */
+
+ PJ_LOG(3,(THIS_FILE, "TX %d bytes %s to %s %s:%d:\n"
+ "%.*s\n"
+ "--end msg--",
+ (tdata->buf.cur - tdata->buf.start),
+ pjsip_tx_data_get_info(tdata),
+ tdata->tp_info.transport->type_name,
+ tdata->tp_info.dst_name,
+ tdata->tp_info.dst_port,
+ (int)(tdata->buf.cur - tdata->buf.start),
+ tdata->buf.start));
+
+ /* Always return success, otherwise message will not get sent! */
+ return PJ_SUCCESS;
+}
+
+/* The module instance. */
+static pjsip_module msg_logger =
+{
+ NULL, NULL, /* prev, next. */
+ { "mod-siprtp-log", 14 }, /* Name. */
+ -1, /* Id */
+ PJSIP_MOD_PRIORITY_TRANSPORT_LAYER-1,/* Priority */
+ NULL, /* load() */
+ NULL, /* start() */
+ NULL, /* stop() */
+ NULL, /* unload() */
+ &logger_on_rx_msg, /* on_rx_request() */
+ &logger_on_rx_msg, /* on_rx_response() */
+ &logger_on_tx_msg, /* on_tx_request. */
+ &logger_on_tx_msg, /* on_tx_response() */
+ NULL, /* on_tsx_state() */
+
+};
+
+
+
+/**************************************************************************
+ * Test Client.
+ */
+
+static pj_bool_t mod_test_on_rx_response(pjsip_rx_data *rdata);
+
+static void call_on_media_update( pjsip_inv_session *inv,
+ pj_status_t status);
+static void call_on_state_changed( pjsip_inv_session *inv,
+ pjsip_event *e);
+static void call_on_forked(pjsip_inv_session *inv, pjsip_event *e);
+
+
+/* Module to handle incoming requests callly.
+ */
+static pjsip_module mod_test =
+{
+ NULL, NULL, /* prev, next. */
+ { "mod-test", 8 }, /* Name. */
+ -1, /* Id */
+ PJSIP_MOD_PRIORITY_APPLICATION, /* Priority */
+ NULL, /* load() */
+ NULL, /* start() */
+ NULL, /* stop() */
+ NULL, /* unload() */
+ NULL, /* on_rx_request() */
+ &mod_test_on_rx_response, /* on_rx_response() */
+ NULL, /* on_tx_request. */
+ NULL, /* on_tx_response() */
+ NULL, /* on_tsx_state() */
+};
+
+
+static void report_completion(int status_code)
+{
+ app.client.job_finished++;
+ if (status_code >= 200 && status_code < 800)
+ app.client.response_codes[status_code]++;
+ app.client.total_responses++;
+ pj_gettimeofday(&app.client.last_completion);
+}
+
+
+/* Handler when response is received. */
+static pj_bool_t mod_test_on_rx_response(pjsip_rx_data *rdata)
+{
+ if (pjsip_rdata_get_tsx(rdata) == NULL) {
+ report_completion(rdata->msg_info.msg->line.status.code);
+ }
+
+ return PJ_TRUE;
+}
+
+
+/*
+ * Create app
+ */
+static pj_status_t create_app(void)
+{
+ pj_status_t status;
+
+ status = pj_init();
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Error initializing pjlib", status);
+ return status;
+ }
+
+ /* init PJLIB-UTIL: */
+ status = pjlib_util_init();
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+ /* Must create a pool factory before we can allocate any memory. */
+ pj_caching_pool_init(&app.cp, &pj_pool_factory_default_policy,
+ CACHING_POOL_SIZE);
+
+ /* Create application pool for misc. */
+ app.pool = pj_pool_create(&app.cp.factory, "app", 1000, 1000, NULL);
+
+ /* Create the endpoint: */
+ status = pjsip_endpt_create(&app.cp.factory, pj_gethostname()->ptr,
+ &app.sip_endpt);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+
+ return status;
+}
+
+
+/*
+ * Init SIP stack
+ */
+static pj_status_t init_sip()
+{
+ pj_status_t status = -1;
+
+ /* Add UDP/TCP transport. */
+ {
+ pj_sockaddr_in addr;
+ pjsip_host_port addrname;
+ const char *transport_type = NULL;
+
+ pj_bzero(&addr, sizeof(addr));
+ addr.sin_family = pj_AF_INET();
+ addr.sin_addr.s_addr = 0;
+ addr.sin_port = pj_htons((pj_uint16_t)app.local_port);
+
+ if (app.local_addr.slen) {
+ addrname.host = app.local_addr;
+ addrname.port = 5060;
+ }
+ if (app.local_port != 0)
+ addrname.port = app.local_port;
+
+ if (0) {
+#if defined(PJ_HAS_TCP) && PJ_HAS_TCP!=0
+ } else if (app.use_tcp) {
+ pj_sockaddr_in local_addr;
+ pjsip_tpfactory *tpfactory;
+
+ transport_type = "tcp";
+ pj_sockaddr_in_init(&local_addr, 0, (pj_uint16_t)app.local_port);
+ status = pjsip_tcp_transport_start(app.sip_endpt, &local_addr,
+ app.thread_count, &tpfactory);
+ if (status == PJ_SUCCESS) {
+ app.local_addr = tpfactory->addr_name.host;
+ app.local_port = tpfactory->addr_name.port;
+ }
+#endif
+ } else {
+ pjsip_transport *tp;
+
+ transport_type = "udp";
+ status = pjsip_udp_transport_start(app.sip_endpt, &addr,
+ (app.local_addr.slen ? &addrname:NULL),
+ app.thread_count, &tp);
+ if (status == PJ_SUCCESS) {
+ app.local_addr = tp->local_name.host;
+ app.local_port = tp->local_name.port;
+ }
+
+ }
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to start transport", status);
+ return status;
+ }
+
+ app.local_uri.ptr = pj_pool_alloc(app.pool, 128);
+ app.local_uri.slen = pj_ansi_sprintf(app.local_uri.ptr,
+ "<sip:pjsip-perf@%.*s:%d;transport=%s>",
+ (int)app.local_addr.slen,
+ app.local_addr.ptr,
+ app.local_port,
+ transport_type);
+
+ app.local_contact = app.local_uri;
+ }
+
+ /*
+ * Init transaction layer.
+ * This will create/initialize transaction hash tables etc.
+ */
+ status = pjsip_tsx_layer_init_module(app.sip_endpt);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+ /* Initialize UA layer. */
+ status = pjsip_ua_init_module( app.sip_endpt, NULL );
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+ /* Initialize 100rel support */
+ status = pjsip_100rel_init_module(app.sip_endpt);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+ /* Init invite session module. */
+ {
+ pjsip_inv_callback inv_cb;
+
+ /* Init the callback for INVITE session: */
+ pj_bzero(&inv_cb, sizeof(inv_cb));
+ inv_cb.on_state_changed = &call_on_state_changed;
+ inv_cb.on_new_session = &call_on_forked;
+ inv_cb.on_media_update = &call_on_media_update;
+
+ /* Initialize invite session module: */
+ status = pjsip_inv_usage_init(app.sip_endpt, &inv_cb);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+ }
+
+ /* Register our module to receive incoming requests. */
+ status = pjsip_endpt_register_module( app.sip_endpt, &mod_test);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+
+ /* Register stateless server module */
+ status = pjsip_endpt_register_module( app.sip_endpt, &mod_stateless_server);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+ /* Register default responder module */
+ status = pjsip_endpt_register_module( app.sip_endpt, &mod_responder);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+ /* Register stateless server module */
+ status = pjsip_endpt_register_module( app.sip_endpt, &mod_stateful_server);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+
+ /* Register call server module */
+ status = pjsip_endpt_register_module( app.sip_endpt, &mod_call_server);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+
+ /* Done */
+ return PJ_SUCCESS;
+}
+
+
+/*
+ * Destroy SIP
+ */
+static void destroy_app()
+{
+ unsigned i;
+
+ app.thread_quit = 1;
+ for (i=0; i<app.thread_count; ++i) {
+ if (app.thread[i]) {
+ pj_thread_join(app.thread[i]);
+ pj_thread_destroy(app.thread[i]);
+ app.thread[i] = NULL;
+ }
+ }
+
+ if (app.sip_endpt) {
+ pjsip_endpt_destroy(app.sip_endpt);
+ app.sip_endpt = NULL;
+ }
+
+ if (app.pool) {
+ pj_pool_release(app.pool);
+ app.pool = NULL;
+ PJ_LOG(3,(THIS_FILE, "Peak memory size: %uMB",
+ app.cp.peak_used_size / 1000000));
+ pj_caching_pool_destroy(&app.cp);
+ }
+
+ /* Shutdown PJLIB */
+ pj_shutdown();
+}
+
+
+/*
+ * Init media stack.
+ */
+static pj_status_t init_media()
+{
+ unsigned i;
+ pj_uint16_t rtp_port;
+ pj_status_t status;
+
+
+ /* Initialize media endpoint so that at least error subsystem is properly
+ * initialized.
+ */
+ status = pjmedia_endpt_create(&app.cp.factory,
+ pjsip_endpt_get_ioqueue(app.sip_endpt), 0,
+ &app.med_endpt);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+
+ /* Must register all codecs to be supported */
+ pjmedia_codec_register_audio_codecs(app.med_endpt, NULL);
+
+ /* Init dummy socket addresses */
+ app.skinfo_cnt = 0;
+ for (i=0, rtp_port=4000; i<PJ_ARRAY_SIZE(app.skinfo); ++i, rtp_port+=2) {
+ pjmedia_sock_info *skinfo;
+
+ skinfo = &app.skinfo[i];
+
+ pj_sockaddr_in_init(&skinfo->rtp_addr_name.ipv4, &app.local_addr,
+ (pj_uint16_t)rtp_port);
+ pj_sockaddr_in_init(&skinfo->rtp_addr_name.ipv4, &app.local_addr,
+ (pj_uint16_t)(rtp_port+1));
+ app.skinfo_cnt++;
+ }
+
+ /* Generate dummy SDP */
+ dummy_sdp_str.slen = pj_ansi_strlen(dummy_sdp_str.ptr);
+ status = pjmedia_sdp_parse(app.pool, dummy_sdp_str.ptr, dummy_sdp_str.slen,
+ &app.dummy_sdp);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Error parsing dummy SDP", status);
+ return status;
+ }
+
+
+ /* Done */
+ return PJ_SUCCESS;
+}
+
+
+/* This is notification from the call about media negotiation
+ * status. This is called for client calls only.
+ */
+static void call_on_media_update( pjsip_inv_session *inv,
+ pj_status_t status)
+{
+ if (status != PJ_SUCCESS) {
+ pjsip_tx_data *tdata;
+ pj_status_t status;
+
+ status = pjsip_inv_end_session(inv, PJSIP_SC_UNSUPPORTED_MEDIA_TYPE,
+ NULL, &tdata);
+ if (status == PJ_SUCCESS && tdata)
+ status = pjsip_inv_send_msg(inv, tdata);
+ }
+}
+
+
+/* This is notification from the call when the call state has changed.
+ * This is called for client calls only.
+ */
+static void call_on_state_changed( pjsip_inv_session *inv,
+ pjsip_event *e)
+{
+ PJ_UNUSED_ARG(e);
+
+ /* Bail out if the session has been counted before */
+ if (inv->mod_data[mod_test.id] != NULL)
+ return;
+
+ /* Bail out if this is not an outgoing call */
+ if (inv->role != PJSIP_UAC_ROLE)
+ return;
+
+ if (inv->state == PJSIP_INV_STATE_CONFIRMED) {
+ pjsip_tx_data *tdata;
+ pj_status_t status;
+
+ //report_completion(200);
+ //inv->mod_data[mod_test.id] = (void*)1;
+
+ status = pjsip_inv_end_session(inv, PJSIP_SC_OK, NULL, &tdata);
+ if (status == PJ_SUCCESS && tdata)
+ status = pjsip_inv_send_msg(inv, tdata);
+
+ } else if (inv->state == PJSIP_INV_STATE_DISCONNECTED) {
+ report_completion(inv->cause);
+ inv->mod_data[mod_test.id] = (void*)1;
+ }
+}
+
+
+/* Not implemented for now */
+static void call_on_forked(pjsip_inv_session *inv, pjsip_event *e)
+{
+ /* Do nothing */
+ PJ_UNUSED_ARG(inv);
+ PJ_UNUSED_ARG(e);
+}
+
+
+/*
+ * Make outgoing call.
+ */
+static pj_status_t make_call(const pj_str_t *dst_uri)
+{
+ struct call *call;
+ pjsip_dialog *dlg;
+ pjmedia_sdp_session *sdp;
+ pjsip_tx_data *tdata;
+ pj_status_t status;
+
+
+ /* Create UAC dialog */
+ status = pjsip_dlg_create_uac( pjsip_ua_instance(),
+ &app.local_uri, /* local URI */
+ &app.local_contact, /* local Contact */
+ dst_uri, /* remote URI */
+ dst_uri, /* remote target */
+ &dlg); /* dialog */
+ if (status != PJ_SUCCESS) {
+ return status;
+ }
+
+ /* Create call */
+ call = pj_pool_zalloc(dlg->pool, sizeof(struct call));
+
+ /* Create SDP */
+ if (app.real_sdp) {
+ status = pjmedia_endpt_create_sdp(app.med_endpt, dlg->pool, 1,
+ app.skinfo, &sdp);
+ if (status != PJ_SUCCESS) {
+ pjsip_dlg_terminate(dlg);
+ return status;
+ }
+ } else
+ sdp = app.dummy_sdp;
+
+ /* Create the INVITE session. */
+ status = pjsip_inv_create_uac( dlg, sdp, 0, &call->inv);
+ if (status != PJ_SUCCESS) {
+ pjsip_dlg_terminate(dlg);
+ return status;
+ }
+
+
+ /* Create initial INVITE request.
+ * This INVITE request will contain a perfectly good request and
+ * an SDP body as well.
+ */
+ status = pjsip_inv_invite(call->inv, &tdata);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+
+ /* Send initial INVITE request.
+ * From now on, the invite session's state will be reported to us
+ * via the invite session callbacks.
+ */
+ status = pjsip_inv_send_msg(call->inv, tdata);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+
+ return PJ_SUCCESS;
+}
+
+
+/*
+ * Verify that valid SIP url is given.
+ */
+static pj_status_t verify_sip_url(const char *c_url)
+{
+ pjsip_uri *p;
+ pj_pool_t *pool;
+ char *url;
+ int len = (c_url ? pj_ansi_strlen(c_url) : 0);
+
+ if (!len) return -1;
+
+ pool = pj_pool_create(&app.cp.factory, "check%p", 1024, 0, NULL);
+ if (!pool) return PJ_ENOMEM;
+
+ url = pj_pool_alloc(pool, len+1);
+ pj_ansi_strcpy(url, c_url);
+ url[len] = '\0';
+
+ p = pjsip_parse_uri(pool, url, len, 0);
+ if (!p || pj_stricmp2(pjsip_uri_get_scheme(p), "sip") != 0)
+ p = NULL;
+
+ pj_pool_release(pool);
+ return p ? 0 : -1;
+}
+
+
+static void usage(void)
+{
+ printf(
+ "Usage:\n"
+ " pjsip-perf [OPTIONS] -- to start as server\n"
+ " pjsip-perf [OPTIONS] URL -- to call server (possibly itself)\n"
+ "\n"
+ "where:\n"
+ " URL The SIP URL to be contacted.\n"
+ "\n"
+ "Client options:\n"
+ " --method=METHOD, -m Set test method (set to INVITE for call benchmark)\n"
+ " [default: OPTIONS]\n"
+ " --count=N, -n Set total number of requests to initiate\n"
+ " [default=%d]\n"
+ " --stateless, -s Set to operate in stateless mode\n"
+ " [default: stateful]\n"
+ " --timeout=SEC, -t Set client timeout [default=60 sec]\n"
+ " --window=COUNT, -w Set maximum outstanding job [default: %d]\n"
+ "\n"
+ "SDP options (client and server):\n"
+ " --real-sdp Generate real SDP from pjmedia, and also perform\n"
+ " proper SDP negotiation [default: dummy]\n"
+ "\n"
+ "Client and Server options:\n"
+ " --local-port=PORT, -p Set local port [default: 5060]\n"
+ " --use-tcp, -T Use TCP instead of UDP. Note that when started as\n"
+ " client, you must add ;transport=tcp parameter to URL\n"
+ " [default: no]\n"
+ " --thread-count=N Set number of worker threads [default=1]\n"
+ " --trying Send 100/Trying response (server, default no)\n"
+ " --ringing Send 180/Ringing response (server, default no)\n"
+ " --delay=MS, -d Delay answering call by MS (server, default no)\n"
+ "\n"
+ "Misc options:\n"
+ " --help, -h Display this screen\n"
+ " --verbose, -v Verbose logging (put more than once for even more)\n"
+ "\n"
+ "When started as server, pjsip-perf can be contacted on the following URIs:\n"
+ " - sip:0@server-addr To handle requests statelessly.\n"
+ " - sip:1@server-addr To handle requests statefully.\n"
+ " - sip:2@server-addr To handle INVITE call.\n",
+ DEFAULT_COUNT, JOB_WINDOW);
+}
+
+
+static int my_atoi(const char *s)
+{
+ pj_str_t ss = pj_str((char*)s);
+ return pj_strtoul(&ss);
+}
+
+
+static pj_status_t init_options(int argc, char *argv[])
+{
+ enum { OPT_THREAD_COUNT = 1, OPT_REAL_SDP, OPT_TRYING, OPT_RINGING };
+ struct pj_getopt_option long_options[] = {
+ { "local-port", 1, 0, 'p' },
+ { "count", 1, 0, 'c' },
+ { "thread-count", 1, 0, OPT_THREAD_COUNT },
+ { "method", 1, 0, 'm' },
+ { "help", 0, 0, 'h' },
+ { "stateless", 0, 0, 's' },
+ { "timeout", 1, 0, 't' },
+ { "real-sdp", 0, 0, OPT_REAL_SDP },
+ { "verbose", 0, 0, 'v' },
+ { "use-tcp", 0, 0, 'T' },
+ { "window", 1, 0, 'w' },
+ { "delay", 1, 0, 'd' },
+ { "trying", 0, 0, OPT_TRYING},
+ { "ringing", 0, 0, OPT_RINGING},
+ { NULL, 0, 0, 0 },
+ };
+ int c;
+ int option_index;
+
+ /* Init default application configs */
+ app.local_port = 5060;
+ app.thread_count = 1;
+ app.client.job_count = DEFAULT_COUNT;
+ app.client.method = *pjsip_get_options_method();
+ app.client.job_window = c = JOB_WINDOW;
+ app.client.timeout = 60;
+ app.log_level = 3;
+
+
+ /* Parse options */
+ pj_optind = 0;
+ while((c=pj_getopt_long(argc,argv, "p:c:m:t:w:d:hsv",
+ long_options, &option_index))!=-1)
+ {
+ switch (c) {
+ case 'p':
+ app.local_port = my_atoi(pj_optarg);
+ if (app.local_port < 0 || app.local_port > 65535) {
+ PJ_LOG(3,(THIS_FILE, "Invalid --local-port %s", pj_optarg));
+ return -1;
+ }
+ break;
+
+ case 'c':
+ app.client.job_count = my_atoi(pj_optarg);
+ if (app.client.job_count < 0) {
+ PJ_LOG(3,(THIS_FILE, "Invalid --local-port %s", pj_optarg));
+ return -1;
+ }
+ if (app.client.job_count > pjsip_cfg()->tsx.max_count)
+ PJ_LOG(3,(THIS_FILE,
+ "Warning: --count value (%d) exceeds maximum "
+ "transaction count (%d)", app.client.job_count,
+ pjsip_cfg()->tsx.max_count));
+ break;
+
+ case OPT_THREAD_COUNT:
+ app.thread_count = my_atoi(pj_optarg);
+ if (app.thread_count < 1 || app.thread_count > 16) {
+ PJ_LOG(3,(THIS_FILE, "Invalid --thread-count %s", pj_optarg));
+ return -1;
+ }
+ break;
+
+ case 'm':
+ {
+ pj_str_t temp = pj_str((char*)pj_optarg);
+ pjsip_method_init_np(&app.client.method, &temp);
+ }
+ break;
+
+ case 'h':
+ usage();
+ return -1;
+
+ case 's':
+ app.client.stateless = PJ_TRUE;
+ break;
+
+ case OPT_REAL_SDP:
+ app.real_sdp = 1;
+ break;
+
+ case 'v':
+ app.log_level++;
+ break;
+
+ case 't':
+ app.client.timeout = my_atoi(pj_optarg);
+ if (app.client.timeout < 0 || app.client.timeout > 600) {
+ PJ_LOG(3,(THIS_FILE, "Invalid --timeout %s", pj_optarg));
+ return -1;
+ }
+ break;
+
+ case 'w':
+ app.client.job_window = my_atoi(pj_optarg);
+ if (app.client.job_window <= 0) {
+ PJ_LOG(3,(THIS_FILE, "Invalid --window %s", pj_optarg));
+ return -1;
+ }
+ break;
+
+ case 'T':
+ app.use_tcp = PJ_TRUE;
+ break;
+
+ case 'd':
+ app.server.delay = my_atoi(pj_optarg);
+ if (app.server.delay > 3600) {
+ PJ_LOG(3,(THIS_FILE, "I think --delay %s is too long",
+ pj_optarg));
+ return -1;
+ }
+ break;
+
+ case OPT_TRYING:
+ app.server.send_trying = 1;
+ break;
+
+ case OPT_RINGING:
+ app.server.send_ringing = 1;
+ break;
+
+ default:
+ PJ_LOG(1,(THIS_FILE,
+ "Invalid argument. Use --help to see help"));
+ return -1;
+ }
+ }
+
+ if (pj_optind != argc) {
+
+ if (verify_sip_url(argv[pj_optind]) != PJ_SUCCESS) {
+ PJ_LOG(1,(THIS_FILE, "Invalid SIP URI %s", argv[pj_optind]));
+ return -1;
+ }
+ app.client.dst_uri = pj_str(argv[pj_optind]);
+
+ pj_optind++;
+
+ }
+
+ if (pj_optind != argc) {
+ PJ_LOG(1,(THIS_FILE, "Error: unknown options %s", argv[pj_optind]));
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/* Send one stateless request */
+static pj_status_t submit_stateless_job(void)
+{
+ pjsip_tx_data *tdata;
+ pj_status_t status;
+
+ status = pjsip_endpt_create_request(app.sip_endpt, &app.client.method,
+ &app.client.dst_uri, &app.local_uri,
+ &app.client.dst_uri, &app.local_contact,
+ NULL, -1, NULL, &tdata);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Error creating request", status);
+ report_completion(701);
+ return status;
+ }
+
+ status = pjsip_endpt_send_request_stateless(app.sip_endpt, tdata, NULL,
+ NULL);
+ if (status != PJ_SUCCESS) {
+ pjsip_tx_data_dec_ref(tdata);
+ app_perror(THIS_FILE, "Error sending stateless request", status);
+ report_completion(701);
+ return status;
+ }
+
+ return PJ_SUCCESS;
+}
+
+
+/* This callback is called when client transaction state has changed */
+static void tsx_completion_cb(void *token, pjsip_event *event)
+{
+ pjsip_transaction *tsx;
+
+ PJ_UNUSED_ARG(token);
+
+ if (event->type != PJSIP_EVENT_TSX_STATE)
+ return;
+
+ tsx = event->body.tsx_state.tsx;
+
+ if (tsx->mod_data[mod_test.id] != NULL) {
+ /* This transaction has been calculated before */
+ return;
+ }
+
+ if (tsx->state==PJSIP_TSX_STATE_TERMINATED) {
+ report_completion(tsx->status_code);
+ tsx->mod_data[mod_test.id] = (void*)1;
+ }
+ else if (tsx->method.id == PJSIP_INVITE_METHOD &&
+ tsx->state == PJSIP_TSX_STATE_CONFIRMED) {
+
+ report_completion(tsx->status_code);
+ tsx->mod_data[mod_test.id] = (void*)1;
+
+ } else if (tsx->state == PJSIP_TSX_STATE_COMPLETED) {
+
+ report_completion(tsx->status_code);
+ tsx->mod_data[mod_test.id] = (void*)1;
+
+ TERMINATE_TSX(tsx, tsx->status_code);
+ }
+}
+
+
+/* Send one stateful request */
+static pj_status_t submit_job(void)
+{
+ pjsip_tx_data *tdata;
+ pj_status_t status;
+
+ status = pjsip_endpt_create_request(app.sip_endpt, &app.client.method,
+ &app.client.dst_uri, &app.local_uri,
+ &app.client.dst_uri, &app.local_contact,
+ NULL, -1, NULL, &tdata);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Error creating request", status);
+ report_completion(701);
+ return status;
+ }
+
+ status = pjsip_endpt_send_request(app.sip_endpt, tdata, -1, NULL,
+ &tsx_completion_cb);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Error sending stateful request", status);
+ //should have been reported by tsx_completion_cb().
+ //report_completion(701);
+ //No longer necessary (r777)
+ //pjsip_tx_data_dec_ref(tdata);
+ }
+ return status;
+}
+
+
+/* Client worker thread */
+static int client_thread(void *arg)
+{
+ pj_time_val end_time, last_report, now;
+ unsigned thread_index = (unsigned)(long)arg;
+ unsigned cycle = 0, last_cycle = 0;
+
+ pj_thread_sleep(100);
+
+ pj_gettimeofday(&end_time);
+ end_time.sec += app.client.timeout;
+
+ pj_gettimeofday(&last_report);
+
+ if (app.client.first_request.sec == 0) {
+ pj_gettimeofday(&app.client.first_request);
+ }
+
+ /* Submit all jobs */
+ while (app.client.job_submitted < app.client.job_count && !app.thread_quit){
+ pj_time_val timeout = { 0, 1 };
+ unsigned i;
+ int outstanding;
+ pj_status_t status;
+
+ /* Calculate current outstanding job */
+ outstanding = app.client.job_submitted - app.client.job_finished;
+
+ /* Update stats on max outstanding jobs */
+ if (outstanding > (int)app.client.stat_max_window)
+ app.client.stat_max_window = outstanding;
+
+ /* Wait if there are more pending jobs than allowed in the
+ * window. But spawn a new job anyway if no events are happening
+ * after we wait for some time.
+ */
+ for (i=0; outstanding > (int)app.client.job_window && i<1000; ++i) {
+ pj_time_val wait = { 0, 500 };
+ unsigned count = 0;
+
+ pjsip_endpt_handle_events2(app.sip_endpt, &wait, &count);
+ outstanding = app.client.job_submitted - app.client.job_finished;
+
+ if (count == 0)
+ break;
+
+ ++cycle;
+ }
+
+
+ /* Submit one job */
+ if (app.client.method.id == PJSIP_INVITE_METHOD) {
+ status = make_call(&app.client.dst_uri);
+ } else if (app.client.stateless) {
+ status = submit_stateless_job();
+ } else {
+ status = submit_job();
+ }
+
+ ++app.client.job_submitted;
+ ++cycle;
+
+ /* Handle event */
+ pjsip_endpt_handle_events2(app.sip_endpt, &timeout, NULL);
+
+ /* Check for time out, also print report */
+ if (cycle - last_cycle >= 500) {
+ pj_gettimeofday(&now);
+ if (PJ_TIME_VAL_GTE(now, end_time)) {
+ break;
+ }
+ last_cycle = cycle;
+
+
+ if (thread_index == 0 && now.sec-last_report.sec >= 2) {
+ printf("\r%d jobs started, %d completed... ",
+ app.client.job_submitted, app.client.job_finished);
+ fflush(stdout);
+ last_report = now;
+ }
+ }
+ }
+
+ if (app.client.requests_sent.sec == 0) {
+ pj_gettimeofday(&app.client.requests_sent);
+ }
+
+
+ if (thread_index == 0) {
+ printf("\r%d jobs started, %d completed%s\n",
+ app.client.job_submitted, app.client.job_finished,
+ (app.client.job_submitted!=app.client.job_finished ?
+ ", waiting..." : ".") );
+ fflush(stdout);
+ }
+
+ /* Wait until all jobs completes, or timed out */
+ pj_gettimeofday(&now);
+ while (PJ_TIME_VAL_LT(now, end_time) &&
+ app.client.job_finished < app.client.job_count &&
+ !app.thread_quit)
+ {
+ pj_time_val timeout = { 0, 1 };
+ unsigned i;
+
+ for (i=0; i<1000; ++i) {
+ unsigned count;
+ count = 0;
+ pjsip_endpt_handle_events2(app.sip_endpt, &timeout, &count);
+ if (count == 0)
+ break;
+ }
+
+ pj_gettimeofday(&now);
+ }
+
+ /* Wait couple of seconds to let jobs completes (e.g. ACKs to be sent) */
+ pj_gettimeofday(&now);
+ end_time = now;
+ end_time.sec += 2;
+ while (PJ_TIME_VAL_LT(now, end_time))
+ {
+ pj_time_val timeout = { 0, 1 };
+ unsigned i;
+
+ for (i=0; i<1000; ++i) {
+ unsigned count;
+ count = 0;
+ pjsip_endpt_handle_events2(app.sip_endpt, &timeout, &count);
+ if (count == 0)
+ break;
+ }
+
+ pj_gettimeofday(&now);
+ }
+
+ return 0;
+}
+
+
+static const char *good_number(char *buf, pj_int32_t val)
+{
+ if (val < 1000) {
+ pj_ansi_sprintf(buf, "%d", val);
+ } else if (val < 1000000) {
+ pj_ansi_sprintf(buf, "%d.%dK",
+ val / 1000,
+ (val % 1000) / 100);
+ } else {
+ pj_ansi_sprintf(buf, "%d.%02dM",
+ val / 1000000,
+ (val % 1000000) / 10000);
+ }
+
+ return buf;
+}
+
+
+static int server_thread(void *arg)
+{
+ pj_time_val timeout = { 0, 1 };
+ unsigned thread_index = (unsigned)(long)arg;
+ pj_time_val last_report, next_report;
+
+ pj_gettimeofday(&last_report);
+ next_report = last_report;
+ next_report.sec++;
+
+ while (!app.thread_quit) {
+ pj_time_val now;
+ unsigned i;
+
+ for (i=0; i<100; ++i) {
+ unsigned count = 0;
+ pjsip_endpt_handle_events2(app.sip_endpt, &timeout, &count);
+ if (count == 0)
+ break;
+ }
+
+ if (thread_index == 0) {
+ pj_gettimeofday(&now);
+
+ if (PJ_TIME_VAL_GTE(now, next_report)) {
+ pj_time_val tmp;
+ unsigned msec;
+ unsigned stateless, stateful, call;
+ char str_stateless[32], str_stateful[32], str_call[32];
+
+ tmp = now;
+ PJ_TIME_VAL_SUB(tmp, last_report);
+ msec = PJ_TIME_VAL_MSEC(tmp);
+
+ last_report = now;
+ next_report = last_report;
+ next_report.sec++;
+
+ stateless = app.server.cur_state.stateless_cnt - app.server.prev_state.stateless_cnt;
+ stateful = app.server.cur_state.stateful_cnt - app.server.prev_state.stateful_cnt;
+ call = app.server.cur_state.call_cnt - app.server.prev_state.call_cnt;
+
+ good_number(str_stateless, app.server.cur_state.stateless_cnt);
+ good_number(str_stateful, app.server.cur_state.stateful_cnt);
+ good_number(str_call, app.server.cur_state.call_cnt);
+
+ printf("Total(rate): stateless:%s (%d/s), statefull:%s (%d/s), call:%s (%d/s) \r",
+ str_stateless, stateless*1000/msec,
+ str_stateful, stateful*1000/msec,
+ str_call, call*1000/msec);
+ fflush(stdout);
+
+ app.server.prev_state = app.server.cur_state;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static void write_report(const char *msg)
+{
+ puts(msg);
+
+#if defined(PJ_WIN32) && PJ_WIN32!=0
+ OutputDebugString(msg);
+ OutputDebugString("\n");
+#endif
+}
+
+
+int main(int argc, char *argv[])
+{
+ static char report[1024];
+
+ printf("PJSIP Performance Measurement Tool v%s\n"
+ "(c)2006 pjsip.org\n\n",
+ PJ_VERSION);
+
+ if (create_app() != 0)
+ return 1;
+
+ if (init_options(argc, argv) != 0)
+ return 1;
+
+ if (init_sip() != 0)
+ return 1;
+
+ if (init_media() != 0)
+ return 1;
+
+ pj_log_set_level(app.log_level);
+
+ if (app.log_level > 4) {
+ pjsip_endpt_register_module(app.sip_endpt, &msg_logger);
+ }
+
+
+ /* Misc infos */
+ if (app.client.dst_uri.slen != 0) {
+ if (app.client.method.id == PJSIP_INVITE_METHOD) {
+ if (app.client.stateless) {
+ PJ_LOG(3,(THIS_FILE,
+ "Info: --stateless option makes no sense for INVITE,"
+ " ignored."));
+ }
+ }
+
+ }
+
+
+
+ if (app.client.dst_uri.slen) {
+ /* Client mode */
+ pj_status_t status;
+ char test_type[64];
+ unsigned msec_req, msec_res;
+ unsigned i;
+
+ /* Get the job name */
+ if (app.client.method.id == PJSIP_INVITE_METHOD) {
+ pj_ansi_strcpy(test_type, "INVITE calls");
+ } else if (app.client.stateless) {
+ pj_ansi_sprintf(test_type, "stateless %.*s requests",
+ (int)app.client.method.name.slen,
+ app.client.method.name.ptr);
+ } else {
+ pj_ansi_sprintf(test_type, "stateful %.*s requests",
+ (int)app.client.method.name.slen,
+ app.client.method.name.ptr);
+ }
+
+
+ printf("Sending %d %s to '%.*s' with %d maximum outstanding jobs, please wait..\n",
+ app.client.job_count, test_type,
+ (int)app.client.dst_uri.slen, app.client.dst_uri.ptr,
+ app.client.job_window);
+
+ for (i=0; i<app.thread_count; ++i) {
+ status = pj_thread_create(app.pool, NULL, &client_thread,
+ (void*)(long)i, 0, 0, &app.thread[i]);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to create thread", status);
+ return 1;
+ }
+ }
+
+ for (i=0; i<app.thread_count; ++i) {
+ pj_thread_join(app.thread[i]);
+ app.thread[i] = NULL;
+ }
+
+ if (app.client.last_completion.sec) {
+ pj_time_val duration;
+ duration = app.client.last_completion;
+ PJ_TIME_VAL_SUB(duration, app.client.first_request);
+ msec_res = PJ_TIME_VAL_MSEC(duration);
+ } else {
+ msec_res = app.client.timeout * 1000;
+ }
+
+ if (msec_res == 0) msec_res = 1;
+
+ if (app.client.requests_sent.sec) {
+ pj_time_val duration;
+ duration = app.client.requests_sent;
+ PJ_TIME_VAL_SUB(duration, app.client.first_request);
+ msec_req = PJ_TIME_VAL_MSEC(duration);
+ } else {
+ msec_req = app.client.timeout * 1000;
+ }
+
+ if (msec_req == 0) msec_req = 1;
+
+ if (app.client.job_submitted < app.client.job_count)
+ puts("\ntimed-out!\n");
+ else
+ puts("\ndone.\n");
+
+ pj_ansi_snprintf(
+ report, sizeof(report),
+ "Total %d %s sent in %d ms at rate of %d/sec\n"
+ "Total %d responses receieved in %d ms at rate of %d/sec:",
+ app.client.job_submitted, test_type, msec_req,
+ app.client.job_submitted * 1000 / msec_req,
+ app.client.total_responses, msec_res,
+ app.client.total_responses*1000/msec_res);
+ write_report(report);
+
+ /* Print detailed response code received */
+ pj_ansi_sprintf(report, "\nDetailed responses received:");
+ write_report(report);
+
+ for (i=0; i<PJ_ARRAY_SIZE(app.client.response_codes); ++i) {
+ const pj_str_t *reason;
+
+ if (app.client.response_codes[i] == 0)
+ continue;
+
+ reason = pjsip_get_status_text(i);
+ pj_ansi_snprintf( report, sizeof(report),
+ " - %d responses: %7d (%.*s)",
+ i, app.client.response_codes[i],
+ (int)reason->slen, reason->ptr);
+ write_report(report);
+ }
+
+ /* Total responses and rate */
+ pj_ansi_snprintf( report, sizeof(report),
+ " ------\n"
+ " TOTAL responses: %7d (rate=%d/sec)\n",
+ app.client.total_responses,
+ app.client.total_responses*1000/msec_res);
+
+ write_report(report);
+
+ pj_ansi_sprintf(report, "Maximum outstanding job: %d",
+ app.client.stat_max_window);
+ write_report(report);
+
+
+ } else {
+ /* Server mode */
+ char s[10], *unused;
+ pj_status_t status;
+ unsigned i;
+
+ puts("pjsip-perf started in server-mode");
+
+ printf("Receiving requests on the following URIs:\n"
+ " sip:0@%.*s:%d%s for stateless handling\n"
+ " sip:1@%.*s:%d%s for stateful handling\n"
+ " sip:2@%.*s:%d%s for call handling\n",
+ (int)app.local_addr.slen,
+ app.local_addr.ptr,
+ app.local_port,
+ (app.use_tcp ? ";transport=tcp" : ""),
+ (int)app.local_addr.slen,
+ app.local_addr.ptr,
+ app.local_port,
+ (app.use_tcp ? ";transport=tcp" : ""),
+ (int)app.local_addr.slen,
+ app.local_addr.ptr,
+ app.local_port,
+ (app.use_tcp ? ";transport=tcp" : ""));
+ printf("INVITE with non-matching user part will be handled call-statefully\n");
+
+ for (i=0; i<app.thread_count; ++i) {
+ status = pj_thread_create(app.pool, NULL, &server_thread,
+ (void*)(long)i, 0, 0, &app.thread[i]);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to create thread", status);
+ return 1;
+ }
+ }
+
+ puts("\nPress <ENTER> to quit\n");
+ fflush(stdout);
+ unused = fgets(s, sizeof(s), stdin);
+ PJ_UNUSED_ARG(unused);
+
+ app.thread_quit = PJ_TRUE;
+ for (i=0; i<app.thread_count; ++i) {
+ pj_thread_join(app.thread[i]);
+ app.thread[i] = NULL;
+ }
+
+ puts("");
+ }
+
+
+ destroy_app();
+
+ return 0;
+}
+
diff --git a/pjsip-apps/src/samples/playfile.c b/pjsip-apps/src/samples/playfile.c
new file mode 100644
index 0000000..778b3e5
--- /dev/null
+++ b/pjsip-apps/src/samples/playfile.c
@@ -0,0 +1,217 @@
+/* $Id: playfile.c 3664 2011-07-19 03:42:28Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <pjmedia.h>
+#include <pjlib-util.h>
+#include <pjlib.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "util.h"
+
+
+/**
+ * \page page_pjmedia_samples_playfile_c Samples: Playing WAV File to Sound Device
+ *
+ * This is a very simple example to use the @ref PJMEDIA_FILE_PLAY and
+ * @ref PJMED_SND_PORT. In this example, we open both the file and sound
+ * device, and connect the two of them, and voila! Sound will be playing
+ * the contents of the file.
+ *
+ * @see page_pjmedia_samples_recfile_c
+ *
+ * This file is pjsip-apps/src/samples/playfile.c
+ *
+ * \includelineno playfile.c
+ */
+
+
+/*
+ * playfile.c
+ *
+ * PURPOSE:
+ * Play a WAV file to sound player device.
+ *
+ * USAGE:
+ * playfile FILE.WAV
+ *
+ * The WAV file could have mono or stereo channels with arbitrary
+ * sampling rate, but MUST contain uncompressed (i.e. 16bit) PCM.
+ *
+ */
+
+
+/* For logging purpose. */
+#define THIS_FILE "playfile.c"
+
+
+static const char *desc =
+" FILE \n"
+" \n"
+" playfile.c \n"
+" \n"
+" PURPOSE \n"
+" \n"
+" Demonstrate how to play a WAV file. \n"
+" \n"
+" USAGE \n"
+" \n"
+" playfile FILE.WAV \n"
+" \n"
+" The WAV file could have mono or stereo channels with arbitrary \n"
+" sampling rate, but MUST contain uncompressed (i.e. 16bit) PCM. \n";
+
+
+/*
+ * main()
+ */
+int main(int argc, char *argv[])
+{
+ pj_caching_pool cp;
+ pjmedia_endpt *med_endpt;
+ pj_pool_t *pool;
+ pjmedia_port *file_port;
+ pjmedia_snd_port *snd_port;
+ char tmp[10];
+ pj_status_t status;
+
+
+ if (argc != 2) {
+ puts("Error: filename required");
+ puts(desc);
+ return 1;
+ }
+
+
+ /* Must init PJLIB first: */
+ status = pj_init();
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ /* Must create a pool factory before we can allocate any memory. */
+ pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);
+
+ /*
+ * Initialize media endpoint.
+ * This will implicitly initialize PJMEDIA too.
+ */
+ status = pjmedia_endpt_create(&cp.factory, NULL, 1, &med_endpt);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ /* Create memory pool for our file player */
+ pool = pj_pool_create( &cp.factory, /* pool factory */
+ "wav", /* pool name. */
+ 4000, /* init size */
+ 4000, /* increment size */
+ NULL /* callback on error */
+ );
+
+ /* Create file media port from the WAV file */
+ status = pjmedia_wav_player_port_create( pool, /* memory pool */
+ argv[1], /* file to play */
+ 20, /* ptime. */
+ 0, /* flags */
+ 0, /* default buffer */
+ &file_port/* returned port */
+ );
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to use WAV file", status);
+ return 1;
+ }
+
+ /* Create sound player port. */
+ status = pjmedia_snd_port_create_player(
+ pool, /* pool */
+ -1, /* use default dev. */
+ PJMEDIA_PIA_SRATE(&file_port->info),/* clock rate. */
+ PJMEDIA_PIA_CCNT(&file_port->info),/* # of channels. */
+ PJMEDIA_PIA_SPF(&file_port->info), /* samples per frame. */
+ PJMEDIA_PIA_BITS(&file_port->info),/* bits per sample. */
+ 0, /* options */
+ &snd_port /* returned port */
+ );
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to open sound device", status);
+ return 1;
+ }
+
+ /* Connect file port to the sound player.
+ * Stream playing will commence immediately.
+ */
+ status = pjmedia_snd_port_connect( snd_port, file_port);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+
+
+ /*
+ * File should be playing and looping now, using sound device's thread.
+ */
+
+
+ /* Sleep to allow log messages to flush */
+ pj_thread_sleep(100);
+
+
+ printf("Playing %s..\n", argv[1]);
+ puts("");
+ puts("Press <ENTER> to stop playing and quit");
+
+ if (fgets(tmp, sizeof(tmp), stdin) == NULL) {
+ puts("EOF while reading stdin, will quit now..");
+ }
+
+
+ /* Start deinitialization: */
+
+ /* Disconnect sound port from file port */
+ status = pjmedia_snd_port_disconnect(snd_port);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ /* Without this sleep, Windows/DirectSound will repeteadly
+ * play the last frame during destroy.
+ */
+ pj_thread_sleep(100);
+
+ /* Destroy sound device */
+ status = pjmedia_snd_port_destroy( snd_port );
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+
+ /* Destroy file port */
+ status = pjmedia_port_destroy( file_port );
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+
+ /* Release application pool */
+ pj_pool_release( pool );
+
+ /* Destroy media endpoint. */
+ pjmedia_endpt_destroy( med_endpt );
+
+ /* Destroy pool factory */
+ pj_caching_pool_destroy( &cp );
+
+ /* Shutdown PJLIB */
+ pj_shutdown();
+
+
+ /* Done. */
+ return 0;
+}
+
diff --git a/pjsip-apps/src/samples/playsine.c b/pjsip-apps/src/samples/playsine.c
new file mode 100644
index 0000000..bab0c9b
--- /dev/null
+++ b/pjsip-apps/src/samples/playsine.c
@@ -0,0 +1,317 @@
+/* $Id: playsine.c 3664 2011-07-19 03:42:28Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+/**
+ * \page page_pjmedia_samples_playsine_c Samples: Using Custom Ports (Sine Wave Generator)
+ *
+ * This example demonstrate how to create a custom media port (in this case, a
+ * sine wave generator) and connect it to the sound device.
+ *
+ * This file is pjsip-apps/src/samples/playsine.c
+ *
+ * \includelineno playsine.c
+ */
+
+/*
+ * playsine.c
+ *
+ * PURPOSE:
+ * Demonstrate how to create and use custom media port which
+ * simply feed a sine wav to the sound player.
+ *
+ * USAGE:
+ * playsine [nchannel]
+ *
+ * where:
+ * nchannel is 1 for mono (this is the default) or 2 for stereo.
+ */
+
+#include <pjmedia.h>
+#include <pjlib.h>
+
+#include <stdlib.h> /* atoi() */
+#include <stdio.h>
+#include <math.h> /* sin() */
+
+/* For logging purpose. */
+#define THIS_FILE "playsine.c"
+
+
+/* Util to display the error message for the specified error code */
+static int app_perror( const char *sender, const char *title,
+ pj_status_t status)
+{
+ char errmsg[PJ_ERR_MSG_SIZE];
+
+ PJ_UNUSED_ARG(sender);
+
+ pj_strerror(status, errmsg, sizeof(errmsg));
+
+ printf("%s: %s [code=%d]\n", title, errmsg, status);
+ return 1;
+}
+
+
+/* Struct attached to sine generator */
+typedef struct
+{
+ pj_int16_t *samples; /* Sine samples. */
+} port_data;
+
+
+/* This callback is called to feed more samples */
+static pj_status_t sine_get_frame( pjmedia_port *port,
+ pjmedia_frame *frame)
+{
+ port_data *sine = port->port_data.pdata;
+ pj_int16_t *samples = frame->buf;
+ unsigned i, count, left, right;
+
+ /* Get number of samples */
+ count = frame->size / 2 / PJMEDIA_PIA_CCNT(&port->info);
+
+ left = 0;
+ right = 0;
+
+ for (i=0; i<count; ++i) {
+ *samples++ = sine->samples[left];
+ ++left;
+
+ if (PJMEDIA_PIA_CCNT(&port->info) == 2) {
+ *samples++ = sine->samples[right];
+ right += 2; /* higher pitch so we can distinguish left and right. */
+ if (right >= count)
+ right = 0;
+ }
+ }
+
+ /* Must set frame->type correctly, otherwise the sound device
+ * will refuse to play.
+ */
+ frame->type = PJMEDIA_FRAME_TYPE_AUDIO;
+
+ return PJ_SUCCESS;
+}
+
+#ifndef M_PI
+#define M_PI (3.14159265)
+#endif
+
+/*
+ * Create a media port to generate sine wave samples.
+ */
+static pj_status_t create_sine_port(pj_pool_t *pool,
+ unsigned sampling_rate,
+ unsigned channel_count,
+ pjmedia_port **p_port)
+{
+ pjmedia_port *port;
+ unsigned i;
+ unsigned count;
+ pj_str_t name;
+ port_data *sine;
+
+ PJ_ASSERT_RETURN(pool && channel_count > 0 && channel_count <= 2,
+ PJ_EINVAL);
+
+ port = pj_pool_zalloc(pool, sizeof(pjmedia_port));
+ PJ_ASSERT_RETURN(port != NULL, PJ_ENOMEM);
+
+ /* Fill in port info. */
+ name = pj_str("sine generator");
+ pjmedia_port_info_init(&port->info, &name,
+ PJMEDIA_SIG_CLASS_PORT_AUD('s', 'i'),
+ sampling_rate,
+ channel_count,
+ 16, sampling_rate * 20 / 1000 * channel_count);
+
+ /* Set the function to feed frame */
+ port->get_frame = &sine_get_frame;
+
+ /* Create sine port data */
+ port->port_data.pdata = sine = pj_pool_zalloc(pool, sizeof(port_data));
+
+ /* Create samples */
+ count = PJMEDIA_PIA_SPF(&port->info) / channel_count;
+ sine->samples = pj_pool_alloc(pool, count * sizeof(pj_int16_t));
+ PJ_ASSERT_RETURN(sine->samples != NULL, PJ_ENOMEM);
+
+ /* initialise sinusoidal wavetable */
+ for( i=0; i<count; i++ )
+ {
+ sine->samples[i] = (pj_int16_t) (10000.0 *
+ sin(((double)i/(double)count) * M_PI * 8.) );
+ }
+
+ *p_port = port;
+
+ return PJ_SUCCESS;
+}
+
+
+/* Show usage */
+static void usage(void)
+{
+ puts("");
+ puts("Usage: playsine [nchannel]");
+ puts("");
+ puts("where");
+ puts(" nchannel is number of audio channels (1 for mono, or 2 for stereo).");
+ puts(" Default is 1 (mono).");
+ puts("");
+}
+
+
+/*
+ * main()
+ */
+int main(int argc, char *argv[])
+{
+ pj_caching_pool cp;
+ pjmedia_endpt *med_endpt;
+ pj_pool_t *pool;
+ pjmedia_port *sine_port;
+ pjmedia_snd_port *snd_port;
+ char tmp[10];
+ int channel_count = 1;
+ pj_status_t status;
+
+ if (argc == 2) {
+ channel_count = atoi(argv[1]);
+ if (channel_count < 1 || channel_count > 2) {
+ puts("Error: invalid arguments");
+ usage();
+ return 1;
+ }
+ }
+
+ /* Must init PJLIB first: */
+ status = pj_init();
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ /* Must create a pool factory before we can allocate any memory. */
+ pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);
+
+ /*
+ * Initialize media endpoint.
+ * This will implicitly initialize PJMEDIA too.
+ */
+ status = pjmedia_endpt_create(&cp.factory, NULL, 1, &med_endpt);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ /* Create memory pool for our sine generator */
+ pool = pj_pool_create( &cp.factory, /* pool factory */
+ "wav", /* pool name. */
+ 4000, /* init size */
+ 4000, /* increment size */
+ NULL /* callback on error */
+ );
+
+ /* Create a media port to generate sine wave samples. */
+ status = create_sine_port( pool, /* memory pool */
+ 11025, /* sampling rate */
+ channel_count,/* # of channels */
+ &sine_port /* returned port */
+ );
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to create sine port", status);
+ return 1;
+ }
+
+ /* Create sound player port. */
+ status = pjmedia_snd_port_create_player(
+ pool, /* pool */
+ -1, /* use default dev. */
+ PJMEDIA_PIA_SRATE(&sine_port->info),/* clock rate. */
+ PJMEDIA_PIA_CCNT(&sine_port->info),/* # of channels. */
+ PJMEDIA_PIA_SPF(&sine_port->info), /* samples per frame. */
+ PJMEDIA_PIA_BITS(&sine_port->info),/* bits per sample. */
+ 0, /* options */
+ &snd_port /* returned port */
+ );
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to open sound device", status);
+ return 1;
+ }
+
+ /* Connect sine generator port to the sound player
+ * Stream playing will commence immediately.
+ */
+ status = pjmedia_snd_port_connect( snd_port, sine_port);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+
+
+ /*
+ * Audio should be playing in a loop now, using sound device's thread.
+ */
+
+
+ /* Sleep to allow log messages to flush */
+ pj_thread_sleep(100);
+
+
+ puts("Playing sine wave..");
+ puts("");
+ puts("Press <ENTER> to stop playing and quit");
+
+ if (fgets(tmp, sizeof(tmp), stdin) == NULL) {
+ puts("EOF while reading stdin, will quit now..");
+ }
+
+
+ /* Start deinitialization: */
+
+ /* Disconnect sound port from file port */
+ status = pjmedia_snd_port_disconnect(snd_port);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ /* Without this sleep, Windows/DirectSound will repeteadly
+ * play the last frame during destroy.
+ */
+ pj_thread_sleep(100);
+
+ /* Destroy sound device */
+ status = pjmedia_snd_port_destroy( snd_port );
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+
+ /* Destroy sine generator */
+ status = pjmedia_port_destroy( sine_port );
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+
+ /* Release application pool */
+ pj_pool_release( pool );
+
+ /* Destroy media endpoint. */
+ pjmedia_endpt_destroy( med_endpt );
+
+ /* Destroy pool factory */
+ pj_caching_pool_destroy( &cp );
+
+ /* Shutdown PJLIB */
+ pj_shutdown();
+
+
+ /* Done. */
+ return 0;
+}
diff --git a/pjsip-apps/src/samples/proxy.h b/pjsip-apps/src/samples/proxy.h
new file mode 100644
index 0000000..2e1b383
--- /dev/null
+++ b/pjsip-apps/src/samples/proxy.h
@@ -0,0 +1,585 @@
+/* $Id: proxy.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <pjsip.h>
+#include <pjlib-util.h>
+#include <pjlib.h>
+
+
+/* Options */
+static struct global_struct
+{
+ pj_caching_pool cp;
+ pjsip_endpoint *endpt;
+ int port;
+ pj_pool_t *pool;
+
+ pj_thread_t *thread;
+ pj_bool_t quit_flag;
+
+ pj_bool_t record_route;
+
+ unsigned name_cnt;
+ pjsip_host_port name[16];
+} global;
+
+
+
+static void app_perror(const char *msg, pj_status_t status)
+{
+ char errmsg[PJ_ERR_MSG_SIZE];
+
+ pj_strerror(status, errmsg, sizeof(errmsg));
+ PJ_LOG(1,(THIS_FILE, "%s: %s", msg, errmsg));
+}
+
+
+static void usage(void)
+{
+ puts("Options:\n"
+ "\n"
+ " -p, --port N Set local listener port to N\n"
+ " -R, --rr Perform record routing\n"
+ " -L, --log-level N Set log level to N (default: 4)\n"
+ " -h, --help Show this help screen\n"
+ );
+}
+
+
+static pj_status_t init_options(int argc, char *argv[])
+{
+ struct pj_getopt_option long_opt[] = {
+ { "port", 1, 0, 'p'},
+ { "rr", 0, 0, 'R'},
+ { "log-level", 1, 0, 'L'},
+ { "help", 0, 0, 'h'},
+ { NULL, 0, 0, 0}
+ };
+ int c;
+ int opt_ind;
+
+ pj_optind = 0;
+ while((c=pj_getopt_long(argc, argv, "p:L:Rh", long_opt, &opt_ind))!=-1) {
+ switch (c) {
+ case 'p':
+ global.port = atoi(pj_optarg);
+ printf("Port is set to %d\n", global.port);
+ break;
+
+ case 'R':
+ global.record_route = PJ_TRUE;
+ printf("Using record route mode\n");
+ break;
+
+ case 'L':
+ pj_log_set_level(atoi(pj_optarg));
+ break;
+
+ case 'h':
+ usage();
+ return -1;
+
+ default:
+ puts("Unknown option. Run with --help for help.");
+ return -1;
+ }
+ }
+
+ return PJ_SUCCESS;
+}
+
+
+/*****************************************************************************
+ * This is a very simple PJSIP module, whose sole purpose is to display
+ * incoming and outgoing messages to log. This module will have priority
+ * higher than transport layer, which means:
+ *
+ * - incoming messages will come to this module first before reaching
+ * transaction layer.
+ *
+ * - outgoing messages will come to this module last, after the message
+ * has been 'printed' to contiguous buffer by transport layer and
+ * appropriate transport instance has been decided for this message.
+ *
+ */
+
+/* Notification on incoming messages */
+static pj_bool_t logging_on_rx_msg(pjsip_rx_data *rdata)
+{
+ PJ_LOG(5,(THIS_FILE, "RX %d bytes %s from %s %s:%d:\n"
+ "%.*s\n"
+ "--end msg--",
+ rdata->msg_info.len,
+ pjsip_rx_data_get_info(rdata),
+ rdata->tp_info.transport->type_name,
+ rdata->pkt_info.src_name,
+ rdata->pkt_info.src_port,
+ (int)rdata->msg_info.len,
+ rdata->msg_info.msg_buf));
+
+ /* Always return false, otherwise messages will not get processed! */
+ return PJ_FALSE;
+}
+
+/* Notification on outgoing messages */
+static pj_status_t logging_on_tx_msg(pjsip_tx_data *tdata)
+{
+
+ /* Important note:
+ * tp_info field is only valid after outgoing messages has passed
+ * transport layer. So don't try to access tp_info when the module
+ * has lower priority than transport layer.
+ */
+
+ PJ_LOG(5,(THIS_FILE, "TX %d bytes %s to %s %s:%d:\n"
+ "%.*s\n"
+ "--end msg--",
+ (tdata->buf.cur - tdata->buf.start),
+ pjsip_tx_data_get_info(tdata),
+ tdata->tp_info.transport->type_name,
+ tdata->tp_info.dst_name,
+ tdata->tp_info.dst_port,
+ (int)(tdata->buf.cur - tdata->buf.start),
+ tdata->buf.start));
+
+ /* Always return success, otherwise message will not get sent! */
+ return PJ_SUCCESS;
+}
+
+/* The module instance. */
+static pjsip_module mod_msg_logger =
+{
+ NULL, NULL, /* prev, next. */
+ { "mod-msg-logger", 14 }, /* Name. */
+ -1, /* Id */
+ PJSIP_MOD_PRIORITY_TRANSPORT_LAYER-1,/* Priority */
+ NULL, /* load() */
+ NULL, /* start() */
+ NULL, /* stop() */
+ NULL, /* unload() */
+ &logging_on_rx_msg, /* on_rx_request() */
+ &logging_on_rx_msg, /* on_rx_response() */
+ &logging_on_tx_msg, /* on_tx_request. */
+ &logging_on_tx_msg, /* on_tx_response() */
+ NULL, /* on_tsx_state() */
+
+};
+
+
+static pj_status_t init_stack(void)
+{
+ pj_status_t status;
+
+ /* Must init PJLIB first: */
+ status = pj_init();
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+
+ /* Then init PJLIB-UTIL: */
+ status = pjlib_util_init();
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+
+ /* Must create a pool factory before we can allocate any memory. */
+ pj_caching_pool_init(&global.cp, &pj_pool_factory_default_policy, 0);
+
+ /* Create the endpoint: */
+ status = pjsip_endpt_create(&global.cp.factory, NULL, &global.endpt);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+ /* Init transaction layer for stateful proxy only */
+#if STATEFUL
+ status = pjsip_tsx_layer_init_module(global.endpt);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+#endif
+
+ /* Create listening transport */
+ {
+ pj_sockaddr_in addr;
+
+ addr.sin_family = pj_AF_INET();
+ addr.sin_addr.s_addr = 0;
+ addr.sin_port = pj_htons((pj_uint16_t)global.port);
+
+ status = pjsip_udp_transport_start( global.endpt, &addr,
+ NULL, 1, NULL);
+ if (status != PJ_SUCCESS)
+ return status;
+ }
+
+ /* Create pool for the application */
+ global.pool = pj_pool_create(&global.cp.factory, "proxyapp",
+ 4000, 4000, NULL);
+
+ /* Register the logger module */
+ pjsip_endpt_register_module(global.endpt, &mod_msg_logger);
+
+ return PJ_SUCCESS;
+}
+
+
+static pj_status_t init_proxy(void)
+{
+ pj_sockaddr pri_addr;
+ pj_sockaddr addr_list[16];
+ unsigned addr_cnt = PJ_ARRAY_SIZE(addr_list);
+ unsigned i;
+
+ /* List all names matching local endpoint.
+ * Note that PJLIB version 0.6 and newer has a function to
+ * enumerate local IP interface (pj_enum_ip_interface()), so
+ * by using it would be possible to list all IP interfaces in
+ * this host.
+ */
+
+ /* The first address is important since this would be the one
+ * to be added in Record-Route.
+ */
+ if (pj_gethostip(pj_AF_INET(), &pri_addr)==PJ_SUCCESS) {
+ pj_strdup2(global.pool, &global.name[global.name_cnt].host,
+ pj_inet_ntoa(pri_addr.ipv4.sin_addr));
+ global.name[global.name_cnt].port = global.port;
+ global.name_cnt++;
+ }
+
+ /* Get the rest of IP interfaces */
+ if (pj_enum_ip_interface(pj_AF_INET(), &addr_cnt, addr_list) == PJ_SUCCESS) {
+ for (i=0; i<addr_cnt; ++i) {
+
+ if (addr_list[i].ipv4.sin_addr.s_addr == pri_addr.ipv4.sin_addr.s_addr)
+ continue;
+
+ pj_strdup2(global.pool, &global.name[global.name_cnt].host,
+ pj_inet_ntoa(addr_list[i].ipv4.sin_addr));
+ global.name[global.name_cnt].port = global.port;
+ global.name_cnt++;
+ }
+ }
+
+ /* Add loopback address. */
+#if PJ_IP_HELPER_IGNORE_LOOPBACK_IF
+ global.name[global.name_cnt].host = pj_str("127.0.0.1");
+ global.name[global.name_cnt].port = global.port;
+ global.name_cnt++;
+#endif
+
+ global.name[global.name_cnt].host = *pj_gethostname();
+ global.name[global.name_cnt].port = global.port;
+ global.name_cnt++;
+
+ global.name[global.name_cnt].host = pj_str("localhost");
+ global.name[global.name_cnt].port = global.port;
+ global.name_cnt++;
+
+ PJ_LOG(3,(THIS_FILE, "Proxy started, listening on port %d", global.port));
+ PJ_LOG(3,(THIS_FILE, "Local host aliases:"));
+ for (i=0; i<global.name_cnt; ++i) {
+ PJ_LOG(3,(THIS_FILE, " %.*s:%d",
+ (int)global.name[i].host.slen,
+ global.name[i].host.ptr,
+ global.name[i].port));
+ }
+
+ if (global.record_route) {
+ PJ_LOG(3,(THIS_FILE, "Using Record-Route mode"));
+ }
+
+ return PJ_SUCCESS;
+}
+
+
+#if PJ_HAS_THREADS
+static int worker_thread(void *p)
+{
+ pj_time_val delay = {0, 10};
+
+ PJ_UNUSED_ARG(p);
+
+ while (!global.quit_flag) {
+ pjsip_endpt_handle_events(global.endpt, &delay);
+ }
+
+ return 0;
+}
+#endif
+
+
+/* Utility to determine if URI is local to this host. */
+static pj_bool_t is_uri_local(const pjsip_sip_uri *uri)
+{
+ unsigned i;
+ for (i=0; i<global.name_cnt; ++i) {
+ if ((uri->port == global.name[i].port ||
+ (uri->port==0 && global.name[i].port==5060)) &&
+ pj_stricmp(&uri->host, &global.name[i].host)==0)
+ {
+ /* Match */
+ return PJ_TRUE;
+ }
+ }
+
+ /* Doesn't match */
+ return PJ_FALSE;
+}
+
+
+/* Proxy utility to verify incoming requests.
+ * Return non-zero if verification failed.
+ */
+static pj_status_t proxy_verify_request(pjsip_rx_data *rdata)
+{
+ const pj_str_t STR_PROXY_REQUIRE = {"Proxy-Require", 13};
+
+ /* RFC 3261 Section 16.3 Request Validation */
+
+ /* Before an element can proxy a request, it MUST verify the message's
+ * validity. A valid message must pass the following checks:
+ *
+ * 1. Reasonable Syntax
+ * 2. URI scheme
+ * 3. Max-Forwards
+ * 4. (Optional) Loop Detection
+ * 5. Proxy-Require
+ * 6. Proxy-Authorization
+ */
+
+ /* 1. Reasonable Syntax.
+ * This would have been checked by transport layer.
+ */
+
+ /* 2. URI scheme.
+ * We only want to support "sip:" URI scheme for this simple proxy.
+ */
+ if (!PJSIP_URI_SCHEME_IS_SIP(rdata->msg_info.msg->line.req.uri)) {
+ pjsip_endpt_respond_stateless(global.endpt, rdata,
+ PJSIP_SC_UNSUPPORTED_URI_SCHEME, NULL,
+ NULL, NULL);
+ return PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_UNSUPPORTED_URI_SCHEME);
+ }
+
+ /* 3. Max-Forwards.
+ * Send error if Max-Forwards is 1 or lower.
+ */
+ if (rdata->msg_info.max_fwd && rdata->msg_info.max_fwd->ivalue <= 1) {
+ pjsip_endpt_respond_stateless(global.endpt, rdata,
+ PJSIP_SC_TOO_MANY_HOPS, NULL,
+ NULL, NULL);
+ return PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_TOO_MANY_HOPS);
+ }
+
+ /* 4. (Optional) Loop Detection.
+ * Nah, we don't do that with this simple proxy.
+ */
+
+ /* 5. Proxy-Require */
+ if (pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &STR_PROXY_REQUIRE,
+ NULL) != NULL)
+ {
+ pjsip_endpt_respond_stateless(global.endpt, rdata,
+ PJSIP_SC_BAD_EXTENSION, NULL,
+ NULL, NULL);
+ return PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_BAD_EXTENSION);
+ }
+
+ /* 6. Proxy-Authorization.
+ * Nah, we don't require any authorization with this sample.
+ */
+
+ return PJ_SUCCESS;
+}
+
+
+/* Process route information in the reqeust */
+static pj_status_t proxy_process_routing(pjsip_tx_data *tdata)
+{
+ pjsip_sip_uri *target;
+ pjsip_route_hdr *hroute;
+
+ /* RFC 3261 Section 16.4 Route Information Preprocessing */
+
+ target = (pjsip_sip_uri*) tdata->msg->line.req.uri;
+
+ /* The proxy MUST inspect the Request-URI of the request. If the
+ * Request-URI of the request contains a value this proxy previously
+ * placed into a Record-Route header field (see Section 16.6 item 4),
+ * the proxy MUST replace the Request-URI in the request with the last
+ * value from the Route header field, and remove that value from the
+ * Route header field. The proxy MUST then proceed as if it received
+ * this modified request.
+ */
+ if (is_uri_local(target)) {
+ pjsip_route_hdr *r;
+ pjsip_sip_uri *uri;
+
+ /* Find the first Route header */
+ r = hroute = (pjsip_route_hdr*)
+ pjsip_msg_find_hdr(tdata->msg, PJSIP_H_ROUTE, NULL);
+ if (r == NULL) {
+ /* No Route header. This request is destined for this proxy. */
+ return PJ_SUCCESS;
+ }
+
+ /* Find the last Route header */
+ while ( (r=(pjsip_route_hdr*)pjsip_msg_find_hdr(tdata->msg,
+ PJSIP_H_ROUTE,
+ r->next)) != NULL )
+ {
+ hroute = r;
+ }
+
+ /* If the last Route header doesn't have ";lr" parameter, then
+ * this is a strict-routed request indeed, and we follow the steps
+ * in processing strict-route requests above.
+ *
+ * But if it does contain ";lr" parameter, skip the strict-route
+ * processing.
+ */
+ uri = (pjsip_sip_uri*)
+ pjsip_uri_get_uri(&hroute->name_addr);
+ if (uri->lr_param == 0) {
+ /* Yes this is strict route, so:
+ * - replace req URI with the URI in Route header,
+ * - remove the Route header,
+ * - proceed as if it received this modified request.
+ */
+ tdata->msg->line.req.uri = hroute->name_addr.uri;
+ target = (pjsip_sip_uri*) tdata->msg->line.req.uri;
+ pj_list_erase(hroute);
+ }
+ }
+
+ /* If the Request-URI contains a maddr parameter, the proxy MUST check
+ * to see if its value is in the set of addresses or domains the proxy
+ * is configured to be responsible for. If the Request-URI has a maddr
+ * parameter with a value the proxy is responsible for, and the request
+ * was received using the port and transport indicated (explicitly or by
+ * default) in the Request-URI, the proxy MUST strip the maddr and any
+ * non-default port or transport parameter and continue processing as if
+ * those values had not been present in the request.
+ */
+ if (target->maddr_param.slen != 0) {
+ pjsip_sip_uri maddr_uri;
+
+ maddr_uri.host = target->maddr_param;
+ maddr_uri.port = global.port;
+
+ if (is_uri_local(&maddr_uri)) {
+ target->maddr_param.slen = 0;
+ target->port = 0;
+ target->transport_param.slen = 0;
+ }
+ }
+
+ /* If the first value in the Route header field indicates this proxy,
+ * the proxy MUST remove that value from the request.
+ */
+ hroute = (pjsip_route_hdr*)
+ pjsip_msg_find_hdr(tdata->msg, PJSIP_H_ROUTE, NULL);
+ if (hroute && is_uri_local((pjsip_sip_uri*)hroute->name_addr.uri)) {
+ pj_list_erase(hroute);
+ }
+
+ return PJ_SUCCESS;
+}
+
+
+/* Postprocess the request before forwarding it */
+static void proxy_postprocess(pjsip_tx_data *tdata)
+{
+ /* Optionally record-route */
+ if (global.record_route) {
+ char uribuf[128];
+ pj_str_t uri;
+ const pj_str_t H_RR = { "Record-Route", 12 };
+ pjsip_generic_string_hdr *rr;
+
+ pj_ansi_snprintf(uribuf, sizeof(uribuf), "<sip:%.*s:%d;lr>",
+ (int)global.name[0].host.slen,
+ global.name[0].host.ptr,
+ global.name[0].port);
+ uri = pj_str(uribuf);
+ rr = pjsip_generic_string_hdr_create(tdata->pool,
+ &H_RR, &uri);
+ pjsip_msg_insert_first_hdr(tdata->msg, (pjsip_hdr*)rr);
+ }
+}
+
+
+/* Calculate new target for the request */
+static pj_status_t proxy_calculate_target(pjsip_rx_data *rdata,
+ pjsip_tx_data *tdata)
+{
+ pjsip_sip_uri *target;
+
+ /* RFC 3261 Section 16.5 Determining Request Targets */
+
+ target = (pjsip_sip_uri*) tdata->msg->line.req.uri;
+
+ /* If the Request-URI of the request contains an maddr parameter, the
+ * Request-URI MUST be placed into the target set as the only target
+ * URI, and the proxy MUST proceed to Section 16.6.
+ */
+ if (target->maddr_param.slen) {
+ proxy_postprocess(tdata);
+ return PJ_SUCCESS;
+ }
+
+
+ /* If the domain of the Request-URI indicates a domain this element is
+ * not responsible for, the Request-URI MUST be placed into the target
+ * set as the only target, and the element MUST proceed to the task of
+ * Request Forwarding (Section 16.6).
+ */
+ if (!is_uri_local(target)) {
+ proxy_postprocess(tdata);
+ return PJ_SUCCESS;
+ }
+
+ /* If the target set for the request has not been predetermined as
+ * described above, this implies that the element is responsible for the
+ * domain in the Request-URI, and the element MAY use whatever mechanism
+ * it desires to determine where to send the request.
+ */
+
+ /* We're not interested to receive request destined to us, so
+ * respond with 404/Not Found (only if request is not ACK!).
+ */
+ if (rdata->msg_info.msg->line.req.method.id != PJSIP_ACK_METHOD) {
+ pjsip_endpt_respond_stateless(global.endpt, rdata,
+ PJSIP_SC_NOT_FOUND, NULL,
+ NULL, NULL);
+ }
+
+ /* Delete the request since we're not forwarding it */
+ pjsip_tx_data_dec_ref(tdata);
+
+ return PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_NOT_FOUND);
+}
+
+
+/* Destroy stack */
+static void destroy_stack(void)
+{
+ pjsip_endpt_destroy(global.endpt);
+ pj_pool_release(global.pool);
+ pj_caching_pool_destroy(&global.cp);
+
+ pj_shutdown();
+}
+
diff --git a/pjsip-apps/src/samples/recfile.c b/pjsip-apps/src/samples/recfile.c
new file mode 100644
index 0000000..fedd5c6
--- /dev/null
+++ b/pjsip-apps/src/samples/recfile.c
@@ -0,0 +1,202 @@
+/* $Id: recfile.c 3664 2011-07-19 03:42:28Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/**
+ * \page page_pjmedia_samples_recfile_c Samples: Capturing Audio to WAV File
+ *
+ * In this example, we capture audio from the sound device and save it to
+ * WAVE file.
+ *
+ * @see page_pjmedia_samples_playfile_c
+ *
+ * This file is pjsip-apps/src/samples/recfile.c
+ *
+ * \includelineno recfile.c
+ */
+
+#include <pjmedia.h>
+#include <pjlib.h>
+
+#include <stdio.h>
+
+/* For logging purpose. */
+#define THIS_FILE "recfile.c"
+
+
+/* Configs */
+#define CLOCK_RATE 44100
+#define NCHANNELS 2
+#define SAMPLES_PER_FRAME (NCHANNELS * (CLOCK_RATE * 10 / 1000))
+#define BITS_PER_SAMPLE 16
+
+
+static const char *desc =
+ " FILE \n"
+ " recfile.c \n"
+ " \n"
+ " PURPOSE: \n"
+ " Record microphone to WAVE file. \n"
+ " \n"
+ " USAGE: \n"
+ " recfile FILE.WAV \n"
+ "";
+
+
+/* Util to display the error message for the specified error code */
+static int app_perror( const char *sender, const char *title,
+ pj_status_t status)
+{
+ char errmsg[PJ_ERR_MSG_SIZE];
+
+ PJ_UNUSED_ARG(sender);
+
+ pj_strerror(status, errmsg, sizeof(errmsg));
+
+ printf("%s: %s [code=%d]\n", title, errmsg, status);
+ return 1;
+}
+
+
+/*
+ * main()
+ */
+int main(int argc, char *argv[])
+{
+ pj_caching_pool cp;
+ pjmedia_endpt *med_endpt;
+ pj_pool_t *pool;
+ pjmedia_port *file_port;
+ pjmedia_snd_port *snd_port;
+ char tmp[10];
+ pj_status_t status;
+
+
+ /* Verify cmd line arguments. */
+ if (argc != 2) {
+ puts("");
+ puts(desc);
+ return 0;
+ }
+
+ /* Must init PJLIB first: */
+ status = pj_init();
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ /* Must create a pool factory before we can allocate any memory. */
+ pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);
+
+ /*
+ * Initialize media endpoint.
+ * This will implicitly initialize PJMEDIA too.
+ */
+ status = pjmedia_endpt_create(&cp.factory, NULL, 1, &med_endpt);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ /* Create memory pool for our file player */
+ pool = pj_pool_create( &cp.factory, /* pool factory */
+ "app", /* pool name. */
+ 4000, /* init size */
+ 4000, /* increment size */
+ NULL /* callback on error */
+ );
+
+ /* Create WAVE file writer port. */
+ status = pjmedia_wav_writer_port_create( pool, argv[1],
+ CLOCK_RATE,
+ NCHANNELS,
+ SAMPLES_PER_FRAME,
+ BITS_PER_SAMPLE,
+ 0, 0,
+ &file_port);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to open WAV file for writing", status);
+ return 1;
+ }
+
+ /* Create sound player port. */
+ status = pjmedia_snd_port_create_rec(
+ pool, /* pool */
+ -1, /* use default dev. */
+ PJMEDIA_PIA_SRATE(&file_port->info),/* clock rate. */
+ PJMEDIA_PIA_CCNT(&file_port->info),/* # of channels. */
+ PJMEDIA_PIA_SPF(&file_port->info), /* samples per frame. */
+ PJMEDIA_PIA_BITS(&file_port->info),/* bits per sample. */
+ 0, /* options */
+ &snd_port /* returned port */
+ );
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to open sound device", status);
+ return 1;
+ }
+
+ /* Connect file port to the sound player.
+ * Stream playing will commence immediately.
+ */
+ status = pjmedia_snd_port_connect( snd_port, file_port);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+
+
+ /*
+ * Recording should be started now.
+ */
+
+
+ /* Sleep to allow log messages to flush */
+ pj_thread_sleep(10);
+
+
+ printf("Recodring %s..\n", argv[1]);
+ puts("");
+ puts("Press <ENTER> to stop recording and quit");
+
+ if (fgets(tmp, sizeof(tmp), stdin) == NULL) {
+ puts("EOF while reading stdin, will quit now..");
+ }
+
+
+ /* Start deinitialization: */
+
+ /* Destroy sound device */
+ status = pjmedia_snd_port_destroy( snd_port );
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+
+ /* Destroy file port */
+ status = pjmedia_port_destroy( file_port );
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+
+ /* Release application pool */
+ pj_pool_release( pool );
+
+ /* Destroy media endpoint. */
+ pjmedia_endpt_destroy( med_endpt );
+
+ /* Destroy pool factory */
+ pj_caching_pool_destroy( &cp );
+
+ /* Shutdown PJLIB */
+ pj_shutdown();
+
+
+ /* Done. */
+ return 0;
+}
diff --git a/pjsip-apps/src/samples/resampleplay.c b/pjsip-apps/src/samples/resampleplay.c
new file mode 100644
index 0000000..c73b2e3
--- /dev/null
+++ b/pjsip-apps/src/samples/resampleplay.c
@@ -0,0 +1,232 @@
+/* $Id: resampleplay.c 3664 2011-07-19 03:42:28Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/**
+ * \page page_pjmedia_samples_resampleplay_c Samples: Using Resample Port
+ *
+ * This example demonstrates how to use @ref PJMEDIA_RESAMPLE_PORT to
+ * change the sampling rate of the media streams.
+ *
+ * This file is pjsip-apps/src/samples/resampleplay.c
+ *
+ * \includelineno resampleplay.c
+ */
+
+#include <pjmedia.h>
+#include <pjlib-util.h>
+#include <pjlib.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "util.h"
+
+/* For logging purpose. */
+#define THIS_FILE "resampleplay.c"
+
+
+static const char *desc =
+" FILE \n"
+" \n"
+" resampleplay.c \n"
+" \n"
+" PURPOSE \n"
+" \n"
+" Demonstrate how use resample port to play a WAV file to sound \n"
+" device using different sampling rate. \n"
+" \n"
+" USAGE \n"
+" \n"
+" resampleplay [options] FILE.WAV \n"
+" \n"
+" where options: \n"
+SND_USAGE
+" \n"
+" The WAV file could have mono or stereo channels with arbitrary \n"
+" sampling rate, but MUST contain uncompressed (i.e. 16bit) PCM. \n";
+
+
+int main(int argc, char *argv[])
+{
+ pj_caching_pool cp;
+ pjmedia_endpt *med_endpt;
+ pj_pool_t *pool;
+ pjmedia_port *file_port;
+ pjmedia_port *resample_port;
+ pjmedia_snd_port *snd_port;
+ char tmp[10];
+ pj_status_t status;
+
+ int dev_id = -1;
+ int sampling_rate = CLOCK_RATE;
+ int channel_count = NCHANNELS;
+ int samples_per_frame = NSAMPLES;
+ int bits_per_sample = NBITS;
+ //int ptime;
+ //int down_samples;
+
+ /* Must init PJLIB first: */
+ status = pj_init();
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+
+ /* Get options */
+ if (get_snd_options(THIS_FILE, argc, argv, &dev_id, &sampling_rate,
+ &channel_count, &samples_per_frame, &bits_per_sample))
+ {
+ puts("");
+ puts(desc);
+ return 1;
+ }
+
+ if (!argv[pj_optind]) {
+ puts("Error: no file is specified");
+ puts(desc);
+ return 1;
+ }
+
+ /* Must create a pool factory before we can allocate any memory. */
+ pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);
+
+ /*
+ * Initialize media endpoint.
+ * This will implicitly initialize PJMEDIA too.
+ */
+ status = pjmedia_endpt_create(&cp.factory, NULL, 1, &med_endpt);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ /* Create memory pool for our file player */
+ pool = pj_pool_create( &cp.factory, /* pool factory */
+ "app", /* pool name. */
+ 4000, /* init size */
+ 4000, /* increment size */
+ NULL /* callback on error */
+ );
+
+ /* Create the file port. */
+ status = pjmedia_wav_player_port_create( pool, argv[pj_optind], 0, 0,
+ 0, &file_port);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to open file", status);
+ return 1;
+ }
+
+ /* File must have same number of channels. */
+ if (PJMEDIA_PIA_CCNT(&file_port->info) != (unsigned)channel_count) {
+ PJ_LOG(3,(THIS_FILE, "Error: file has different number of channels. "
+ "Perhaps you'd need -c option?"));
+ pjmedia_port_destroy(file_port);
+ return 1;
+ }
+
+ /* Calculate number of samples per frame to be taken from file port */
+ //ptime = samples_per_frame * 1000 / sampling_rate;
+
+ /* Create the resample port. */
+ status = pjmedia_resample_port_create( pool, file_port,
+ sampling_rate, 0,
+ &resample_port);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to create resample port", status);
+ return 1;
+ }
+
+ /* Create sound player port. */
+ status = pjmedia_snd_port_create(
+ pool, /* pool */
+ dev_id, /* device */
+ dev_id, /* device */
+ sampling_rate, /* clock rate. */
+ channel_count, /* # of channels. */
+ samples_per_frame, /* samples per frame. */
+ bits_per_sample, /* bits per sample. */
+ 0, /* options */
+ &snd_port /* returned port */
+ );
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to open sound device", status);
+ return 1;
+ }
+
+ /* Connect resample port to sound device */
+ status = pjmedia_snd_port_connect( snd_port, resample_port);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Error connecting sound ports", status);
+ return 1;
+ }
+
+
+ /* Dump memory usage */
+ dump_pool_usage(THIS_FILE, &cp);
+
+ /*
+ * File should be playing and looping now, using sound device's thread.
+ */
+
+
+ /* Sleep to allow log messages to flush */
+ pj_thread_sleep(100);
+
+
+ printf("Playing %s at sampling rate %d (original file sampling rate=%d)\n",
+ argv[pj_optind], sampling_rate,
+ PJMEDIA_PIA_SRATE(&file_port->info));
+ puts("");
+ puts("Press <ENTER> to stop playing and quit");
+
+ if (fgets(tmp, sizeof(tmp), stdin) == NULL) {
+ puts("EOF while reading stdin, will quit now..");
+ }
+
+ /* Start deinitialization: */
+
+
+ /* Destroy sound device */
+ status = pjmedia_snd_port_destroy( snd_port );
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+
+ /* Destroy resample port.
+ * This will destroy all downstream ports (e.g. the file port)
+ */
+ status = pjmedia_port_destroy( resample_port );
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+
+ /* Release application pool */
+ pj_pool_release( pool );
+
+ /* Destroy media endpoint. */
+ pjmedia_endpt_destroy( med_endpt );
+
+ /* Destroy pool factory */
+ pj_caching_pool_destroy( &cp );
+
+ /* Shutdown PJLIB */
+ pj_shutdown();
+
+
+ /* Done. */
+ return 0;
+
+}
+
+
+
diff --git a/pjsip-apps/src/samples/simple_pjsua.c b/pjsip-apps/src/samples/simple_pjsua.c
new file mode 100644
index 0000000..7716f7f
--- /dev/null
+++ b/pjsip-apps/src/samples/simple_pjsua.c
@@ -0,0 +1,201 @@
+/* $Id: simple_pjsua.c 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/**
+ * simple_pjsua.c
+ *
+ * This is a very simple but fully featured SIP user agent, with the
+ * following capabilities:
+ * - SIP registration
+ * - Making and receiving call
+ * - Audio/media to sound device.
+ *
+ * Usage:
+ * - To make outgoing call, start simple_pjsua with the URL of remote
+ * destination to contact.
+ * E.g.:
+ * simpleua sip:user@remote
+ *
+ * - Incoming calls will automatically be answered with 200.
+ *
+ * This program will quit once it has completed a single call.
+ */
+
+#include <pjsua-lib/pjsua.h>
+
+#define THIS_FILE "APP"
+
+#define SIP_DOMAIN "example.com"
+#define SIP_USER "alice"
+#define SIP_PASSWD "secret"
+
+
+/* Callback called by the library upon receiving incoming call */
+static void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id,
+ pjsip_rx_data *rdata)
+{
+ pjsua_call_info ci;
+
+ PJ_UNUSED_ARG(acc_id);
+ PJ_UNUSED_ARG(rdata);
+
+ pjsua_call_get_info(call_id, &ci);
+
+ PJ_LOG(3,(THIS_FILE, "Incoming call from %.*s!!",
+ (int)ci.remote_info.slen,
+ ci.remote_info.ptr));
+
+ /* Automatically answer incoming calls with 200/OK */
+ pjsua_call_answer(call_id, 200, NULL, NULL);
+}
+
+/* Callback called by the library when call's state has changed */
+static void on_call_state(pjsua_call_id call_id, pjsip_event *e)
+{
+ pjsua_call_info ci;
+
+ PJ_UNUSED_ARG(e);
+
+ pjsua_call_get_info(call_id, &ci);
+ PJ_LOG(3,(THIS_FILE, "Call %d state=%.*s", call_id,
+ (int)ci.state_text.slen,
+ ci.state_text.ptr));
+}
+
+/* Callback called by the library when call's media state has changed */
+static void on_call_media_state(pjsua_call_id call_id)
+{
+ pjsua_call_info ci;
+
+ pjsua_call_get_info(call_id, &ci);
+
+ if (ci.media_status == PJSUA_CALL_MEDIA_ACTIVE) {
+ // When media is active, connect call to sound device.
+ pjsua_conf_connect(ci.conf_slot, 0);
+ pjsua_conf_connect(0, ci.conf_slot);
+ }
+}
+
+/* Display error and exit application */
+static void error_exit(const char *title, pj_status_t status)
+{
+ pjsua_perror(THIS_FILE, title, status);
+ pjsua_destroy();
+ exit(1);
+}
+
+/*
+ * main()
+ *
+ * argv[1] may contain URL to call.
+ */
+int main(int argc, char *argv[])
+{
+ pjsua_acc_id acc_id;
+ pj_status_t status;
+
+ /* Create pjsua first! */
+ status = pjsua_create();
+ if (status != PJ_SUCCESS) error_exit("Error in pjsua_create()", status);
+
+ /* If argument is specified, it's got to be a valid SIP URL */
+ if (argc > 1) {
+ status = pjsua_verify_url(argv[1]);
+ if (status != PJ_SUCCESS) error_exit("Invalid URL in argv", status);
+ }
+
+ /* Init pjsua */
+ {
+ pjsua_config cfg;
+ pjsua_logging_config log_cfg;
+
+ pjsua_config_default(&cfg);
+ cfg.cb.on_incoming_call = &on_incoming_call;
+ cfg.cb.on_call_media_state = &on_call_media_state;
+ cfg.cb.on_call_state = &on_call_state;
+
+ pjsua_logging_config_default(&log_cfg);
+ log_cfg.console_level = 4;
+
+ status = pjsua_init(&cfg, &log_cfg, NULL);
+ if (status != PJ_SUCCESS) error_exit("Error in pjsua_init()", status);
+ }
+
+ /* Add UDP transport. */
+ {
+ pjsua_transport_config cfg;
+
+ pjsua_transport_config_default(&cfg);
+ cfg.port = 5060;
+ status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, &cfg, NULL);
+ if (status != PJ_SUCCESS) error_exit("Error creating transport", status);
+ }
+
+ /* Initialization is done, now start pjsua */
+ status = pjsua_start();
+ if (status != PJ_SUCCESS) error_exit("Error starting pjsua", status);
+
+ /* Register to SIP server by creating SIP account. */
+ {
+ pjsua_acc_config cfg;
+
+ pjsua_acc_config_default(&cfg);
+ cfg.id = pj_str("sip:" SIP_USER "@" SIP_DOMAIN);
+ cfg.reg_uri = pj_str("sip:" SIP_DOMAIN);
+ cfg.cred_count = 1;
+ cfg.cred_info[0].realm = pj_str(SIP_DOMAIN);
+ cfg.cred_info[0].scheme = pj_str("digest");
+ cfg.cred_info[0].username = pj_str(SIP_USER);
+ cfg.cred_info[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
+ cfg.cred_info[0].data = pj_str(SIP_PASSWD);
+
+ status = pjsua_acc_add(&cfg, PJ_TRUE, &acc_id);
+ if (status != PJ_SUCCESS) error_exit("Error adding account", status);
+ }
+
+ /* If URL is specified, make call to the URL. */
+ if (argc > 1) {
+ pj_str_t uri = pj_str(argv[1]);
+ status = pjsua_call_make_call(acc_id, &uri, 0, NULL, NULL, NULL);
+ if (status != PJ_SUCCESS) error_exit("Error making call", status);
+ }
+
+ /* Wait until user press "q" to quit. */
+ for (;;) {
+ char option[10];
+
+ puts("Press 'h' to hangup all calls, 'q' to quit");
+ if (fgets(option, sizeof(option), stdin) == NULL) {
+ puts("EOF while reading stdin, will quit now..");
+ break;
+ }
+
+ if (option[0] == 'q')
+ break;
+
+ if (option[0] == 'h')
+ pjsua_call_hangup_all();
+ }
+
+ /* Destroy pjsua */
+ pjsua_destroy();
+
+ return 0;
+}
diff --git a/pjsip-apps/src/samples/simpleua.c b/pjsip-apps/src/samples/simpleua.c
new file mode 100644
index 0000000..2906323
--- /dev/null
+++ b/pjsip-apps/src/samples/simpleua.c
@@ -0,0 +1,1030 @@
+/* $Id: simpleua.c 4051 2012-04-13 08:16:30Z ming $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+/**
+ * simpleua.c
+ *
+ * This is a very simple SIP user agent complete with media. The user
+ * agent should do a proper SDP negotiation and start RTP media once
+ * SDP negotiation has completed.
+ *
+ * This program does not register to SIP server.
+ *
+ * Capabilities to be demonstrated here:
+ * - Basic call
+ * - Should support IPv6 (not tested)
+ * - UDP transport at port 5060 (hard coded)
+ * - RTP socket at port 4000 (hard coded)
+ * - proper SDP negotiation
+ * - PCMA/PCMU codec only.
+ * - Audio/media to sound device.
+ *
+ *
+ * Usage:
+ * - To make outgoing call, start simpleua with the URL of remote
+ * destination to contact.
+ * E.g.:
+ * simpleua sip:user@remote
+ *
+ * - Incoming calls will automatically be answered with 180, then 200.
+ *
+ * This program does not disconnect call.
+ *
+ * This program will quit once it has completed a single call.
+ */
+
+/* Include all headers. */
+#include <pjsip.h>
+#include <pjmedia.h>
+#include <pjmedia-codec.h>
+#include <pjsip_ua.h>
+#include <pjsip_simple.h>
+#include <pjlib-util.h>
+#include <pjlib.h>
+
+/* For logging purpose. */
+#define THIS_FILE "simpleua.c"
+
+#include "util.h"
+
+
+/* Settings */
+#define AF pj_AF_INET() /* Change to pj_AF_INET6() for IPv6.
+ * PJ_HAS_IPV6 must be enabled and
+ * your system must support IPv6. */
+#if 0
+#define SIP_PORT 5080 /* Listening SIP port */
+#define RTP_PORT 5000 /* RTP port */
+#else
+#define SIP_PORT 5060 /* Listening SIP port */
+#define RTP_PORT 4000 /* RTP port */
+#endif
+
+#define MAX_MEDIA_CNT 2 /* Media count, set to 1 for audio
+ * only or 2 for audio and video */
+
+/*
+ * Static variables.
+ */
+
+static pj_bool_t g_complete; /* Quit flag. */
+static pjsip_endpoint *g_endpt; /* SIP endpoint. */
+static pj_caching_pool cp; /* Global pool factory. */
+
+static pjmedia_endpt *g_med_endpt; /* Media endpoint. */
+
+static pjmedia_transport_info g_med_tpinfo[MAX_MEDIA_CNT];
+ /* Socket info for media */
+static pjmedia_transport *g_med_transport[MAX_MEDIA_CNT];
+ /* Media stream transport */
+static pjmedia_sock_info g_sock_info[MAX_MEDIA_CNT];
+ /* Socket info array */
+
+/* Call variables: */
+static pjsip_inv_session *g_inv; /* Current invite session. */
+static pjmedia_stream *g_med_stream; /* Call's audio stream. */
+static pjmedia_snd_port *g_snd_port; /* Sound device. */
+
+#if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
+static pjmedia_vid_stream *g_med_vstream; /* Call's video stream. */
+static pjmedia_vid_port *g_vid_capturer;/* Call's video capturer. */
+static pjmedia_vid_port *g_vid_renderer;/* Call's video renderer. */
+#endif /* PJMEDIA_HAS_VIDEO */
+
+/*
+ * Prototypes:
+ */
+
+/* Callback to be called when SDP negotiation is done in the call: */
+static void call_on_media_update( pjsip_inv_session *inv,
+ pj_status_t status);
+
+/* Callback to be called when invite session's state has changed: */
+static void call_on_state_changed( pjsip_inv_session *inv,
+ pjsip_event *e);
+
+/* Callback to be called when dialog has forked: */
+static void call_on_forked(pjsip_inv_session *inv, pjsip_event *e);
+
+/* Callback to be called to handle incoming requests outside dialogs: */
+static pj_bool_t on_rx_request( pjsip_rx_data *rdata );
+
+
+
+
+/* This is a PJSIP module to be registered by application to handle
+ * incoming requests outside any dialogs/transactions. The main purpose
+ * here is to handle incoming INVITE request message, where we will
+ * create a dialog and INVITE session for it.
+ */
+static pjsip_module mod_simpleua =
+{
+ NULL, NULL, /* prev, next. */
+ { "mod-simpleua", 12 }, /* Name. */
+ -1, /* Id */
+ PJSIP_MOD_PRIORITY_APPLICATION, /* Priority */
+ NULL, /* load() */
+ NULL, /* start() */
+ NULL, /* stop() */
+ NULL, /* unload() */
+ &on_rx_request, /* on_rx_request() */
+ NULL, /* on_rx_response() */
+ NULL, /* on_tx_request. */
+ NULL, /* on_tx_response() */
+ NULL, /* on_tsx_state() */
+};
+
+
+/* Notification on incoming messages */
+static pj_bool_t logging_on_rx_msg(pjsip_rx_data *rdata)
+{
+ PJ_LOG(4,(THIS_FILE, "RX %d bytes %s from %s %s:%d:\n"
+ "%.*s\n"
+ "--end msg--",
+ rdata->msg_info.len,
+ pjsip_rx_data_get_info(rdata),
+ rdata->tp_info.transport->type_name,
+ rdata->pkt_info.src_name,
+ rdata->pkt_info.src_port,
+ (int)rdata->msg_info.len,
+ rdata->msg_info.msg_buf));
+
+ /* Always return false, otherwise messages will not get processed! */
+ return PJ_FALSE;
+}
+
+/* Notification on outgoing messages */
+static pj_status_t logging_on_tx_msg(pjsip_tx_data *tdata)
+{
+
+ /* Important note:
+ * tp_info field is only valid after outgoing messages has passed
+ * transport layer. So don't try to access tp_info when the module
+ * has lower priority than transport layer.
+ */
+
+ PJ_LOG(4,(THIS_FILE, "TX %d bytes %s to %s %s:%d:\n"
+ "%.*s\n"
+ "--end msg--",
+ (tdata->buf.cur - tdata->buf.start),
+ pjsip_tx_data_get_info(tdata),
+ tdata->tp_info.transport->type_name,
+ tdata->tp_info.dst_name,
+ tdata->tp_info.dst_port,
+ (int)(tdata->buf.cur - tdata->buf.start),
+ tdata->buf.start));
+
+ /* Always return success, otherwise message will not get sent! */
+ return PJ_SUCCESS;
+}
+
+/* The module instance. */
+static pjsip_module msg_logger =
+{
+ NULL, NULL, /* prev, next. */
+ { "mod-msg-log", 13 }, /* Name. */
+ -1, /* Id */
+ PJSIP_MOD_PRIORITY_TRANSPORT_LAYER-1,/* Priority */
+ NULL, /* load() */
+ NULL, /* start() */
+ NULL, /* stop() */
+ NULL, /* unload() */
+ &logging_on_rx_msg, /* on_rx_request() */
+ &logging_on_rx_msg, /* on_rx_response() */
+ &logging_on_tx_msg, /* on_tx_request. */
+ &logging_on_tx_msg, /* on_tx_response() */
+ NULL, /* on_tsx_state() */
+
+};
+
+
+/*
+ * main()
+ *
+ * If called with argument, treat argument as SIP URL to be called.
+ * Otherwise wait for incoming calls.
+ */
+int main(int argc, char *argv[])
+{
+ pj_pool_t *pool = NULL;
+ pj_status_t status;
+ unsigned i;
+
+ /* Must init PJLIB first: */
+ status = pj_init();
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ pj_log_set_level(5);
+
+ /* Then init PJLIB-UTIL: */
+ status = pjlib_util_init();
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+
+ /* Must create a pool factory before we can allocate any memory. */
+ pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);
+
+
+ /* Create global endpoint: */
+ {
+ const pj_str_t *hostname;
+ const char *endpt_name;
+
+ /* Endpoint MUST be assigned a globally unique name.
+ * The name will be used as the hostname in Warning header.
+ */
+
+ /* For this implementation, we'll use hostname for simplicity */
+ hostname = pj_gethostname();
+ endpt_name = hostname->ptr;
+
+ /* Create the endpoint: */
+
+ status = pjsip_endpt_create(&cp.factory, endpt_name,
+ &g_endpt);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+ }
+
+
+ /*
+ * Add UDP transport, with hard-coded port
+ * Alternatively, application can use pjsip_udp_transport_attach() to
+ * start UDP transport, if it already has an UDP socket (e.g. after it
+ * resolves the address with STUN).
+ */
+ {
+ pj_sockaddr addr;
+
+ pj_sockaddr_init(AF, &addr, NULL, (pj_uint16_t)SIP_PORT);
+
+ if (AF == pj_AF_INET()) {
+ status = pjsip_udp_transport_start( g_endpt, &addr.ipv4, NULL,
+ 1, NULL);
+ } else if (AF == pj_AF_INET6()) {
+ status = pjsip_udp_transport_start6(g_endpt, &addr.ipv6, NULL,
+ 1, NULL);
+ } else {
+ status = PJ_EAFNOTSUP;
+ }
+
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to start UDP transport", status);
+ return 1;
+ }
+ }
+
+
+ /*
+ * Init transaction layer.
+ * This will create/initialize transaction hash tables etc.
+ */
+ status = pjsip_tsx_layer_init_module(g_endpt);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+
+ /*
+ * Initialize UA layer module.
+ * This will create/initialize dialog hash tables etc.
+ */
+ status = pjsip_ua_init_module( g_endpt, NULL );
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+
+ /*
+ * Init invite session module.
+ * The invite session module initialization takes additional argument,
+ * i.e. a structure containing callbacks to be called on specific
+ * occurence of events.
+ *
+ * The on_state_changed and on_new_session callbacks are mandatory.
+ * Application must supply the callback function.
+ *
+ * We use on_media_update() callback in this application to start
+ * media transmission.
+ */
+ {
+ pjsip_inv_callback inv_cb;
+
+ /* Init the callback for INVITE session: */
+ pj_bzero(&inv_cb, sizeof(inv_cb));
+ inv_cb.on_state_changed = &call_on_state_changed;
+ inv_cb.on_new_session = &call_on_forked;
+ inv_cb.on_media_update = &call_on_media_update;
+
+ /* Initialize invite session module: */
+ status = pjsip_inv_usage_init(g_endpt, &inv_cb);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+ }
+
+ /* Initialize 100rel support */
+ status = pjsip_100rel_init_module(g_endpt);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+ /*
+ * Register our module to receive incoming requests.
+ */
+ status = pjsip_endpt_register_module( g_endpt, &mod_simpleua);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ /*
+ * Register message logger module.
+ */
+ status = pjsip_endpt_register_module( g_endpt, &msg_logger);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+
+ /*
+ * Initialize media endpoint.
+ * This will implicitly initialize PJMEDIA too.
+ */
+#if PJ_HAS_THREADS
+ status = pjmedia_endpt_create(&cp.factory, NULL, 1, &g_med_endpt);
+#else
+ status = pjmedia_endpt_create(&cp.factory,
+ pjsip_endpt_get_ioqueue(g_endpt),
+ 0, &g_med_endpt);
+#endif
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ /*
+ * Add PCMA/PCMU codec to the media endpoint.
+ */
+#if defined(PJMEDIA_HAS_G711_CODEC) && PJMEDIA_HAS_G711_CODEC!=0
+ status = pjmedia_codec_g711_init(g_med_endpt);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+#endif
+
+
+#if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
+ /* Init video subsystem */
+ pool = pjmedia_endpt_create_pool(g_med_endpt, "Video subsystem", 512, 512);
+ status = pjmedia_video_format_mgr_create(pool, 64, 0, NULL);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+ status = pjmedia_converter_mgr_create(pool, NULL);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+ status = pjmedia_vid_codec_mgr_create(pool, NULL);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+ status = pjmedia_vid_dev_subsys_init(&cp.factory);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+# if defined(PJMEDIA_HAS_FFMPEG_VID_CODEC) && PJMEDIA_HAS_FFMPEG_VID_CODEC!=0
+ /* Init ffmpeg video codecs */
+ status = pjmedia_codec_ffmpeg_vid_init(NULL, &cp.factory);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+# endif /* PJMEDIA_HAS_FFMPEG_VID_CODEC */
+
+#endif /* PJMEDIA_HAS_VIDEO */
+
+ /*
+ * Create media transport used to send/receive RTP/RTCP socket.
+ * One media transport is needed for each call. Application may
+ * opt to re-use the same media transport for subsequent calls.
+ */
+ for (i = 0; i < PJ_ARRAY_SIZE(g_med_transport); ++i) {
+ status = pjmedia_transport_udp_create3(g_med_endpt, AF, NULL, NULL,
+ RTP_PORT + i*2, 0,
+ &g_med_transport[i]);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to create media transport", status);
+ return 1;
+ }
+
+ /*
+ * Get socket info (address, port) of the media transport. We will
+ * need this info to create SDP (i.e. the address and port info in
+ * the SDP).
+ */
+ pjmedia_transport_info_init(&g_med_tpinfo[i]);
+ pjmedia_transport_get_info(g_med_transport[i], &g_med_tpinfo[i]);
+
+ pj_memcpy(&g_sock_info[i], &g_med_tpinfo[i].sock_info,
+ sizeof(pjmedia_sock_info));
+ }
+
+ /*
+ * If URL is specified, then make call immediately.
+ */
+ if (argc > 1) {
+ pj_sockaddr hostaddr;
+ char hostip[PJ_INET6_ADDRSTRLEN+2];
+ char temp[80];
+ pj_str_t dst_uri = pj_str(argv[1]);
+ pj_str_t local_uri;
+ pjsip_dialog *dlg;
+ pjmedia_sdp_session *local_sdp;
+ pjsip_tx_data *tdata;
+
+ if (pj_gethostip(AF, &hostaddr) != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to retrieve local host IP", status);
+ return 1;
+ }
+ pj_sockaddr_print(&hostaddr, hostip, sizeof(hostip), 2);
+
+ pj_ansi_sprintf(temp, "<sip:simpleuac@%s:%d>",
+ hostip, SIP_PORT);
+ local_uri = pj_str(temp);
+
+ /* Create UAC dialog */
+ status = pjsip_dlg_create_uac( pjsip_ua_instance(),
+ &local_uri, /* local URI */
+ &local_uri, /* local Contact */
+ &dst_uri, /* remote URI */
+ &dst_uri, /* remote target */
+ &dlg); /* dialog */
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to create UAC dialog", status);
+ return 1;
+ }
+
+ /* If we expect the outgoing INVITE to be challenged, then we should
+ * put the credentials in the dialog here, with something like this:
+ *
+ {
+ pjsip_cred_info cred[1];
+
+ cred[0].realm = pj_str("sip.server.realm");
+ cred[0].scheme = pj_str("digest");
+ cred[0].username = pj_str("theuser");
+ cred[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
+ cred[0].data = pj_str("thepassword");
+
+ pjsip_auth_clt_set_credentials( &dlg->auth_sess, 1, cred);
+ }
+ *
+ */
+
+
+ /* Get the SDP body to be put in the outgoing INVITE, by asking
+ * media endpoint to create one for us.
+ */
+ status = pjmedia_endpt_create_sdp( g_med_endpt, /* the media endpt */
+ dlg->pool, /* pool. */
+ MAX_MEDIA_CNT, /* # of streams */
+ g_sock_info, /* RTP sock info */
+ &local_sdp); /* the SDP result */
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+
+
+ /* Create the INVITE session, and pass the SDP returned earlier
+ * as the session's initial capability.
+ */
+ status = pjsip_inv_create_uac( dlg, local_sdp, 0, &g_inv);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ /* If we want the initial INVITE to travel to specific SIP proxies,
+ * then we should put the initial dialog's route set here. The final
+ * route set will be updated once a dialog has been established.
+ * To set the dialog's initial route set, we do it with something
+ * like this:
+ *
+ {
+ pjsip_route_hdr route_set;
+ pjsip_route_hdr *route;
+ const pj_str_t hname = { "Route", 5 };
+ char *uri = "sip:proxy.server;lr";
+
+ pj_list_init(&route_set);
+
+ route = pjsip_parse_hdr( dlg->pool, &hname,
+ uri, strlen(uri),
+ NULL);
+ PJ_ASSERT_RETURN(route != NULL, 1);
+ pj_list_push_back(&route_set, route);
+
+ pjsip_dlg_set_route_set(dlg, &route_set);
+ }
+ *
+ * Note that Route URI SHOULD have an ";lr" parameter!
+ */
+
+ /* Create initial INVITE request.
+ * This INVITE request will contain a perfectly good request and
+ * an SDP body as well.
+ */
+ status = pjsip_inv_invite(g_inv, &tdata);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+
+
+ /* Send initial INVITE request.
+ * From now on, the invite session's state will be reported to us
+ * via the invite session callbacks.
+ */
+ status = pjsip_inv_send_msg(g_inv, tdata);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+
+ } else {
+
+ /* No URL to make call to */
+
+ PJ_LOG(3,(THIS_FILE, "Ready to accept incoming calls..."));
+ }
+
+
+ /* Loop until one call is completed */
+ for (;!g_complete;) {
+ pj_time_val timeout = {0, 10};
+ pjsip_endpt_handle_events(g_endpt, &timeout);
+ }
+
+ /* On exit, dump current memory usage: */
+ dump_pool_usage(THIS_FILE, &cp);
+
+ /* Destroy audio ports. Destroy the audio port first
+ * before the stream since the audio port has threads
+ * that get/put frames to the stream.
+ */
+ if (g_snd_port)
+ pjmedia_snd_port_destroy(g_snd_port);
+
+#if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
+ /* Destroy video ports */
+ if (g_vid_capturer)
+ pjmedia_vid_port_destroy(g_vid_capturer);
+ if (g_vid_renderer)
+ pjmedia_vid_port_destroy(g_vid_renderer);
+#endif
+
+ /* Destroy streams */
+ if (g_med_stream)
+ pjmedia_stream_destroy(g_med_stream);
+#if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
+ if (g_med_vstream)
+ pjmedia_vid_stream_destroy(g_med_vstream);
+
+ /* Deinit ffmpeg codec */
+# if defined(PJMEDIA_HAS_FFMPEG_VID_CODEC) && PJMEDIA_HAS_FFMPEG_VID_CODEC!=0
+ pjmedia_codec_ffmpeg_vid_deinit();
+# endif
+
+#endif
+
+ /* Destroy media transports */
+ for (i = 0; i < MAX_MEDIA_CNT; ++i) {
+ if (g_med_transport[i])
+ pjmedia_transport_close(g_med_transport[i]);
+ }
+
+ /* Deinit pjmedia endpoint */
+ if (g_med_endpt)
+ pjmedia_endpt_destroy(g_med_endpt);
+
+ /* Deinit pjsip endpoint */
+ if (g_endpt)
+ pjsip_endpt_destroy(g_endpt);
+
+ /* Release pool */
+ if (pool)
+ pj_pool_release(pool);
+
+ return 0;
+}
+
+
+
+/*
+ * Callback when INVITE session state has changed.
+ * This callback is registered when the invite session module is initialized.
+ * We mostly want to know when the invite session has been disconnected,
+ * so that we can quit the application.
+ */
+static void call_on_state_changed( pjsip_inv_session *inv,
+ pjsip_event *e)
+{
+ PJ_UNUSED_ARG(e);
+
+ if (inv->state == PJSIP_INV_STATE_DISCONNECTED) {
+
+ PJ_LOG(3,(THIS_FILE, "Call DISCONNECTED [reason=%d (%s)]",
+ inv->cause,
+ pjsip_get_status_text(inv->cause)->ptr));
+
+ PJ_LOG(3,(THIS_FILE, "One call completed, application quitting..."));
+ g_complete = 1;
+
+ } else {
+
+ PJ_LOG(3,(THIS_FILE, "Call state changed to %s",
+ pjsip_inv_state_name(inv->state)));
+
+ }
+}
+
+
+/* This callback is called when dialog has forked. */
+static void call_on_forked(pjsip_inv_session *inv, pjsip_event *e)
+{
+ /* To be done... */
+ PJ_UNUSED_ARG(inv);
+ PJ_UNUSED_ARG(e);
+}
+
+
+/*
+ * Callback when incoming requests outside any transactions and any
+ * dialogs are received. We're only interested to hande incoming INVITE
+ * request, and we'll reject any other requests with 500 response.
+ */
+static pj_bool_t on_rx_request( pjsip_rx_data *rdata )
+{
+ pj_sockaddr hostaddr;
+ char temp[80], hostip[PJ_INET6_ADDRSTRLEN];
+ pj_str_t local_uri;
+ pjsip_dialog *dlg;
+ pjmedia_sdp_session *local_sdp;
+ pjsip_tx_data *tdata;
+ unsigned options = 0;
+ pj_status_t status;
+
+
+ /*
+ * Respond (statelessly) any non-INVITE requests with 500
+ */
+ if (rdata->msg_info.msg->line.req.method.id != PJSIP_INVITE_METHOD) {
+
+ if (rdata->msg_info.msg->line.req.method.id != PJSIP_ACK_METHOD) {
+ pj_str_t reason = pj_str("Simple UA unable to handle "
+ "this request");
+
+ pjsip_endpt_respond_stateless( g_endpt, rdata,
+ 500, &reason,
+ NULL, NULL);
+ }
+ return PJ_TRUE;
+ }
+
+
+ /*
+ * Reject INVITE if we already have an INVITE session in progress.
+ */
+ if (g_inv) {
+
+ pj_str_t reason = pj_str("Another call is in progress");
+
+ pjsip_endpt_respond_stateless( g_endpt, rdata,
+ 500, &reason,
+ NULL, NULL);
+ return PJ_TRUE;
+
+ }
+
+ /* Verify that we can handle the request. */
+ status = pjsip_inv_verify_request(rdata, &options, NULL, NULL,
+ g_endpt, NULL);
+ if (status != PJ_SUCCESS) {
+
+ pj_str_t reason = pj_str("Sorry Simple UA can not handle this INVITE");
+
+ pjsip_endpt_respond_stateless( g_endpt, rdata,
+ 500, &reason,
+ NULL, NULL);
+ return PJ_TRUE;
+ }
+
+ /*
+ * Generate Contact URI
+ */
+ if (pj_gethostip(AF, &hostaddr) != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to retrieve local host IP", status);
+ return PJ_TRUE;
+ }
+ pj_sockaddr_print(&hostaddr, hostip, sizeof(hostip), 2);
+
+ pj_ansi_sprintf(temp, "<sip:simpleuas@%s:%d>",
+ hostip, SIP_PORT);
+ local_uri = pj_str(temp);
+
+ /*
+ * Create UAS dialog.
+ */
+ status = pjsip_dlg_create_uas( pjsip_ua_instance(),
+ rdata,
+ &local_uri, /* contact */
+ &dlg);
+ if (status != PJ_SUCCESS) {
+ pjsip_endpt_respond_stateless(g_endpt, rdata, 500, NULL,
+ NULL, NULL);
+ return PJ_TRUE;
+ }
+
+ /*
+ * Get media capability from media endpoint:
+ */
+
+ status = pjmedia_endpt_create_sdp( g_med_endpt, rdata->tp_info.pool,
+ MAX_MEDIA_CNT, g_sock_info, &local_sdp);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, PJ_TRUE);
+
+
+ /*
+ * Create invite session, and pass both the UAS dialog and the SDP
+ * capability to the session.
+ */
+ status = pjsip_inv_create_uas( dlg, rdata, local_sdp, 0, &g_inv);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, PJ_TRUE);
+
+
+ /*
+ * Initially send 180 response.
+ *
+ * The very first response to an INVITE must be created with
+ * pjsip_inv_initial_answer(). Subsequent responses to the same
+ * transaction MUST use pjsip_inv_answer().
+ */
+ status = pjsip_inv_initial_answer(g_inv, rdata,
+ 180,
+ NULL, NULL, &tdata);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, PJ_TRUE);
+
+
+ /* Send the 180 response. */
+ status = pjsip_inv_send_msg(g_inv, tdata);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, PJ_TRUE);
+
+
+ /*
+ * Now create 200 response.
+ */
+ status = pjsip_inv_answer( g_inv,
+ 200, NULL, /* st_code and st_text */
+ NULL, /* SDP already specified */
+ &tdata);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, PJ_TRUE);
+
+ /*
+ * Send the 200 response.
+ */
+ status = pjsip_inv_send_msg(g_inv, tdata);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, PJ_TRUE);
+
+
+ /* Done.
+ * When the call is disconnected, it will be reported via the callback.
+ */
+
+ return PJ_TRUE;
+}
+
+
+
+/*
+ * Callback when SDP negotiation has completed.
+ * We are interested with this callback because we want to start media
+ * as soon as SDP negotiation is completed.
+ */
+static void call_on_media_update( pjsip_inv_session *inv,
+ pj_status_t status)
+{
+ pjmedia_stream_info stream_info;
+ const pjmedia_sdp_session *local_sdp;
+ const pjmedia_sdp_session *remote_sdp;
+ pjmedia_port *media_port;
+
+ if (status != PJ_SUCCESS) {
+
+ app_perror(THIS_FILE, "SDP negotiation has failed", status);
+
+ /* Here we should disconnect call if we're not in the middle
+ * of initializing an UAS dialog and if this is not a re-INVITE.
+ */
+ return;
+ }
+
+ /* Get local and remote SDP.
+ * We need both SDPs to create a media session.
+ */
+ status = pjmedia_sdp_neg_get_active_local(inv->neg, &local_sdp);
+
+ status = pjmedia_sdp_neg_get_active_remote(inv->neg, &remote_sdp);
+
+
+ /* Create stream info based on the media audio SDP. */
+ status = pjmedia_stream_info_from_sdp(&stream_info, inv->dlg->pool,
+ g_med_endpt,
+ local_sdp, remote_sdp, 0);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE,"Unable to create audio stream info",status);
+ return;
+ }
+
+ /* If required, we can also change some settings in the stream info,
+ * (such as jitter buffer settings, codec settings, etc) before we
+ * create the stream.
+ */
+
+ /* Create new audio media stream, passing the stream info, and also the
+ * media socket that we created earlier.
+ */
+ status = pjmedia_stream_create(g_med_endpt, inv->dlg->pool, &stream_info,
+ g_med_transport[0], NULL, &g_med_stream);
+ if (status != PJ_SUCCESS) {
+ app_perror( THIS_FILE, "Unable to create audio stream", status);
+ return;
+ }
+
+ /* Start the audio stream */
+ status = pjmedia_stream_start(g_med_stream);
+ if (status != PJ_SUCCESS) {
+ app_perror( THIS_FILE, "Unable to start audio stream", status);
+ return;
+ }
+
+ /* Get the media port interface of the audio stream.
+ * Media port interface is basicly a struct containing get_frame() and
+ * put_frame() function. With this media port interface, we can attach
+ * the port interface to conference bridge, or directly to a sound
+ * player/recorder device.
+ */
+ pjmedia_stream_get_port(g_med_stream, &media_port);
+
+ /* Create sound port */
+ pjmedia_snd_port_create(inv->pool,
+ PJMEDIA_AUD_DEFAULT_CAPTURE_DEV,
+ PJMEDIA_AUD_DEFAULT_PLAYBACK_DEV,
+ PJMEDIA_PIA_SRATE(&media_port->info),/* clock rate */
+ PJMEDIA_PIA_CCNT(&media_port->info),/* channel count */
+ PJMEDIA_PIA_SPF(&media_port->info), /* samples per frame*/
+ PJMEDIA_PIA_BITS(&media_port->info),/* bits per sample */
+ 0,
+ &g_snd_port);
+
+ if (status != PJ_SUCCESS) {
+ app_perror( THIS_FILE, "Unable to create sound port", status);
+ PJ_LOG(3,(THIS_FILE, "%d %d %d %d",
+ PJMEDIA_PIA_SRATE(&media_port->info),/* clock rate */
+ PJMEDIA_PIA_CCNT(&media_port->info),/* channel count */
+ PJMEDIA_PIA_SPF(&media_port->info), /* samples per frame*/
+ PJMEDIA_PIA_BITS(&media_port->info) /* bits per sample */
+ ));
+ return;
+ }
+
+ status = pjmedia_snd_port_connect(g_snd_port, media_port);
+
+
+ /* Get the media port interface of the second stream in the session,
+ * which is video stream. With this media port interface, we can attach
+ * the port directly to a renderer/capture video device.
+ */
+#if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
+ if (local_sdp->media_count > 1) {
+ pjmedia_vid_stream_info vstream_info;
+ pjmedia_vid_port_param vport_param;
+
+ pjmedia_vid_port_param_default(&vport_param);
+
+ /* Create stream info based on the media video SDP. */
+ status = pjmedia_vid_stream_info_from_sdp(&vstream_info,
+ inv->dlg->pool, g_med_endpt,
+ local_sdp, remote_sdp, 1);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE,"Unable to create video stream info",status);
+ return;
+ }
+
+ /* If required, we can also change some settings in the stream info,
+ * (such as jitter buffer settings, codec settings, etc) before we
+ * create the video stream.
+ */
+
+ /* Create new video media stream, passing the stream info, and also the
+ * media socket that we created earlier.
+ */
+ status = pjmedia_vid_stream_create(g_med_endpt, NULL, &vstream_info,
+ g_med_transport[1], NULL,
+ &g_med_vstream);
+ if (status != PJ_SUCCESS) {
+ app_perror( THIS_FILE, "Unable to create video stream", status);
+ return;
+ }
+
+ /* Start the video stream */
+ status = pjmedia_vid_stream_start(g_med_vstream);
+ if (status != PJ_SUCCESS) {
+ app_perror( THIS_FILE, "Unable to start video stream", status);
+ return;
+ }
+
+ if (vstream_info.dir & PJMEDIA_DIR_DECODING) {
+ status = pjmedia_vid_dev_default_param(
+ inv->pool, PJMEDIA_VID_DEFAULT_RENDER_DEV,
+ &vport_param.vidparam);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to get default param of video "
+ "renderer device", status);
+ return;
+ }
+
+ /* Get video stream port for decoding direction */
+ pjmedia_vid_stream_get_port(g_med_vstream, PJMEDIA_DIR_DECODING,
+ &media_port);
+
+ /* Set format */
+ pjmedia_format_copy(&vport_param.vidparam.fmt,
+ &media_port->info.fmt);
+ vport_param.vidparam.dir = PJMEDIA_DIR_RENDER;
+ vport_param.active = PJ_TRUE;
+
+ /* Create renderer */
+ status = pjmedia_vid_port_create(inv->pool, &vport_param,
+ &g_vid_renderer);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to create video renderer device",
+ status);
+ return;
+ }
+
+ /* Connect renderer to media_port */
+ status = pjmedia_vid_port_connect(g_vid_renderer, media_port,
+ PJ_FALSE);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to connect renderer to stream",
+ status);
+ return;
+ }
+ }
+
+ /* Create capturer */
+ if (vstream_info.dir & PJMEDIA_DIR_ENCODING) {
+ status = pjmedia_vid_dev_default_param(
+ inv->pool, PJMEDIA_VID_DEFAULT_CAPTURE_DEV,
+ &vport_param.vidparam);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to get default param of video "
+ "capture device", status);
+ return;
+ }
+
+ /* Get video stream port for decoding direction */
+ pjmedia_vid_stream_get_port(g_med_vstream, PJMEDIA_DIR_ENCODING,
+ &media_port);
+
+ /* Get capturer format from stream info */
+ pjmedia_format_copy(&vport_param.vidparam.fmt,
+ &media_port->info.fmt);
+ vport_param.vidparam.dir = PJMEDIA_DIR_CAPTURE;
+ vport_param.active = PJ_TRUE;
+
+ /* Create capturer */
+ status = pjmedia_vid_port_create(inv->pool, &vport_param,
+ &g_vid_capturer);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to create video capture device",
+ status);
+ return;
+ }
+
+ /* Connect capturer to media_port */
+ status = pjmedia_vid_port_connect(g_vid_capturer, media_port,
+ PJ_FALSE);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to connect capturer to stream",
+ status);
+ return;
+ }
+ }
+
+ /* Start streaming */
+ if (g_vid_renderer) {
+ status = pjmedia_vid_port_start(g_vid_renderer);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to start video renderer",
+ status);
+ return;
+ }
+ }
+ if (g_vid_capturer) {
+ status = pjmedia_vid_port_start(g_vid_capturer);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to start video capturer",
+ status);
+ return;
+ }
+ }
+ }
+#endif /* PJMEDIA_HAS_VIDEO */
+
+ /* Done with media. */
+}
+
+
diff --git a/pjsip-apps/src/samples/sipecho.c b/pjsip-apps/src/samples/sipecho.c
new file mode 100644
index 0000000..6d1ab2d
--- /dev/null
+++ b/pjsip-apps/src/samples/sipecho.c
@@ -0,0 +1,688 @@
+/* $Id: sipecho.c 4148 2012-05-31 12:21:59Z bennylp $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+/**
+ * sipecho.c
+ *
+ * - Accepts incoming calls and echoes back SDP and any media.
+ * - Specify URI in cmdline argument to make call
+ * - Accepts registration too!
+ */
+
+/* Include all headers. */
+#include <pjsip.h>
+#include <pjmedia/sdp.h>
+#include <pjsip_ua.h>
+#include <pjlib-util.h>
+#include <pjlib.h>
+
+/* For logging purpose. */
+#define THIS_FILE "sipecho.c"
+
+#include "util.h"
+
+
+/* Settings */
+#define MAX_CALLS 8
+
+typedef struct call_t
+{
+ pjsip_inv_session *inv;
+} call_t;
+
+static struct app_t
+{
+ pj_caching_pool cp;
+ pj_pool_t *pool;
+
+ pjsip_endpoint *sip_endpt;
+ //pjmedia_endpt *med_endpt;
+
+ call_t call[MAX_CALLS];
+
+ pj_bool_t quit;
+ pj_thread_t *worker_thread;
+
+ pj_bool_t enable_msg_logging;
+} app;
+
+/*
+ * Prototypes:
+ */
+
+static void call_on_media_update(pjsip_inv_session *inv, pj_status_t status);
+static void call_on_state_changed(pjsip_inv_session *inv, pjsip_event *e);
+static void call_on_rx_offer(pjsip_inv_session *inv, const pjmedia_sdp_session *offer);
+static void call_on_forked(pjsip_inv_session *inv, pjsip_event *e);
+static pj_bool_t on_rx_request( pjsip_rx_data *rdata );
+
+/* Globals */
+static int sip_af;
+static int sip_port = 5060;
+static pj_bool_t sip_tcp;
+
+/* This is a PJSIP module to be registered by application to handle
+ * incoming requests outside any dialogs/transactions. The main purpose
+ * here is to handle incoming INVITE request message, where we will
+ * create a dialog and INVITE session for it.
+ */
+static pjsip_module mod_sipecho =
+{
+ NULL, NULL, /* prev, next. */
+ { "mod-sipecho", 11 }, /* Name. */
+ -1, /* Id */
+ PJSIP_MOD_PRIORITY_APPLICATION, /* Priority */
+ NULL, /* load() */
+ NULL, /* start() */
+ NULL, /* stop() */
+ NULL, /* unload() */
+ &on_rx_request, /* on_rx_request() */
+ NULL, /* on_rx_response() */
+ NULL, /* on_tx_request. */
+ NULL, /* on_tx_response() */
+ NULL, /* on_tsx_state() */
+};
+
+/* Notification on incoming messages */
+static pj_bool_t logging_on_rx_msg(pjsip_rx_data *rdata)
+{
+ if (!app.enable_msg_logging)
+ return PJ_FALSE;
+
+ PJ_LOG(3,(THIS_FILE, "RX %d bytes %s from %s %s:%d:\n"
+ "%.*s\n"
+ "--end msg--",
+ rdata->msg_info.len,
+ pjsip_rx_data_get_info(rdata),
+ rdata->tp_info.transport->type_name,
+ rdata->pkt_info.src_name,
+ rdata->pkt_info.src_port,
+ (int)rdata->msg_info.len,
+ rdata->msg_info.msg_buf));
+ return PJ_FALSE;
+}
+
+/* Notification on outgoing messages */
+static pj_status_t logging_on_tx_msg(pjsip_tx_data *tdata)
+{
+ if (!app.enable_msg_logging)
+ return PJ_SUCCESS;
+
+ PJ_LOG(3,(THIS_FILE, "TX %d bytes %s to %s %s:%d:\n"
+ "%.*s\n"
+ "--end msg--",
+ (tdata->buf.cur - tdata->buf.start),
+ pjsip_tx_data_get_info(tdata),
+ tdata->tp_info.transport->type_name,
+ tdata->tp_info.dst_name,
+ tdata->tp_info.dst_port,
+ (int)(tdata->buf.cur - tdata->buf.start),
+ tdata->buf.start));
+ return PJ_SUCCESS;
+}
+
+/* The module instance. */
+static pjsip_module msg_logger =
+{
+ NULL, NULL, /* prev, next. */
+ { "mod-msg-log", 13 }, /* Name. */
+ -1, /* Id */
+ PJSIP_MOD_PRIORITY_TRANSPORT_LAYER-1,/* Priority */
+ NULL, /* load() */
+ NULL, /* start() */
+ NULL, /* stop() */
+ NULL, /* unload() */
+ &logging_on_rx_msg, /* on_rx_request() */
+ &logging_on_rx_msg, /* on_rx_response() */
+ &logging_on_tx_msg, /* on_tx_request. */
+ &logging_on_tx_msg, /* on_tx_response() */
+ NULL, /* on_tsx_state() */
+
+};
+
+static int worker_proc(void *arg)
+{
+ PJ_UNUSED_ARG(arg);
+
+ while (!app.quit) {
+ pj_time_val interval = { 0, 20 };
+ pjsip_endpt_handle_events(app.sip_endpt, &interval);
+ }
+
+ return 0;
+}
+
+static void hangup_all(void)
+{
+ unsigned i;
+ for (i=0; i<MAX_CALLS; ++i) {
+ call_t *call = &app.call[i];
+
+ if (call->inv && call->inv->state <= PJSIP_INV_STATE_CONFIRMED) {
+ pj_status_t status;
+ pjsip_tx_data *tdata;
+
+ status = pjsip_inv_end_session(call->inv, PJSIP_SC_BUSY_HERE, NULL, &tdata);
+ if (status==PJ_SUCCESS && tdata)
+ pjsip_inv_send_msg(call->inv, tdata);
+ }
+ }
+}
+
+static void destroy_stack(void)
+{
+ enum { WAIT_CLEAR = 5000, WAIT_INTERVAL = 500 };
+ unsigned i;
+
+ PJ_LOG(3,(THIS_FILE, "Shutting down.."));
+
+ /* Wait until all clear */
+ hangup_all();
+ for (i=0; i<WAIT_CLEAR/WAIT_INTERVAL; ++i) {
+ unsigned j;
+
+ for (j=0; j<MAX_CALLS; ++j) {
+ call_t *call = &app.call[j];
+ if (call->inv && call->inv->state <= PJSIP_INV_STATE_CONFIRMED)
+ break;
+ }
+
+ if (j==MAX_CALLS)
+ return;
+
+ pj_thread_sleep(WAIT_INTERVAL);
+ }
+
+ app.quit = PJ_TRUE;
+ if (app.worker_thread) {
+ pj_thread_join(app.worker_thread);
+ app.worker_thread = NULL;
+ }
+
+ //if (app.med_endpt)
+ //pjmedia_endpt_destroy(app.med_endpt);
+
+ if (app.sip_endpt)
+ pjsip_endpt_destroy(app.sip_endpt);
+
+ if (app.pool)
+ pj_pool_release(app.pool);
+
+ dump_pool_usage(THIS_FILE, &app.cp);
+ pj_caching_pool_destroy(&app.cp);
+}
+
+#define CHECK_STATUS() do { if (status != PJ_SUCCESS) return status; } while (0)
+
+static pj_status_t init_stack()
+{
+ pj_sockaddr addr;
+ pjsip_inv_callback inv_cb;
+ pj_status_t status;
+
+ pj_log_set_level(3);
+
+ status = pjlib_util_init();
+ CHECK_STATUS();
+
+ pj_caching_pool_init(&app.cp, NULL, 0);
+ app.pool = pj_pool_create( &app.cp.factory, "sipecho", 512, 512, 0);
+
+ status = pjsip_endpt_create(&app.cp.factory, NULL, &app.sip_endpt);
+ CHECK_STATUS();
+
+ pj_log_set_level(4);
+ pj_sockaddr_init((pj_uint16_t)sip_af, &addr, NULL, (pj_uint16_t)sip_port);
+ if (sip_af == pj_AF_INET()) {
+ if (sip_tcp) {
+ status = pjsip_tcp_transport_start( app.sip_endpt, &addr.ipv4, 1,
+ NULL);
+ } else {
+ status = pjsip_udp_transport_start( app.sip_endpt, &addr.ipv4,
+ NULL, 1, NULL);
+ }
+ } else if (sip_af == pj_AF_INET6()) {
+ status = pjsip_udp_transport_start6(app.sip_endpt, &addr.ipv6,
+ NULL, 1, NULL);
+ } else {
+ status = PJ_EAFNOTSUP;
+ }
+
+ pj_log_set_level(3);
+ CHECK_STATUS();
+
+ status = pjsip_tsx_layer_init_module(app.sip_endpt) ||
+ pjsip_ua_init_module( app.sip_endpt, NULL );
+ CHECK_STATUS();
+
+ pj_bzero(&inv_cb, sizeof(inv_cb));
+ inv_cb.on_state_changed = &call_on_state_changed;
+ inv_cb.on_new_session = &call_on_forked;
+ inv_cb.on_media_update = &call_on_media_update;
+ inv_cb.on_rx_offer = &call_on_rx_offer;
+
+ status = pjsip_inv_usage_init(app.sip_endpt, &inv_cb) ||
+ pjsip_100rel_init_module(app.sip_endpt) ||
+ pjsip_endpt_register_module( app.sip_endpt, &mod_sipecho) ||
+ pjsip_endpt_register_module( app.sip_endpt, &msg_logger) ||
+ //pjmedia_endpt_create(&app.cp.factory,
+ // pjsip_endpt_get_ioqueue(app.sip_endpt),
+ // 0, &app.med_endpt) ||
+ pj_thread_create(app.pool, "sipecho", &worker_proc, NULL, 0, 0,
+ &app.worker_thread);
+ CHECK_STATUS();
+
+ return PJ_SUCCESS;
+}
+
+static void destroy_call(call_t *call)
+{
+ call->inv = NULL;
+}
+
+static pjmedia_sdp_attr * find_remove_sdp_attrs(unsigned *cnt,
+ pjmedia_sdp_attr *attr[],
+ unsigned cnt_attr_to_remove,
+ const char* attr_to_remove[])
+{
+ pjmedia_sdp_attr *found_attr = NULL;
+ int i;
+
+ for (i=0; i<(int)*cnt; ++i) {
+ unsigned j;
+ for (j=0; j<cnt_attr_to_remove; ++j) {
+ if (pj_strcmp2(&attr[i]->name, attr_to_remove[j])==0) {
+ if (!found_attr) found_attr = attr[i];
+ pj_array_erase(attr, sizeof(attr[0]), *cnt, i);
+ --(*cnt);
+ --i;
+ break;
+ }
+ }
+ }
+
+ return found_attr;
+}
+
+static pjmedia_sdp_session *create_answer(int call_num, pj_pool_t *pool,
+ const pjmedia_sdp_session *offer)
+{
+ const char* dir_attrs[] = { "sendrecv", "sendonly", "recvonly", "inactive" };
+ const char *ice_attrs[] = {"ice-pwd", "ice-ufrag", "candidate"};
+ pjmedia_sdp_session *answer = pjmedia_sdp_session_clone(pool, offer);
+ pjmedia_sdp_attr *sess_dir_attr = NULL;
+ unsigned mi;
+
+ PJ_LOG(3,(THIS_FILE, "Call %d: creating answer:", call_num));
+
+ answer->name = pj_str("sipecho");
+ sess_dir_attr = find_remove_sdp_attrs(&answer->attr_count, answer->attr,
+ PJ_ARRAY_SIZE(dir_attrs),
+ dir_attrs);
+
+ for (mi=0; mi<answer->media_count; ++mi) {
+ pjmedia_sdp_media *m = answer->media[mi];
+ pjmedia_sdp_attr *m_dir_attr;
+ pjmedia_sdp_attr *dir_attr;
+ const char *our_dir = NULL;
+ pjmedia_sdp_conn *c;
+
+ /* Match direction */
+ m_dir_attr = find_remove_sdp_attrs(&m->attr_count, m->attr,
+ PJ_ARRAY_SIZE(dir_attrs),
+ dir_attrs);
+ dir_attr = m_dir_attr ? m_dir_attr : sess_dir_attr;
+
+ if (dir_attr) {
+ if (pj_strcmp2(&dir_attr->name, "sendonly")==0)
+ our_dir = "recvonly";
+ else if (pj_strcmp2(&dir_attr->name, "inactive")==0)
+ our_dir = "inactive";
+ else if (pj_strcmp2(&dir_attr->name, "recvonly")==0)
+ our_dir = "inactive";
+
+ if (our_dir) {
+ dir_attr = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_attr);
+ dir_attr->name = pj_str((char*)our_dir);
+ m->attr[m->attr_count++] = dir_attr;
+ }
+ }
+
+ /* Remove ICE attributes */
+ find_remove_sdp_attrs(&m->attr_count, m->attr, PJ_ARRAY_SIZE(ice_attrs), ice_attrs);
+
+ /* Done */
+ c = m->conn ? m->conn : answer->conn;
+ PJ_LOG(3,(THIS_FILE, " Media %d, %.*s: %s <--> %.*s:%d",
+ mi, (int)m->desc.media.slen, m->desc.media.ptr,
+ (our_dir ? our_dir : "sendrecv"),
+ (int)c->addr.slen, c->addr.ptr, m->desc.port));
+ }
+
+ return answer;
+}
+
+static void call_on_state_changed( pjsip_inv_session *inv,
+ pjsip_event *e)
+{
+ call_t *call = (call_t*)inv->mod_data[mod_sipecho.id];
+ if (!call)
+ return;
+
+ PJ_UNUSED_ARG(e);
+ if (inv->state == PJSIP_INV_STATE_DISCONNECTED) {
+ PJ_LOG(3,(THIS_FILE, "Call %d: DISCONNECTED [reason=%d (%s)]",
+ call - app.call, inv->cause,
+ pjsip_get_status_text(inv->cause)->ptr));
+ destroy_call(call);
+ } else {
+ PJ_LOG(3,(THIS_FILE, "Call %d: state changed to %s",
+ call - app.call, pjsip_inv_state_name(inv->state)));
+ }
+}
+
+static void call_on_rx_offer(pjsip_inv_session *inv, const pjmedia_sdp_session *offer)
+{
+ call_t *call = (call_t*) inv->mod_data[mod_sipecho.id];
+ pjsip_inv_set_sdp_answer(inv, create_answer(call - app.call, inv->pool_prov, offer));
+}
+
+static void call_on_forked(pjsip_inv_session *inv, pjsip_event *e)
+{
+ PJ_UNUSED_ARG(inv);
+ PJ_UNUSED_ARG(e);
+}
+
+static pj_bool_t on_rx_request( pjsip_rx_data *rdata )
+{
+ pj_sockaddr hostaddr;
+ char temp[80], hostip[PJ_INET6_ADDRSTRLEN];
+ pj_str_t local_uri;
+ pjsip_dialog *dlg;
+ pjsip_rdata_sdp_info *sdp_info;
+ pjmedia_sdp_session *answer = NULL;
+ pjsip_tx_data *tdata = NULL;
+ call_t *call = NULL;
+ unsigned i;
+ pj_status_t status;
+
+ PJ_LOG(3,(THIS_FILE, "RX %.*s from %s",
+ (int)rdata->msg_info.msg->line.req.method.name.slen,
+ rdata->msg_info.msg->line.req.method.name.ptr,
+ rdata->pkt_info.src_name));
+
+ if (rdata->msg_info.msg->line.req.method.id == PJSIP_REGISTER_METHOD) {
+ /* Let me be a registrar! */
+ pjsip_hdr hdr_list, *h;
+ pjsip_msg *msg;
+ int expires = -1;
+
+ pj_list_init(&hdr_list);
+ msg = rdata->msg_info.msg;
+ h = (pjsip_hdr*)pjsip_msg_find_hdr(msg, PJSIP_H_EXPIRES, NULL);
+ if (h) {
+ expires = ((pjsip_expires_hdr*)h)->ivalue;
+ pj_list_push_back(&hdr_list, pjsip_hdr_clone(rdata->tp_info.pool, h));
+ PJ_LOG(3,(THIS_FILE, " Expires=%d", expires));
+ }
+ if (expires != 0) {
+ h = (pjsip_hdr*)pjsip_msg_find_hdr(msg, PJSIP_H_CONTACT, NULL);
+ if (h)
+ pj_list_push_back(&hdr_list, pjsip_hdr_clone(rdata->tp_info.pool, h));
+ }
+
+ pjsip_endpt_respond(app.sip_endpt, &mod_sipecho, rdata, 200, NULL,
+ &hdr_list, NULL, NULL);
+ return PJ_TRUE;
+ }
+
+ if (rdata->msg_info.msg->line.req.method.id != PJSIP_INVITE_METHOD) {
+ if (rdata->msg_info.msg->line.req.method.id != PJSIP_ACK_METHOD) {
+ pj_str_t reason = pj_str("Go away");
+ pjsip_endpt_respond_stateless( app.sip_endpt, rdata,
+ 400, &reason,
+ NULL, NULL);
+ }
+ return PJ_TRUE;
+ }
+
+ sdp_info = pjsip_rdata_get_sdp_info(rdata);
+ if (!sdp_info || !sdp_info->sdp) {
+ pj_str_t reason = pj_str("Require valid offer");
+ pjsip_endpt_respond_stateless( app.sip_endpt, rdata,
+ 400, &reason,
+ NULL, NULL);
+ }
+
+ for (i=0; i<MAX_CALLS; ++i) {
+ if (app.call[i].inv == NULL) {
+ call = &app.call[i];
+ break;
+ }
+ }
+
+ if (i==MAX_CALLS) {
+ pj_str_t reason = pj_str("We're full");
+ pjsip_endpt_respond_stateless( app.sip_endpt, rdata,
+ PJSIP_SC_BUSY_HERE, &reason,
+ NULL, NULL);
+ return PJ_TRUE;
+ }
+
+ /* Generate Contact URI */
+ status = pj_gethostip(sip_af, &hostaddr);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to retrieve local host IP", status);
+ return PJ_TRUE;
+ }
+ pj_sockaddr_print(&hostaddr, hostip, sizeof(hostip), 2);
+ pj_ansi_sprintf(temp, "<sip:sipecho@%s:%d>", hostip, sip_port);
+ local_uri = pj_str(temp);
+
+ status = pjsip_dlg_create_uas( pjsip_ua_instance(), rdata,
+ &local_uri, &dlg);
+
+ if (status == PJ_SUCCESS)
+ answer = create_answer(call-app.call, dlg->pool, sdp_info->sdp);
+ if (status == PJ_SUCCESS)
+ status = pjsip_inv_create_uas( dlg, rdata, answer, 0, &call->inv);
+ if (status == PJ_SUCCESS)
+ status = pjsip_inv_initial_answer(call->inv, rdata, 100,
+ NULL, NULL, &tdata);
+ if (status == PJ_SUCCESS)
+ status = pjsip_inv_send_msg(call->inv, tdata);
+
+ if (status == PJ_SUCCESS)
+ status = pjsip_inv_answer(call->inv, 180, NULL,
+ NULL, &tdata);
+ if (status == PJ_SUCCESS)
+ status = pjsip_inv_send_msg(call->inv, tdata);
+
+ if (status == PJ_SUCCESS)
+ status = pjsip_inv_answer(call->inv, 200, NULL,
+ NULL, &tdata);
+ if (status == PJ_SUCCESS)
+ status = pjsip_inv_send_msg(call->inv, tdata);
+
+ if (status != PJ_SUCCESS) {
+ pjsip_endpt_respond_stateless( app.sip_endpt, rdata,
+ 500, NULL, NULL, NULL);
+ destroy_call(call);
+ } else {
+ call->inv->mod_data[mod_sipecho.id] = call;
+ }
+
+ return PJ_TRUE;
+}
+
+static void call_on_media_update( pjsip_inv_session *inv,
+ pj_status_t status)
+{
+ PJ_UNUSED_ARG(inv);
+ PJ_UNUSED_ARG(status);
+}
+
+
+static void usage()
+{
+ printf("\nUsage: sipecho OPTIONS\n");
+ printf("\n");
+ printf("where OPTIONS:\n");
+ printf(" --local-port, -p PORT Bind to port PORT.\n");
+ printf(" --tcp, -t Listen to TCP instead.\n");
+ printf(" --ipv6, -6 Use IPv6 instead.\n");
+ printf(" --help, -h Show this help page.\n");
+}
+
+/* main()
+ *
+ * If called with argument, treat argument as SIP URL to be called.
+ * Otherwise wait for incoming calls.
+ */
+int main(int argc, char *argv[])
+{
+ struct pj_getopt_option long_options[] = {
+ { "local-port", 1, 0, 'p' },
+ { "tcp", 0, 0, 't' },
+ { "ipv6", 0, 0, '6' },
+ { "help", 0, 0, 'h' }
+ };
+ int c, option_index;
+
+ pj_log_set_level(5);
+
+ pj_init();
+
+ sip_af = pj_AF_INET();
+
+ pj_optind = 0;
+ while ((c = pj_getopt_long(argc, argv, "p:t6h", long_options,
+ &option_index)) != -1)
+ {
+ switch (c) {
+ case 'p':
+ sip_port = atoi(pj_optarg);
+ break;
+ case 't':
+ sip_tcp = PJ_TRUE;
+ break;
+ case 'h':
+ usage();
+ return 0;
+ case '6':
+ sip_af = pj_AF_INET6();
+ break;
+ default:
+ PJ_LOG(1,(THIS_FILE,
+ "Argument \"%s\" is not valid. Use --help to see help",
+ argv[pj_optind-1]));
+ return -1;
+ }
+ }
+
+ if (init_stack())
+ goto on_error;
+
+ /* If URL is specified, then make call immediately. */
+ if (pj_optind != argc) {
+ pj_sockaddr hostaddr;
+ char hostip[PJ_INET6_ADDRSTRLEN+2];
+ char temp[80];
+ call_t *call;
+ pj_str_t dst_uri = pj_str(argv[pj_optind]);
+ pj_str_t local_uri;
+ pjsip_dialog *dlg;
+ pj_status_t status;
+ pjsip_tx_data *tdata;
+
+ if (pj_gethostip(sip_af, &hostaddr) != PJ_SUCCESS) {
+ PJ_LOG(1,(THIS_FILE, "Unable to retrieve local host IP"));
+ goto on_error;
+ }
+ pj_sockaddr_print(&hostaddr, hostip, sizeof(hostip), 2);
+
+ pj_ansi_sprintf(temp, "<sip:sipecho@%s:%d>",
+ hostip, sip_port);
+ local_uri = pj_str(temp);
+
+ call = &app.call[0];
+
+ status = pjsip_dlg_create_uac( pjsip_ua_instance(),
+ &local_uri, /* local URI */
+ &local_uri, /* local Contact */
+ &dst_uri, /* remote URI */
+ &dst_uri, /* remote target */
+ &dlg); /* dialog */
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to create UAC dialog", status);
+ return 1;
+ }
+
+ status = pjsip_inv_create_uac( dlg, NULL, 0, &call->inv);
+ if (status != PJ_SUCCESS) goto on_error;
+
+ call->inv->mod_data[mod_sipecho.id] = call;
+
+ status = pjsip_inv_invite(call->inv, &tdata);
+ if (status != PJ_SUCCESS) goto on_error;
+
+ status = pjsip_inv_send_msg(call->inv, tdata);
+ if (status != PJ_SUCCESS) goto on_error;
+
+ puts("Press ENTER to quit...");
+ } else {
+ puts("Ready for incoming calls. Press ENTER to quit...");
+ }
+
+ for (;;) {
+ char s[10];
+
+ printf("\nMenu:\n"
+ " h Hangup all calls\n"
+ " l %s message logging\n"
+ " q Quit\n",
+ (app.enable_msg_logging? "Disable" : "Enable"));
+
+ if (fgets(s, sizeof(s), stdin) == NULL)
+ continue;
+
+ if (s[0]=='q')
+ break;
+ switch (s[0]) {
+ case 'l':
+ app.enable_msg_logging = !app.enable_msg_logging;
+ break;
+ case 'h':
+ hangup_all();
+ break;
+ }
+ }
+
+ destroy_stack();
+
+ puts("Bye bye..");
+ return 0;
+
+on_error:
+ puts("An error has occurred. run a debugger..");
+ return 1;
+}
+
diff --git a/pjsip-apps/src/samples/siprtp.c b/pjsip-apps/src/samples/siprtp.c
new file mode 100644
index 0000000..2bd478a
--- /dev/null
+++ b/pjsip-apps/src/samples/siprtp.c
@@ -0,0 +1,2189 @@
+/* $Id: siprtp.c 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+
+
+
+/* Usage */
+static const char *USAGE =
+" PURPOSE: \n"
+" This program establishes SIP INVITE session and media, and calculate \n"
+" the media quality (packet lost, jitter, rtt, etc.). Unlike normal \n"
+" pjmedia applications, this program bypasses all pjmedia stream \n"
+" framework and transmit encoded RTP packets manually using own thread. \n"
+"\n"
+" USAGE:\n"
+" siprtp [options] => to start in server mode\n"
+" siprtp [options] URL => to start in client mode\n"
+"\n"
+" Program options:\n"
+" --count=N, -c Set number of calls to create (default:1) \n"
+" --gap=N -g Set call gapping to N msec (default:0)\n"
+" --duration=SEC, -d Set maximum call duration (default:unlimited) \n"
+" --auto-quit, -q Quit when calls have been completed (default:no)\n"
+" --call-report -R Display report on call termination (default:yes)\n"
+"\n"
+" Address and ports options:\n"
+" --local-port=PORT,-p Set local SIP port (default: 5060)\n"
+" --rtp-port=PORT, -r Set start of RTP port (default: 4000)\n"
+" --ip-addr=IP, -i Set local IP address to use (otherwise it will\n"
+" try to determine local IP address from hostname)\n"
+"\n"
+" Logging Options:\n"
+" --log-level=N, -l Set log verbosity level (default=5)\n"
+" --app-log-level=N Set app screen log verbosity (default=3)\n"
+" --log-file=FILE Write log to file FILE\n"
+" --report-file=FILE Write report to file FILE\n"
+"\n"
+/* Don't support this anymore, because codec is properly examined in
+ pjmedia_session_info_from_sdp() function.
+
+" Codec Options:\n"
+" --a-pt=PT Set audio payload type to PT (default=0)\n"
+" --a-name=NAME Set audio codec name to NAME (default=pcmu)\n"
+" --a-clock=RATE Set audio codec rate to RATE Hz (default=8000Hz)\n"
+" --a-bitrate=BPS Set audio codec bitrate to BPS (default=64000bps)\n"
+" --a-ptime=MS Set audio frame time to MS msec (default=20ms)\n"
+*/
+;
+
+
+/* Include all headers. */
+#include <pjsip.h>
+#include <pjmedia.h>
+#include <pjmedia-codec.h>
+#include <pjsip_ua.h>
+#include <pjsip_simple.h>
+#include <pjlib-util.h>
+#include <pjlib.h>
+
+#include <stdlib.h>
+
+/* Uncomment these to disable threads.
+ * NOTE:
+ * when threading is disabled, siprtp won't transmit any
+ * RTP packets.
+ */
+/*
+#undef PJ_HAS_THREADS
+#define PJ_HAS_THREADS 0
+*/
+
+
+#if PJ_HAS_HIGH_RES_TIMER==0
+# error "High resolution timer is needed for this sample"
+#endif
+
+#define THIS_FILE "siprtp.c"
+#define MAX_CALLS 1024
+#define RTP_START_PORT 4000
+
+
+/* Codec descriptor: */
+struct codec
+{
+ unsigned pt;
+ char* name;
+ unsigned clock_rate;
+ unsigned bit_rate;
+ unsigned ptime;
+ char* description;
+};
+
+
+/* A bidirectional media stream created when the call is active. */
+struct media_stream
+{
+ /* Static: */
+ unsigned call_index; /* Call owner. */
+ unsigned media_index; /* Media index in call. */
+ pjmedia_transport *transport; /* To send/recv RTP/RTCP */
+
+ /* Active? */
+ pj_bool_t active; /* Non-zero if is in call. */
+
+ /* Current stream info: */
+ pjmedia_stream_info si; /* Current stream info. */
+
+ /* More info: */
+ unsigned clock_rate; /* clock rate */
+ unsigned samples_per_frame; /* samples per frame */
+ unsigned bytes_per_frame; /* frame size. */
+
+ /* RTP session: */
+ pjmedia_rtp_session out_sess; /* outgoing RTP session */
+ pjmedia_rtp_session in_sess; /* incoming RTP session */
+
+ /* RTCP stats: */
+ pjmedia_rtcp_session rtcp; /* incoming RTCP session. */
+
+ /* Thread: */
+ pj_bool_t thread_quit_flag; /* Stop media thread. */
+ pj_thread_t *thread; /* Media thread. */
+};
+
+
+/* This is a call structure that is created when the application starts
+ * and only destroyed when the application quits.
+ */
+struct call
+{
+ unsigned index;
+ pjsip_inv_session *inv;
+ unsigned media_count;
+ struct media_stream media[1];
+ pj_time_val start_time;
+ pj_time_val response_time;
+ pj_time_val connect_time;
+
+ pj_timer_entry d_timer; /**< Disconnect timer. */
+};
+
+
+/* Application's global variables */
+static struct app
+{
+ unsigned max_calls;
+ unsigned call_gap;
+ pj_bool_t call_report;
+ unsigned uac_calls;
+ unsigned duration;
+ pj_bool_t auto_quit;
+ unsigned thread_count;
+ int sip_port;
+ int rtp_start_port;
+ pj_str_t local_addr;
+ pj_str_t local_uri;
+ pj_str_t local_contact;
+
+ int app_log_level;
+ int log_level;
+ char *log_filename;
+ char *report_filename;
+
+ struct codec audio_codec;
+
+ pj_str_t uri_to_call;
+
+ pj_caching_pool cp;
+ pj_pool_t *pool;
+
+ pjsip_endpoint *sip_endpt;
+ pj_bool_t thread_quit;
+ pj_thread_t *sip_thread[1];
+
+ pjmedia_endpt *med_endpt;
+ struct call call[MAX_CALLS];
+} app;
+
+
+
+/*
+ * Prototypes:
+ */
+
+/* Callback to be called when SDP negotiation is done in the call: */
+static void call_on_media_update( pjsip_inv_session *inv,
+ pj_status_t status);
+
+/* Callback to be called when invite session's state has changed: */
+static void call_on_state_changed( pjsip_inv_session *inv,
+ pjsip_event *e);
+
+/* Callback to be called when dialog has forked: */
+static void call_on_forked(pjsip_inv_session *inv, pjsip_event *e);
+
+/* Callback to be called to handle incoming requests outside dialogs: */
+static pj_bool_t on_rx_request( pjsip_rx_data *rdata );
+
+/* Worker thread prototype */
+static int sip_worker_thread(void *arg);
+
+/* Create SDP for call */
+static pj_status_t create_sdp( pj_pool_t *pool,
+ struct call *call,
+ pjmedia_sdp_session **p_sdp);
+
+/* Hangup call */
+static void hangup_call(unsigned index);
+
+/* Destroy the call's media */
+static void destroy_call_media(unsigned call_index);
+
+/* Destroy media. */
+static void destroy_media();
+
+/* This callback is called by media transport on receipt of RTP packet. */
+static void on_rx_rtp(void *user_data, void *pkt, pj_ssize_t size);
+
+/* This callback is called by media transport on receipt of RTCP packet. */
+static void on_rx_rtcp(void *user_data, void *pkt, pj_ssize_t size);
+
+/* Display error */
+static void app_perror(const char *sender, const char *title,
+ pj_status_t status);
+
+/* Print call */
+static void print_call(int call_index);
+
+
+/* This is a PJSIP module to be registered by application to handle
+ * incoming requests outside any dialogs/transactions. The main purpose
+ * here is to handle incoming INVITE request message, where we will
+ * create a dialog and INVITE session for it.
+ */
+static pjsip_module mod_siprtp =
+{
+ NULL, NULL, /* prev, next. */
+ { "mod-siprtpapp", 13 }, /* Name. */
+ -1, /* Id */
+ PJSIP_MOD_PRIORITY_APPLICATION, /* Priority */
+ NULL, /* load() */
+ NULL, /* start() */
+ NULL, /* stop() */
+ NULL, /* unload() */
+ &on_rx_request, /* on_rx_request() */
+ NULL, /* on_rx_response() */
+ NULL, /* on_tx_request. */
+ NULL, /* on_tx_response() */
+ NULL, /* on_tsx_state() */
+};
+
+
+/* Codec constants */
+struct codec audio_codecs[] =
+{
+ { 0, "PCMU", 8000, 64000, 20, "G.711 ULaw" },
+ { 3, "GSM", 8000, 13200, 20, "GSM" },
+ { 4, "G723", 8000, 6400, 30, "G.723.1" },
+ { 8, "PCMA", 8000, 64000, 20, "G.711 ALaw" },
+ { 18, "G729", 8000, 8000, 20, "G.729" },
+};
+
+
+/*
+ * Init SIP stack
+ */
+static pj_status_t init_sip()
+{
+ unsigned i;
+ pj_status_t status;
+
+ /* init PJLIB-UTIL: */
+ status = pjlib_util_init();
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+ /* Must create a pool factory before we can allocate any memory. */
+ pj_caching_pool_init(&app.cp, &pj_pool_factory_default_policy, 0);
+
+ /* Create application pool for misc. */
+ app.pool = pj_pool_create(&app.cp.factory, "app", 1000, 1000, NULL);
+
+ /* Create the endpoint: */
+ status = pjsip_endpt_create(&app.cp.factory, pj_gethostname()->ptr,
+ &app.sip_endpt);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+
+ /* Add UDP transport. */
+ {
+ pj_sockaddr_in addr;
+ pjsip_host_port addrname;
+ pjsip_transport *tp;
+
+ pj_bzero(&addr, sizeof(addr));
+ addr.sin_family = pj_AF_INET();
+ addr.sin_addr.s_addr = 0;
+ addr.sin_port = pj_htons((pj_uint16_t)app.sip_port);
+
+ if (app.local_addr.slen) {
+
+ addrname.host = app.local_addr;
+ addrname.port = app.sip_port;
+
+ status = pj_sockaddr_in_init(&addr, &app.local_addr,
+ (pj_uint16_t)app.sip_port);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to resolve IP interface", status);
+ return status;
+ }
+ }
+
+ status = pjsip_udp_transport_start( app.sip_endpt, &addr,
+ (app.local_addr.slen ? &addrname:NULL),
+ 1, &tp);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to start UDP transport", status);
+ return status;
+ }
+
+ PJ_LOG(3,(THIS_FILE, "SIP UDP listening on %.*s:%d",
+ (int)tp->local_name.host.slen, tp->local_name.host.ptr,
+ tp->local_name.port));
+ }
+
+ /*
+ * Init transaction layer.
+ * This will create/initialize transaction hash tables etc.
+ */
+ status = pjsip_tsx_layer_init_module(app.sip_endpt);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+ /* Initialize UA layer. */
+ status = pjsip_ua_init_module( app.sip_endpt, NULL );
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+ /* Initialize 100rel support */
+ status = pjsip_100rel_init_module(app.sip_endpt);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+ /* Init invite session module. */
+ {
+ pjsip_inv_callback inv_cb;
+
+ /* Init the callback for INVITE session: */
+ pj_bzero(&inv_cb, sizeof(inv_cb));
+ inv_cb.on_state_changed = &call_on_state_changed;
+ inv_cb.on_new_session = &call_on_forked;
+ inv_cb.on_media_update = &call_on_media_update;
+
+ /* Initialize invite session module: */
+ status = pjsip_inv_usage_init(app.sip_endpt, &inv_cb);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+ }
+
+ /* Register our module to receive incoming requests. */
+ status = pjsip_endpt_register_module( app.sip_endpt, &mod_siprtp);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+ /* Init calls */
+ for (i=0; i<app.max_calls; ++i)
+ app.call[i].index = i;
+
+ /* Done */
+ return PJ_SUCCESS;
+}
+
+
+/*
+ * Destroy SIP
+ */
+static void destroy_sip()
+{
+ unsigned i;
+
+ app.thread_quit = 1;
+ for (i=0; i<app.thread_count; ++i) {
+ if (app.sip_thread[i]) {
+ pj_thread_join(app.sip_thread[i]);
+ pj_thread_destroy(app.sip_thread[i]);
+ app.sip_thread[i] = NULL;
+ }
+ }
+
+ if (app.sip_endpt) {
+ pjsip_endpt_destroy(app.sip_endpt);
+ app.sip_endpt = NULL;
+ }
+
+}
+
+
+/*
+ * Init media stack.
+ */
+static pj_status_t init_media()
+{
+ unsigned i, count;
+ pj_uint16_t rtp_port;
+ pj_status_t status;
+
+
+ /* Initialize media endpoint so that at least error subsystem is properly
+ * initialized.
+ */
+#if PJ_HAS_THREADS
+ status = pjmedia_endpt_create(&app.cp.factory, NULL, 1, &app.med_endpt);
+#else
+ status = pjmedia_endpt_create(&app.cp.factory,
+ pjsip_endpt_get_ioqueue(app.sip_endpt),
+ 0, &app.med_endpt);
+#endif
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+
+ /* Must register codecs to be supported */
+#if defined(PJMEDIA_HAS_G711_CODEC) && PJMEDIA_HAS_G711_CODEC!=0
+ pjmedia_codec_g711_init(app.med_endpt);
+#endif
+
+ /* RTP port counter */
+ rtp_port = (pj_uint16_t)(app.rtp_start_port & 0xFFFE);
+
+ /* Init media transport for all calls. */
+ for (i=0, count=0; i<app.max_calls; ++i, ++count) {
+
+ unsigned j;
+
+ /* Create transport for each media in the call */
+ for (j=0; j<PJ_ARRAY_SIZE(app.call[0].media); ++j) {
+ /* Repeat binding media socket to next port when fails to bind
+ * to current port number.
+ */
+ int retry;
+
+ app.call[i].media[j].call_index = i;
+ app.call[i].media[j].media_index = j;
+
+ status = -1;
+ for (retry=0; retry<100; ++retry,rtp_port+=2) {
+ struct media_stream *m = &app.call[i].media[j];
+
+ status = pjmedia_transport_udp_create2(app.med_endpt,
+ "siprtp",
+ &app.local_addr,
+ rtp_port, 0,
+ &m->transport);
+ if (status == PJ_SUCCESS) {
+ rtp_port += 2;
+ break;
+ }
+ }
+ }
+
+ if (status != PJ_SUCCESS)
+ goto on_error;
+ }
+
+ /* Done */
+ return PJ_SUCCESS;
+
+on_error:
+ destroy_media();
+ return status;
+}
+
+
+/*
+ * Destroy media.
+ */
+static void destroy_media()
+{
+ unsigned i;
+
+ for (i=0; i<app.max_calls; ++i) {
+ unsigned j;
+ for (j=0; j<PJ_ARRAY_SIZE(app.call[0].media); ++j) {
+ struct media_stream *m = &app.call[i].media[j];
+
+ if (m->transport) {
+ pjmedia_transport_close(m->transport);
+ m->transport = NULL;
+ }
+ }
+ }
+
+ if (app.med_endpt) {
+ pjmedia_endpt_destroy(app.med_endpt);
+ app.med_endpt = NULL;
+ }
+}
+
+
+/*
+ * Make outgoing call.
+ */
+static pj_status_t make_call(const pj_str_t *dst_uri)
+{
+ unsigned i;
+ struct call *call;
+ pjsip_dialog *dlg;
+ pjmedia_sdp_session *sdp;
+ pjsip_tx_data *tdata;
+ pj_status_t status;
+
+
+ /* Find unused call slot */
+ for (i=0; i<app.max_calls; ++i) {
+ if (app.call[i].inv == NULL)
+ break;
+ }
+
+ if (i == app.max_calls)
+ return PJ_ETOOMANY;
+
+ call = &app.call[i];
+
+ /* Create UAC dialog */
+ status = pjsip_dlg_create_uac( pjsip_ua_instance(),
+ &app.local_uri, /* local URI */
+ &app.local_contact, /* local Contact */
+ dst_uri, /* remote URI */
+ dst_uri, /* remote target */
+ &dlg); /* dialog */
+ if (status != PJ_SUCCESS) {
+ ++app.uac_calls;
+ return status;
+ }
+
+ /* Create SDP */
+ create_sdp( dlg->pool, call, &sdp);
+
+ /* Create the INVITE session. */
+ status = pjsip_inv_create_uac( dlg, sdp, 0, &call->inv);
+ if (status != PJ_SUCCESS) {
+ pjsip_dlg_terminate(dlg);
+ ++app.uac_calls;
+ return status;
+ }
+
+
+ /* Attach call data to invite session */
+ call->inv->mod_data[mod_siprtp.id] = call;
+
+ /* Mark start of call */
+ pj_gettimeofday(&call->start_time);
+
+
+ /* Create initial INVITE request.
+ * This INVITE request will contain a perfectly good request and
+ * an SDP body as well.
+ */
+ status = pjsip_inv_invite(call->inv, &tdata);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+
+ /* Send initial INVITE request.
+ * From now on, the invite session's state will be reported to us
+ * via the invite session callbacks.
+ */
+ status = pjsip_inv_send_msg(call->inv, tdata);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+
+ return PJ_SUCCESS;
+}
+
+
+/*
+ * Receive incoming call
+ */
+static void process_incoming_call(pjsip_rx_data *rdata)
+{
+ unsigned i, options;
+ struct call *call;
+ pjsip_dialog *dlg;
+ pjmedia_sdp_session *sdp;
+ pjsip_tx_data *tdata;
+ pj_status_t status;
+
+ /* Find free call slot */
+ for (i=0; i<app.max_calls; ++i) {
+ if (app.call[i].inv == NULL)
+ break;
+ }
+
+ if (i == app.max_calls) {
+ const pj_str_t reason = pj_str("Too many calls");
+ pjsip_endpt_respond_stateless( app.sip_endpt, rdata,
+ 500, &reason,
+ NULL, NULL);
+ return;
+ }
+
+ call = &app.call[i];
+
+ /* Verify that we can handle the request. */
+ options = 0;
+ status = pjsip_inv_verify_request(rdata, &options, NULL, NULL,
+ app.sip_endpt, &tdata);
+ if (status != PJ_SUCCESS) {
+ /*
+ * No we can't handle the incoming INVITE request.
+ */
+ if (tdata) {
+ pjsip_response_addr res_addr;
+
+ pjsip_get_response_addr(tdata->pool, rdata, &res_addr);
+ pjsip_endpt_send_response(app.sip_endpt, &res_addr, tdata,
+ NULL, NULL);
+
+ } else {
+
+ /* Respond with 500 (Internal Server Error) */
+ pjsip_endpt_respond_stateless(app.sip_endpt, rdata, 500, NULL,
+ NULL, NULL);
+ }
+
+ return;
+ }
+
+ /* Create UAS dialog */
+ status = pjsip_dlg_create_uas( pjsip_ua_instance(), rdata,
+ &app.local_contact, &dlg);
+ if (status != PJ_SUCCESS) {
+ const pj_str_t reason = pj_str("Unable to create dialog");
+ pjsip_endpt_respond_stateless( app.sip_endpt, rdata,
+ 500, &reason,
+ NULL, NULL);
+ return;
+ }
+
+ /* Create SDP */
+ create_sdp( dlg->pool, call, &sdp);
+
+ /* Create UAS invite session */
+ status = pjsip_inv_create_uas( dlg, rdata, sdp, 0, &call->inv);
+ if (status != PJ_SUCCESS) {
+ pjsip_dlg_create_response(dlg, rdata, 500, NULL, &tdata);
+ pjsip_dlg_send_response(dlg, pjsip_rdata_get_tsx(rdata), tdata);
+ return;
+ }
+
+
+ /* Attach call data to invite session */
+ call->inv->mod_data[mod_siprtp.id] = call;
+
+ /* Mark start of call */
+ pj_gettimeofday(&call->start_time);
+
+
+
+ /* Create 200 response .*/
+ status = pjsip_inv_initial_answer(call->inv, rdata, 200,
+ NULL, NULL, &tdata);
+ if (status != PJ_SUCCESS) {
+ status = pjsip_inv_initial_answer(call->inv, rdata,
+ PJSIP_SC_NOT_ACCEPTABLE,
+ NULL, NULL, &tdata);
+ if (status == PJ_SUCCESS)
+ pjsip_inv_send_msg(call->inv, tdata);
+ else
+ pjsip_inv_terminate(call->inv, 500, PJ_FALSE);
+ return;
+ }
+
+
+ /* Send the 200 response. */
+ status = pjsip_inv_send_msg(call->inv, tdata);
+ PJ_ASSERT_ON_FAIL(status == PJ_SUCCESS, return);
+
+
+ /* Done */
+}
+
+
+/* Callback to be called when dialog has forked: */
+static void call_on_forked(pjsip_inv_session *inv, pjsip_event *e)
+{
+ PJ_UNUSED_ARG(inv);
+ PJ_UNUSED_ARG(e);
+
+ PJ_TODO( HANDLE_FORKING );
+}
+
+
+/* Callback to be called to handle incoming requests outside dialogs: */
+static pj_bool_t on_rx_request( pjsip_rx_data *rdata )
+{
+ /* Ignore strandled ACKs (must not send respone */
+ if (rdata->msg_info.msg->line.req.method.id == PJSIP_ACK_METHOD)
+ return PJ_FALSE;
+
+ /* Respond (statelessly) any non-INVITE requests with 500 */
+ if (rdata->msg_info.msg->line.req.method.id != PJSIP_INVITE_METHOD) {
+ pj_str_t reason = pj_str("Unsupported Operation");
+ pjsip_endpt_respond_stateless( app.sip_endpt, rdata,
+ 500, &reason,
+ NULL, NULL);
+ return PJ_TRUE;
+ }
+
+ /* Handle incoming INVITE */
+ process_incoming_call(rdata);
+
+ /* Done */
+ return PJ_TRUE;
+}
+
+
+/* Callback timer to disconnect call (limiting call duration) */
+static void timer_disconnect_call( pj_timer_heap_t *timer_heap,
+ struct pj_timer_entry *entry)
+{
+ struct call *call = entry->user_data;
+
+ PJ_UNUSED_ARG(timer_heap);
+
+ entry->id = 0;
+ hangup_call(call->index);
+}
+
+
+/* Callback to be called when invite session's state has changed: */
+static void call_on_state_changed( pjsip_inv_session *inv,
+ pjsip_event *e)
+{
+ struct call *call = inv->mod_data[mod_siprtp.id];
+
+ PJ_UNUSED_ARG(e);
+
+ if (!call)
+ return;
+
+ if (inv->state == PJSIP_INV_STATE_DISCONNECTED) {
+
+ pj_time_val null_time = {0, 0};
+
+ if (call->d_timer.id != 0) {
+ pjsip_endpt_cancel_timer(app.sip_endpt, &call->d_timer);
+ call->d_timer.id = 0;
+ }
+
+ PJ_LOG(3,(THIS_FILE, "Call #%d disconnected. Reason=%d (%.*s)",
+ call->index,
+ inv->cause,
+ (int)inv->cause_text.slen,
+ inv->cause_text.ptr));
+
+ if (app.call_report) {
+ PJ_LOG(3,(THIS_FILE, "Call #%d statistics:", call->index));
+ print_call(call->index);
+ }
+
+
+ call->inv = NULL;
+ inv->mod_data[mod_siprtp.id] = NULL;
+
+ destroy_call_media(call->index);
+
+ call->start_time = null_time;
+ call->response_time = null_time;
+ call->connect_time = null_time;
+
+ ++app.uac_calls;
+
+ } else if (inv->state == PJSIP_INV_STATE_CONFIRMED) {
+
+ pj_time_val t;
+
+ pj_gettimeofday(&call->connect_time);
+ if (call->response_time.sec == 0)
+ call->response_time = call->connect_time;
+
+ t = call->connect_time;
+ PJ_TIME_VAL_SUB(t, call->start_time);
+
+ PJ_LOG(3,(THIS_FILE, "Call #%d connected in %d ms", call->index,
+ PJ_TIME_VAL_MSEC(t)));
+
+ if (app.duration != 0) {
+ call->d_timer.id = 1;
+ call->d_timer.user_data = call;
+ call->d_timer.cb = &timer_disconnect_call;
+
+ t.sec = app.duration;
+ t.msec = 0;
+
+ pjsip_endpt_schedule_timer(app.sip_endpt, &call->d_timer, &t);
+ }
+
+ } else if ( inv->state == PJSIP_INV_STATE_EARLY ||
+ inv->state == PJSIP_INV_STATE_CONNECTING) {
+
+ if (call->response_time.sec == 0)
+ pj_gettimeofday(&call->response_time);
+
+ }
+}
+
+
+/* Utility */
+static void app_perror(const char *sender, const char *title,
+ pj_status_t status)
+{
+ char errmsg[PJ_ERR_MSG_SIZE];
+
+ pj_strerror(status, errmsg, sizeof(errmsg));
+ PJ_LOG(3,(sender, "%s: %s [status=%d]", title, errmsg, status));
+}
+
+
+/* Worker thread for SIP */
+static int sip_worker_thread(void *arg)
+{
+ PJ_UNUSED_ARG(arg);
+
+ while (!app.thread_quit) {
+ pj_time_val timeout = {0, 10};
+ pjsip_endpt_handle_events(app.sip_endpt, &timeout);
+ }
+
+ return 0;
+}
+
+
+/* Init application options */
+static pj_status_t init_options(int argc, char *argv[])
+{
+ static char ip_addr[32];
+ static char local_uri[64];
+
+ enum { OPT_START,
+ OPT_APP_LOG_LEVEL, OPT_LOG_FILE,
+ OPT_A_PT, OPT_A_NAME, OPT_A_CLOCK, OPT_A_BITRATE, OPT_A_PTIME,
+ OPT_REPORT_FILE };
+
+ struct pj_getopt_option long_options[] = {
+ { "count", 1, 0, 'c' },
+ { "gap", 1, 0, 'g' },
+ { "call-report", 0, 0, 'R' },
+ { "duration", 1, 0, 'd' },
+ { "auto-quit", 0, 0, 'q' },
+ { "local-port", 1, 0, 'p' },
+ { "rtp-port", 1, 0, 'r' },
+ { "ip-addr", 1, 0, 'i' },
+
+ { "log-level", 1, 0, 'l' },
+ { "app-log-level", 1, 0, OPT_APP_LOG_LEVEL },
+ { "log-file", 1, 0, OPT_LOG_FILE },
+
+ { "report-file", 1, 0, OPT_REPORT_FILE },
+
+ /* Don't support this anymore, see comments in USAGE above.
+ { "a-pt", 1, 0, OPT_A_PT },
+ { "a-name", 1, 0, OPT_A_NAME },
+ { "a-clock", 1, 0, OPT_A_CLOCK },
+ { "a-bitrate", 1, 0, OPT_A_BITRATE },
+ { "a-ptime", 1, 0, OPT_A_PTIME },
+ */
+
+ { NULL, 0, 0, 0 },
+ };
+ int c;
+ int option_index;
+
+ /* Get local IP address for the default IP address */
+ {
+ const pj_str_t *hostname;
+ pj_sockaddr_in tmp_addr;
+ char *addr;
+
+ hostname = pj_gethostname();
+ pj_sockaddr_in_init(&tmp_addr, hostname, 0);
+ addr = pj_inet_ntoa(tmp_addr.sin_addr);
+ pj_ansi_strcpy(ip_addr, addr);
+ }
+
+ /* Init defaults */
+ app.max_calls = 1;
+ app.thread_count = 1;
+ app.sip_port = 5060;
+ app.rtp_start_port = RTP_START_PORT;
+ app.local_addr = pj_str(ip_addr);
+ app.log_level = 5;
+ app.app_log_level = 3;
+ app.log_filename = NULL;
+
+ /* Default codecs: */
+ app.audio_codec = audio_codecs[0];
+
+ /* Parse options */
+ pj_optind = 0;
+ while((c=pj_getopt_long(argc,argv, "c:d:p:r:i:l:g:qR",
+ long_options, &option_index))!=-1)
+ {
+ switch (c) {
+ case 'c':
+ app.max_calls = atoi(pj_optarg);
+ if (app.max_calls < 0 || app.max_calls > MAX_CALLS) {
+ PJ_LOG(3,(THIS_FILE, "Invalid max calls value %s", pj_optarg));
+ return 1;
+ }
+ break;
+ case 'g':
+ app.call_gap = atoi(pj_optarg);
+ break;
+ case 'R':
+ app.call_report = PJ_TRUE;
+ break;
+ case 'd':
+ app.duration = atoi(pj_optarg);
+ break;
+ case 'q':
+ app.auto_quit = 1;
+ break;
+
+ case 'p':
+ app.sip_port = atoi(pj_optarg);
+ break;
+ case 'r':
+ app.rtp_start_port = atoi(pj_optarg);
+ break;
+ case 'i':
+ app.local_addr = pj_str(pj_optarg);
+ break;
+
+ case 'l':
+ app.log_level = atoi(pj_optarg);
+ break;
+ case OPT_APP_LOG_LEVEL:
+ app.app_log_level = atoi(pj_optarg);
+ break;
+ case OPT_LOG_FILE:
+ app.log_filename = pj_optarg;
+ break;
+
+ case OPT_A_PT:
+ app.audio_codec.pt = atoi(pj_optarg);
+ break;
+ case OPT_A_NAME:
+ app.audio_codec.name = pj_optarg;
+ break;
+ case OPT_A_CLOCK:
+ app.audio_codec.clock_rate = atoi(pj_optarg);
+ break;
+ case OPT_A_BITRATE:
+ app.audio_codec.bit_rate = atoi(pj_optarg);
+ break;
+ case OPT_A_PTIME:
+ app.audio_codec.ptime = atoi(pj_optarg);
+ break;
+ case OPT_REPORT_FILE:
+ app.report_filename = pj_optarg;
+ break;
+
+ default:
+ puts(USAGE);
+ return 1;
+ }
+ }
+
+ /* Check if URL is specified */
+ if (pj_optind < argc)
+ app.uri_to_call = pj_str(argv[pj_optind]);
+
+ /* Build local URI and contact */
+ pj_ansi_sprintf( local_uri, "sip:%s:%d", app.local_addr.ptr, app.sip_port);
+ app.local_uri = pj_str(local_uri);
+ app.local_contact = app.local_uri;
+
+
+ return PJ_SUCCESS;
+}
+
+
+/*****************************************************************************
+ * MEDIA STUFFS
+ */
+
+/*
+ * Create SDP session for a call.
+ */
+static pj_status_t create_sdp( pj_pool_t *pool,
+ struct call *call,
+ pjmedia_sdp_session **p_sdp)
+{
+ pj_time_val tv;
+ pjmedia_sdp_session *sdp;
+ pjmedia_sdp_media *m;
+ pjmedia_sdp_attr *attr;
+ pjmedia_transport_info tpinfo;
+ struct media_stream *audio = &call->media[0];
+
+ PJ_ASSERT_RETURN(pool && p_sdp, PJ_EINVAL);
+
+
+ /* Get transport info */
+ pjmedia_transport_info_init(&tpinfo);
+ pjmedia_transport_get_info(audio->transport, &tpinfo);
+
+ /* Create and initialize basic SDP session */
+ sdp = pj_pool_zalloc (pool, sizeof(pjmedia_sdp_session));
+
+ pj_gettimeofday(&tv);
+ sdp->origin.user = pj_str("pjsip-siprtp");
+ sdp->origin.version = sdp->origin.id = tv.sec + 2208988800UL;
+ sdp->origin.net_type = pj_str("IN");
+ sdp->origin.addr_type = pj_str("IP4");
+ sdp->origin.addr = *pj_gethostname();
+ sdp->name = pj_str("pjsip");
+
+ /* Since we only support one media stream at present, put the
+ * SDP connection line in the session level.
+ */
+ sdp->conn = pj_pool_zalloc (pool, sizeof(pjmedia_sdp_conn));
+ sdp->conn->net_type = pj_str("IN");
+ sdp->conn->addr_type = pj_str("IP4");
+ sdp->conn->addr = app.local_addr;
+
+
+ /* SDP time and attributes. */
+ sdp->time.start = sdp->time.stop = 0;
+ sdp->attr_count = 0;
+
+ /* Create media stream 0: */
+
+ sdp->media_count = 1;
+ m = pj_pool_zalloc (pool, sizeof(pjmedia_sdp_media));
+ sdp->media[0] = m;
+
+ /* Standard media info: */
+ m->desc.media = pj_str("audio");
+ m->desc.port = pj_ntohs(tpinfo.sock_info.rtp_addr_name.ipv4.sin_port);
+ m->desc.port_count = 1;
+ m->desc.transport = pj_str("RTP/AVP");
+
+ /* Add format and rtpmap for each codec. */
+ m->desc.fmt_count = 1;
+ m->attr_count = 0;
+
+ {
+ pjmedia_sdp_rtpmap rtpmap;
+ pjmedia_sdp_attr *attr;
+ char ptstr[10];
+
+ sprintf(ptstr, "%d", app.audio_codec.pt);
+ pj_strdup2(pool, &m->desc.fmt[0], ptstr);
+ rtpmap.pt = m->desc.fmt[0];
+ rtpmap.clock_rate = app.audio_codec.clock_rate;
+ rtpmap.enc_name = pj_str(app.audio_codec.name);
+ rtpmap.param.slen = 0;
+
+ pjmedia_sdp_rtpmap_to_attr(pool, &rtpmap, &attr);
+ m->attr[m->attr_count++] = attr;
+ }
+
+ /* Add sendrecv attribute. */
+ attr = pj_pool_zalloc(pool, sizeof(pjmedia_sdp_attr));
+ attr->name = pj_str("sendrecv");
+ m->attr[m->attr_count++] = attr;
+
+#if 1
+ /*
+ * Add support telephony event
+ */
+ m->desc.fmt[m->desc.fmt_count++] = pj_str("121");
+ /* Add rtpmap. */
+ attr = pj_pool_zalloc(pool, sizeof(pjmedia_sdp_attr));
+ attr->name = pj_str("rtpmap");
+ attr->value = pj_str("121 telephone-event/8000");
+ m->attr[m->attr_count++] = attr;
+ /* Add fmtp */
+ attr = pj_pool_zalloc(pool, sizeof(pjmedia_sdp_attr));
+ attr->name = pj_str("fmtp");
+ attr->value = pj_str("121 0-15");
+ m->attr[m->attr_count++] = attr;
+#endif
+
+ /* Done */
+ *p_sdp = sdp;
+
+ return PJ_SUCCESS;
+}
+
+
+#if defined(PJ_WIN32) && PJ_WIN32 != 0
+#include <windows.h>
+static void boost_priority(void)
+{
+ SetPriorityClass( GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
+ SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
+}
+
+#elif defined(PJ_LINUX) && PJ_LINUX != 0
+#include <pthread.h>
+static void boost_priority(void)
+{
+#define POLICY SCHED_FIFO
+ struct sched_param tp;
+ int max_prio;
+ int policy;
+ int rc;
+
+ if (sched_get_priority_min(POLICY) < sched_get_priority_max(POLICY))
+ max_prio = sched_get_priority_max(POLICY)-1;
+ else
+ max_prio = sched_get_priority_max(POLICY)+1;
+
+ /*
+ * Adjust process scheduling algorithm and priority
+ */
+ rc = sched_getparam(0, &tp);
+ if (rc != 0) {
+ app_perror( THIS_FILE, "sched_getparam error",
+ PJ_RETURN_OS_ERROR(rc));
+ return;
+ }
+ tp.__sched_priority = max_prio;
+
+ rc = sched_setscheduler(0, POLICY, &tp);
+ if (rc != 0) {
+ app_perror( THIS_FILE, "sched_setscheduler error",
+ PJ_RETURN_OS_ERROR(rc));
+ }
+
+ PJ_LOG(4, (THIS_FILE, "New process policy=%d, priority=%d",
+ policy, tp.__sched_priority));
+
+ /*
+ * Adjust thread scheduling algorithm and priority
+ */
+ rc = pthread_getschedparam(pthread_self(), &policy, &tp);
+ if (rc != 0) {
+ app_perror( THIS_FILE, "pthread_getschedparam error",
+ PJ_RETURN_OS_ERROR(rc));
+ return;
+ }
+
+ PJ_LOG(4, (THIS_FILE, "Old thread policy=%d, priority=%d",
+ policy, tp.__sched_priority));
+
+ policy = POLICY;
+ tp.__sched_priority = max_prio;
+
+ rc = pthread_setschedparam(pthread_self(), policy, &tp);
+ if (rc != 0) {
+ app_perror( THIS_FILE, "pthread_setschedparam error",
+ PJ_RETURN_OS_ERROR(rc));
+ return;
+ }
+
+ PJ_LOG(4, (THIS_FILE, "New thread policy=%d, priority=%d",
+ policy, tp.__sched_priority));
+}
+
+#else
+# define boost_priority()
+#endif
+
+
+/*
+ * This callback is called by media transport on receipt of RTP packet.
+ */
+static void on_rx_rtp(void *user_data, void *pkt, pj_ssize_t size)
+{
+ struct media_stream *strm;
+ pj_status_t status;
+ const pjmedia_rtp_hdr *hdr;
+ const void *payload;
+ unsigned payload_len;
+
+ strm = user_data;
+
+ /* Discard packet if media is inactive */
+ if (!strm->active)
+ return;
+
+ /* Check for errors */
+ if (size < 0) {
+ app_perror(THIS_FILE, "RTP recv() error", -size);
+ return;
+ }
+
+ /* Decode RTP packet. */
+ status = pjmedia_rtp_decode_rtp(&strm->in_sess,
+ pkt, size,
+ &hdr, &payload, &payload_len);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "RTP decode error", status);
+ return;
+ }
+
+ //PJ_LOG(4,(THIS_FILE, "Rx seq=%d", pj_ntohs(hdr->seq)));
+
+ /* Update the RTCP session. */
+ pjmedia_rtcp_rx_rtp(&strm->rtcp, pj_ntohs(hdr->seq),
+ pj_ntohl(hdr->ts), payload_len);
+
+ /* Update RTP session */
+ pjmedia_rtp_session_update(&strm->in_sess, hdr, NULL);
+
+}
+
+/*
+ * This callback is called by media transport on receipt of RTCP packet.
+ */
+static void on_rx_rtcp(void *user_data, void *pkt, pj_ssize_t size)
+{
+ struct media_stream *strm;
+
+ strm = user_data;
+
+ /* Discard packet if media is inactive */
+ if (!strm->active)
+ return;
+
+ /* Check for errors */
+ if (size < 0) {
+ app_perror(THIS_FILE, "Error receiving RTCP packet", -size);
+ return;
+ }
+
+ /* Update RTCP session */
+ pjmedia_rtcp_rx_rtcp(&strm->rtcp, pkt, size);
+}
+
+
+/*
+ * Media thread
+ *
+ * This is the thread to send and receive both RTP and RTCP packets.
+ */
+static int media_thread(void *arg)
+{
+ enum { RTCP_INTERVAL = 5000, RTCP_RAND = 2000 };
+ struct media_stream *strm = arg;
+ char packet[1500];
+ unsigned msec_interval;
+ pj_timestamp freq, next_rtp, next_rtcp;
+
+
+ /* Boost thread priority if necessary */
+ boost_priority();
+
+ /* Let things settle */
+ pj_thread_sleep(100);
+
+ msec_interval = strm->samples_per_frame * 1000 / strm->clock_rate;
+ pj_get_timestamp_freq(&freq);
+
+ pj_get_timestamp(&next_rtp);
+ next_rtp.u64 += (freq.u64 * msec_interval / 1000);
+
+ next_rtcp = next_rtp;
+ next_rtcp.u64 += (freq.u64 * (RTCP_INTERVAL+(pj_rand()%RTCP_RAND)) / 1000);
+
+
+ while (!strm->thread_quit_flag) {
+ pj_timestamp now, lesser;
+ pj_time_val timeout;
+ pj_bool_t send_rtp, send_rtcp;
+
+ send_rtp = send_rtcp = PJ_FALSE;
+
+ /* Determine how long to sleep */
+ if (next_rtp.u64 < next_rtcp.u64) {
+ lesser = next_rtp;
+ send_rtp = PJ_TRUE;
+ } else {
+ lesser = next_rtcp;
+ send_rtcp = PJ_TRUE;
+ }
+
+ pj_get_timestamp(&now);
+ if (lesser.u64 <= now.u64) {
+ timeout.sec = timeout.msec = 0;
+ //printf("immediate "); fflush(stdout);
+ } else {
+ pj_uint64_t tick_delay;
+ tick_delay = lesser.u64 - now.u64;
+ timeout.sec = 0;
+ timeout.msec = (pj_uint32_t)(tick_delay * 1000 / freq.u64);
+ pj_time_val_normalize(&timeout);
+
+ //printf("%d:%03d ", timeout.sec, timeout.msec); fflush(stdout);
+ }
+
+ /* Wait for next interval */
+ //if (timeout.sec!=0 && timeout.msec!=0) {
+ pj_thread_sleep(PJ_TIME_VAL_MSEC(timeout));
+ if (strm->thread_quit_flag)
+ break;
+ //}
+
+ pj_get_timestamp(&now);
+
+ if (send_rtp || next_rtp.u64 <= now.u64) {
+ /*
+ * Time to send RTP packet.
+ */
+ pj_status_t status;
+ const void *p_hdr;
+ const pjmedia_rtp_hdr *hdr;
+ pj_ssize_t size;
+ int hdrlen;
+
+ /* Format RTP header */
+ status = pjmedia_rtp_encode_rtp( &strm->out_sess, strm->si.tx_pt,
+ 0, /* marker bit */
+ strm->bytes_per_frame,
+ strm->samples_per_frame,
+ &p_hdr, &hdrlen);
+ if (status == PJ_SUCCESS) {
+
+ //PJ_LOG(4,(THIS_FILE, "\t\tTx seq=%d", pj_ntohs(hdr->seq)));
+
+ hdr = (const pjmedia_rtp_hdr*) p_hdr;
+
+ /* Copy RTP header to packet */
+ pj_memcpy(packet, hdr, hdrlen);
+
+ /* Zero the payload */
+ pj_bzero(packet+hdrlen, strm->bytes_per_frame);
+
+ /* Send RTP packet */
+ size = hdrlen + strm->bytes_per_frame;
+ status = pjmedia_transport_send_rtp(strm->transport,
+ packet, size);
+ if (status != PJ_SUCCESS)
+ app_perror(THIS_FILE, "Error sending RTP packet", status);
+
+ } else {
+ pj_assert(!"RTP encode() error");
+ }
+
+ /* Update RTCP SR */
+ pjmedia_rtcp_tx_rtp( &strm->rtcp, (pj_uint16_t)strm->bytes_per_frame);
+
+ /* Schedule next send */
+ next_rtp.u64 += (msec_interval * freq.u64 / 1000);
+ }
+
+
+ if (send_rtcp || next_rtcp.u64 <= now.u64) {
+ /*
+ * Time to send RTCP packet.
+ */
+ void *rtcp_pkt;
+ int rtcp_len;
+ pj_ssize_t size;
+ pj_status_t status;
+
+ /* Build RTCP packet */
+ pjmedia_rtcp_build_rtcp(&strm->rtcp, &rtcp_pkt, &rtcp_len);
+
+
+ /* Send packet */
+ size = rtcp_len;
+ status = pjmedia_transport_send_rtcp(strm->transport,
+ rtcp_pkt, size);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Error sending RTCP packet", status);
+ }
+
+ /* Schedule next send */
+ next_rtcp.u64 += (freq.u64 * (RTCP_INTERVAL+(pj_rand()%RTCP_RAND)) /
+ 1000);
+ }
+ }
+
+ return 0;
+}
+
+
+/* Callback to be called when SDP negotiation is done in the call: */
+static void call_on_media_update( pjsip_inv_session *inv,
+ pj_status_t status)
+{
+ struct call *call;
+ pj_pool_t *pool;
+ struct media_stream *audio;
+ const pjmedia_sdp_session *local_sdp, *remote_sdp;
+ struct codec *codec_desc = NULL;
+ unsigned i;
+
+ call = inv->mod_data[mod_siprtp.id];
+ pool = inv->dlg->pool;
+ audio = &call->media[0];
+
+ /* If this is a mid-call media update, then destroy existing media */
+ if (audio->thread != NULL)
+ destroy_call_media(call->index);
+
+
+ /* Do nothing if media negotiation has failed */
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "SDP negotiation failed", status);
+ return;
+ }
+
+
+ /* Capture stream definition from the SDP */
+ pjmedia_sdp_neg_get_active_local(inv->neg, &local_sdp);
+ pjmedia_sdp_neg_get_active_remote(inv->neg, &remote_sdp);
+
+ status = pjmedia_stream_info_from_sdp(&audio->si, inv->pool, app.med_endpt,
+ local_sdp, remote_sdp, 0);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Error creating stream info from SDP", status);
+ return;
+ }
+
+ /* Get the remainder of codec information from codec descriptor */
+ if (audio->si.fmt.pt == app.audio_codec.pt)
+ codec_desc = &app.audio_codec;
+ else {
+ /* Find the codec description in codec array */
+ for (i=0; i<PJ_ARRAY_SIZE(audio_codecs); ++i) {
+ if (audio_codecs[i].pt == audio->si.fmt.pt) {
+ codec_desc = &audio_codecs[i];
+ break;
+ }
+ }
+
+ if (codec_desc == NULL) {
+ PJ_LOG(3, (THIS_FILE, "Error: Invalid codec payload type"));
+ return;
+ }
+ }
+
+ audio->clock_rate = audio->si.fmt.clock_rate;
+ audio->samples_per_frame = audio->clock_rate * codec_desc->ptime / 1000;
+ audio->bytes_per_frame = codec_desc->bit_rate * codec_desc->ptime / 1000 / 8;
+
+
+ pjmedia_rtp_session_init(&audio->out_sess, audio->si.tx_pt,
+ pj_rand());
+ pjmedia_rtp_session_init(&audio->in_sess, audio->si.fmt.pt, 0);
+ pjmedia_rtcp_init(&audio->rtcp, "rtcp", audio->clock_rate,
+ audio->samples_per_frame, 0);
+
+
+ /* Attach media to transport */
+ status = pjmedia_transport_attach(audio->transport, audio,
+ &audio->si.rem_addr,
+ &audio->si.rem_rtcp,
+ sizeof(pj_sockaddr_in),
+ &on_rx_rtp,
+ &on_rx_rtcp);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Error on pjmedia_transport_attach()", status);
+ return;
+ }
+
+ /* Start media thread. */
+ audio->thread_quit_flag = 0;
+#if PJ_HAS_THREADS
+ status = pj_thread_create( inv->pool, "media", &media_thread, audio,
+ 0, 0, &audio->thread);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Error creating media thread", status);
+ return;
+ }
+#endif
+
+ /* Set the media as active */
+ audio->active = PJ_TRUE;
+}
+
+
+
+/* Destroy call's media */
+static void destroy_call_media(unsigned call_index)
+{
+ struct media_stream *audio = &app.call[call_index].media[0];
+
+ if (audio) {
+ audio->active = PJ_FALSE;
+
+ if (audio->thread) {
+ audio->thread_quit_flag = 1;
+ pj_thread_join(audio->thread);
+ pj_thread_destroy(audio->thread);
+ audio->thread = NULL;
+ audio->thread_quit_flag = 0;
+ }
+
+ pjmedia_transport_detach(audio->transport, audio);
+ }
+}
+
+
+/*****************************************************************************
+ * USER INTERFACE STUFFS
+ */
+
+static void call_get_duration(int call_index, pj_time_val *dur)
+{
+ struct call *call = &app.call[call_index];
+ pjsip_inv_session *inv;
+
+ dur->sec = dur->msec = 0;
+
+ if (!call)
+ return;
+
+ inv = call->inv;
+ if (!inv)
+ return;
+
+ if (inv->state >= PJSIP_INV_STATE_CONFIRMED && call->connect_time.sec) {
+
+ pj_gettimeofday(dur);
+ PJ_TIME_VAL_SUB((*dur), call->connect_time);
+ }
+}
+
+
+static const char *good_number(char *buf, pj_int32_t val)
+{
+ if (val < 1000) {
+ pj_ansi_sprintf(buf, "%d", val);
+ } else if (val < 1000000) {
+ pj_ansi_sprintf(buf, "%d.%02dK",
+ val / 1000,
+ (val % 1000) / 100);
+ } else {
+ pj_ansi_sprintf(buf, "%d.%02dM",
+ val / 1000000,
+ (val % 1000000) / 10000);
+ }
+
+ return buf;
+}
+
+
+
+static void print_avg_stat(void)
+{
+#define MIN_(var,val) if ((int)val < (int)var) var = val
+#define MAX_(var,val) if ((int)val > (int)var) var = val
+#define AVG_(var,val) var = ( ((var * count) + val) / (count+1) )
+#define BIGVAL 0x7FFFFFFFL
+ struct stat_entry
+ {
+ int min, avg, max;
+ };
+
+ struct stat_entry call_dur, call_pdd;
+ pjmedia_rtcp_stat min_stat, avg_stat, max_stat;
+
+ char srx_min[16], srx_avg[16], srx_max[16];
+ char brx_min[16], brx_avg[16], brx_max[16];
+ char stx_min[16], stx_avg[16], stx_max[16];
+ char btx_min[16], btx_avg[16], btx_max[16];
+
+
+ unsigned i, count;
+
+ pj_bzero(&call_dur, sizeof(call_dur));
+ call_dur.min = BIGVAL;
+
+ pj_bzero(&call_pdd, sizeof(call_pdd));
+ call_pdd.min = BIGVAL;
+
+ pj_bzero(&min_stat, sizeof(min_stat));
+ min_stat.rx.pkt = min_stat.tx.pkt = BIGVAL;
+ min_stat.rx.bytes = min_stat.tx.bytes = BIGVAL;
+ min_stat.rx.loss = min_stat.tx.loss = BIGVAL;
+ min_stat.rx.dup = min_stat.tx.dup = BIGVAL;
+ min_stat.rx.reorder = min_stat.tx.reorder = BIGVAL;
+ min_stat.rx.jitter.min = min_stat.tx.jitter.min = BIGVAL;
+ min_stat.rtt.min = BIGVAL;
+
+ pj_bzero(&avg_stat, sizeof(avg_stat));
+ pj_bzero(&max_stat, sizeof(max_stat));
+
+
+ for (i=0, count=0; i<app.max_calls; ++i) {
+
+ struct call *call = &app.call[i];
+ struct media_stream *audio = &call->media[0];
+ pj_time_val dur;
+ unsigned msec_dur;
+
+ if (call->inv == NULL ||
+ call->inv->state < PJSIP_INV_STATE_CONFIRMED ||
+ call->connect_time.sec == 0)
+ {
+ continue;
+ }
+
+ /* Duration */
+ call_get_duration(i, &dur);
+ msec_dur = PJ_TIME_VAL_MSEC(dur);
+
+ MIN_(call_dur.min, msec_dur);
+ MAX_(call_dur.max, msec_dur);
+ AVG_(call_dur.avg, msec_dur);
+
+ /* Connect delay */
+ if (call->connect_time.sec) {
+ pj_time_val t = call->connect_time;
+ PJ_TIME_VAL_SUB(t, call->start_time);
+ msec_dur = PJ_TIME_VAL_MSEC(t);
+ } else {
+ msec_dur = 10;
+ }
+
+ MIN_(call_pdd.min, msec_dur);
+ MAX_(call_pdd.max, msec_dur);
+ AVG_(call_pdd.avg, msec_dur);
+
+ /* RX Statistisc: */
+
+ /* Packets */
+ MIN_(min_stat.rx.pkt, audio->rtcp.stat.rx.pkt);
+ MAX_(max_stat.rx.pkt, audio->rtcp.stat.rx.pkt);
+ AVG_(avg_stat.rx.pkt, audio->rtcp.stat.rx.pkt);
+
+ /* Bytes */
+ MIN_(min_stat.rx.bytes, audio->rtcp.stat.rx.bytes);
+ MAX_(max_stat.rx.bytes, audio->rtcp.stat.rx.bytes);
+ AVG_(avg_stat.rx.bytes, audio->rtcp.stat.rx.bytes);
+
+
+ /* Packet loss */
+ MIN_(min_stat.rx.loss, audio->rtcp.stat.rx.loss);
+ MAX_(max_stat.rx.loss, audio->rtcp.stat.rx.loss);
+ AVG_(avg_stat.rx.loss, audio->rtcp.stat.rx.loss);
+
+ /* Packet dup */
+ MIN_(min_stat.rx.dup, audio->rtcp.stat.rx.dup);
+ MAX_(max_stat.rx.dup, audio->rtcp.stat.rx.dup);
+ AVG_(avg_stat.rx.dup, audio->rtcp.stat.rx.dup);
+
+ /* Packet reorder */
+ MIN_(min_stat.rx.reorder, audio->rtcp.stat.rx.reorder);
+ MAX_(max_stat.rx.reorder, audio->rtcp.stat.rx.reorder);
+ AVG_(avg_stat.rx.reorder, audio->rtcp.stat.rx.reorder);
+
+ /* Jitter */
+ MIN_(min_stat.rx.jitter.min, audio->rtcp.stat.rx.jitter.min);
+ MAX_(max_stat.rx.jitter.max, audio->rtcp.stat.rx.jitter.max);
+ AVG_(avg_stat.rx.jitter.mean, audio->rtcp.stat.rx.jitter.mean);
+
+
+ /* TX Statistisc: */
+
+ /* Packets */
+ MIN_(min_stat.tx.pkt, audio->rtcp.stat.tx.pkt);
+ MAX_(max_stat.tx.pkt, audio->rtcp.stat.tx.pkt);
+ AVG_(avg_stat.tx.pkt, audio->rtcp.stat.tx.pkt);
+
+ /* Bytes */
+ MIN_(min_stat.tx.bytes, audio->rtcp.stat.tx.bytes);
+ MAX_(max_stat.tx.bytes, audio->rtcp.stat.tx.bytes);
+ AVG_(avg_stat.tx.bytes, audio->rtcp.stat.tx.bytes);
+
+ /* Packet loss */
+ MIN_(min_stat.tx.loss, audio->rtcp.stat.tx.loss);
+ MAX_(max_stat.tx.loss, audio->rtcp.stat.tx.loss);
+ AVG_(avg_stat.tx.loss, audio->rtcp.stat.tx.loss);
+
+ /* Packet dup */
+ MIN_(min_stat.tx.dup, audio->rtcp.stat.tx.dup);
+ MAX_(max_stat.tx.dup, audio->rtcp.stat.tx.dup);
+ AVG_(avg_stat.tx.dup, audio->rtcp.stat.tx.dup);
+
+ /* Packet reorder */
+ MIN_(min_stat.tx.reorder, audio->rtcp.stat.tx.reorder);
+ MAX_(max_stat.tx.reorder, audio->rtcp.stat.tx.reorder);
+ AVG_(avg_stat.tx.reorder, audio->rtcp.stat.tx.reorder);
+
+ /* Jitter */
+ MIN_(min_stat.tx.jitter.min, audio->rtcp.stat.tx.jitter.min);
+ MAX_(max_stat.tx.jitter.max, audio->rtcp.stat.tx.jitter.max);
+ AVG_(avg_stat.tx.jitter.mean, audio->rtcp.stat.tx.jitter.mean);
+
+
+ /* RTT */
+ MIN_(min_stat.rtt.min, audio->rtcp.stat.rtt.min);
+ MAX_(max_stat.rtt.max, audio->rtcp.stat.rtt.max);
+ AVG_(avg_stat.rtt.mean, audio->rtcp.stat.rtt.mean);
+
+ ++count;
+ }
+
+ if (count == 0) {
+ puts("No active calls");
+ return;
+ }
+
+ printf("Total %d call(s) active.\n"
+ " Average Statistics\n"
+ " min avg max \n"
+ " -----------------------\n"
+ " call duration: %7d %7d %7d %s\n"
+ " connect delay: %7d %7d %7d %s\n"
+ " RX stat:\n"
+ " packets: %7s %7s %7s %s\n"
+ " payload: %7s %7s %7s %s\n"
+ " loss: %7d %7d %7d %s\n"
+ " percent loss: %7.3f %7.3f %7.3f %s\n"
+ " dup: %7d %7d %7d %s\n"
+ " reorder: %7d %7d %7d %s\n"
+ " jitter: %7.3f %7.3f %7.3f %s\n"
+ " TX stat:\n"
+ " packets: %7s %7s %7s %s\n"
+ " payload: %7s %7s %7s %s\n"
+ " loss: %7d %7d %7d %s\n"
+ " percent loss: %7.3f %7.3f %7.3f %s\n"
+ " dup: %7d %7d %7d %s\n"
+ " reorder: %7d %7d %7d %s\n"
+ " jitter: %7.3f %7.3f %7.3f %s\n"
+ " RTT : %7.3f %7.3f %7.3f %s\n"
+ ,
+ count,
+ call_dur.min/1000, call_dur.avg/1000, call_dur.max/1000,
+ "seconds",
+
+ call_pdd.min, call_pdd.avg, call_pdd.max,
+ "ms",
+
+ /* rx */
+
+ good_number(srx_min, min_stat.rx.pkt),
+ good_number(srx_avg, avg_stat.rx.pkt),
+ good_number(srx_max, max_stat.rx.pkt),
+ "packets",
+
+ good_number(brx_min, min_stat.rx.bytes),
+ good_number(brx_avg, avg_stat.rx.bytes),
+ good_number(brx_max, max_stat.rx.bytes),
+ "bytes",
+
+ min_stat.rx.loss, avg_stat.rx.loss, max_stat.rx.loss,
+ "packets",
+
+ min_stat.rx.loss*100.0/(min_stat.rx.pkt+min_stat.rx.loss),
+ avg_stat.rx.loss*100.0/(avg_stat.rx.pkt+avg_stat.rx.loss),
+ max_stat.rx.loss*100.0/(max_stat.rx.pkt+max_stat.rx.loss),
+ "%",
+
+
+ min_stat.rx.dup, avg_stat.rx.dup, max_stat.rx.dup,
+ "packets",
+
+ min_stat.rx.reorder, avg_stat.rx.reorder, max_stat.rx.reorder,
+ "packets",
+
+ min_stat.rx.jitter.min/1000.0,
+ avg_stat.rx.jitter.mean/1000.0,
+ max_stat.rx.jitter.max/1000.0,
+ "ms",
+
+ /* tx */
+
+ good_number(stx_min, min_stat.tx.pkt),
+ good_number(stx_avg, avg_stat.tx.pkt),
+ good_number(stx_max, max_stat.tx.pkt),
+ "packets",
+
+ good_number(btx_min, min_stat.tx.bytes),
+ good_number(btx_avg, avg_stat.tx.bytes),
+ good_number(btx_max, max_stat.tx.bytes),
+ "bytes",
+
+ min_stat.tx.loss, avg_stat.tx.loss, max_stat.tx.loss,
+ "packets",
+
+ min_stat.tx.loss*100.0/(min_stat.tx.pkt+min_stat.tx.loss),
+ avg_stat.tx.loss*100.0/(avg_stat.tx.pkt+avg_stat.tx.loss),
+ max_stat.tx.loss*100.0/(max_stat.tx.pkt+max_stat.tx.loss),
+ "%",
+
+ min_stat.tx.dup, avg_stat.tx.dup, max_stat.tx.dup,
+ "packets",
+
+ min_stat.tx.reorder, avg_stat.tx.reorder, max_stat.tx.reorder,
+ "packets",
+
+ min_stat.tx.jitter.min/1000.0,
+ avg_stat.tx.jitter.mean/1000.0,
+ max_stat.tx.jitter.max/1000.0,
+ "ms",
+
+ /* rtt */
+ min_stat.rtt.min/1000.0,
+ avg_stat.rtt.mean/1000.0,
+ max_stat.rtt.max/1000.0,
+ "ms"
+ );
+
+}
+
+
+#include "siprtp_report.c"
+
+
+static void list_calls()
+{
+ unsigned i;
+ puts("List all calls:");
+ for (i=0; i<app.max_calls; ++i) {
+ if (!app.call[i].inv)
+ continue;
+ print_call(i);
+ }
+}
+
+static void hangup_call(unsigned index)
+{
+ pjsip_tx_data *tdata;
+ pj_status_t status;
+
+ if (app.call[index].inv == NULL)
+ return;
+
+ status = pjsip_inv_end_session(app.call[index].inv, 603, NULL, &tdata);
+ if (status==PJ_SUCCESS && tdata!=NULL)
+ pjsip_inv_send_msg(app.call[index].inv, tdata);
+}
+
+static void hangup_all_calls()
+{
+ unsigned i;
+ for (i=0; i<app.max_calls; ++i) {
+ if (!app.call[i].inv)
+ continue;
+ hangup_call(i);
+ pj_thread_sleep(app.call_gap);
+ }
+
+ /* Wait until all calls are terminated */
+ for (i=0; i<app.max_calls; ++i) {
+ while (app.call[i].inv)
+ pj_thread_sleep(10);
+ }
+}
+
+static pj_bool_t simple_input(const char *title, char *buf, pj_size_t len)
+{
+ char *p;
+
+ printf("%s (empty to cancel): ", title); fflush(stdout);
+ if (fgets(buf, len, stdin) == NULL)
+ return PJ_FALSE;
+
+ /* Remove trailing newlines. */
+ for (p=buf; ; ++p) {
+ if (*p=='\r' || *p=='\n') *p='\0';
+ else if (!*p) break;
+ }
+
+ if (!*buf)
+ return PJ_FALSE;
+
+ return PJ_TRUE;
+}
+
+
+static const char *MENU =
+"\n"
+"Enter menu character:\n"
+" s Summary\n"
+" l List all calls\n"
+" h Hangup a call\n"
+" H Hangup all calls\n"
+" q Quit\n"
+"\n";
+
+
+/* Main screen menu */
+static void console_main()
+{
+ char input1[10];
+ unsigned i;
+
+ printf("%s", MENU);
+
+ for (;;) {
+ printf(">>> "); fflush(stdout);
+ if (fgets(input1, sizeof(input1), stdin) == NULL) {
+ puts("EOF while reading stdin, will quit now..");
+ break;
+ }
+
+ switch (input1[0]) {
+
+ case 's':
+ print_avg_stat();
+ break;
+
+ case 'l':
+ list_calls();
+ break;
+
+ case 'h':
+ if (!simple_input("Call number to hangup", input1, sizeof(input1)))
+ break;
+
+ i = atoi(input1);
+ hangup_call(i);
+ break;
+
+ case 'H':
+ hangup_all_calls();
+ break;
+
+ case 'q':
+ goto on_exit;
+
+ default:
+ puts("Invalid command");
+ printf("%s", MENU);
+ break;
+ }
+
+ fflush(stdout);
+ }
+
+on_exit:
+ hangup_all_calls();
+}
+
+
+/*****************************************************************************
+ * Below is a simple module to log all incoming and outgoing SIP messages
+ */
+
+
+/* Notification on incoming messages */
+static pj_bool_t logger_on_rx_msg(pjsip_rx_data *rdata)
+{
+ PJ_LOG(4,(THIS_FILE, "RX %d bytes %s from %s:%d:\n"
+ "%s\n"
+ "--end msg--",
+ rdata->msg_info.len,
+ pjsip_rx_data_get_info(rdata),
+ rdata->pkt_info.src_name,
+ rdata->pkt_info.src_port,
+ rdata->msg_info.msg_buf));
+
+ /* Always return false, otherwise messages will not get processed! */
+ return PJ_FALSE;
+}
+
+/* Notification on outgoing messages */
+static pj_status_t logger_on_tx_msg(pjsip_tx_data *tdata)
+{
+
+ /* Important note:
+ * tp_info field is only valid after outgoing messages has passed
+ * transport layer. So don't try to access tp_info when the module
+ * has lower priority than transport layer.
+ */
+
+ PJ_LOG(4,(THIS_FILE, "TX %d bytes %s to %s:%d:\n"
+ "%s\n"
+ "--end msg--",
+ (tdata->buf.cur - tdata->buf.start),
+ pjsip_tx_data_get_info(tdata),
+ tdata->tp_info.dst_name,
+ tdata->tp_info.dst_port,
+ tdata->buf.start));
+
+ /* Always return success, otherwise message will not get sent! */
+ return PJ_SUCCESS;
+}
+
+/* The module instance. */
+static pjsip_module msg_logger =
+{
+ NULL, NULL, /* prev, next. */
+ { "mod-siprtp-log", 14 }, /* Name. */
+ -1, /* Id */
+ PJSIP_MOD_PRIORITY_TRANSPORT_LAYER-1,/* Priority */
+ NULL, /* load() */
+ NULL, /* start() */
+ NULL, /* stop() */
+ NULL, /* unload() */
+ &logger_on_rx_msg, /* on_rx_request() */
+ &logger_on_rx_msg, /* on_rx_response() */
+ &logger_on_tx_msg, /* on_tx_request. */
+ &logger_on_tx_msg, /* on_tx_response() */
+ NULL, /* on_tsx_state() */
+
+};
+
+
+
+/*****************************************************************************
+ * 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 <= app.app_log_level)
+ pj_log_write(level, buffer, len);
+
+ if (log_file) {
+ int count = fwrite(buffer, len, 1, log_file);
+ PJ_UNUSED_ARG(count);
+ fflush(log_file);
+ }
+}
+
+
+pj_status_t app_logging_init(void)
+{
+ /* Redirect log function to ours */
+
+ pj_log_set_log_func( &app_log_writer );
+
+ /* If output log file is desired, create the file: */
+
+ if (app.log_filename) {
+ log_file = fopen(app.log_filename, "wt");
+ if (log_file == NULL) {
+ PJ_LOG(1,(THIS_FILE, "Unable to open log file %s",
+ app.log_filename));
+ return -1;
+ }
+ }
+
+ return PJ_SUCCESS;
+}
+
+
+void app_logging_shutdown(void)
+{
+ /* Close logging file, if any: */
+
+ if (log_file) {
+ fclose(log_file);
+ log_file = NULL;
+ }
+}
+
+
+/*
+ * main()
+ */
+int main(int argc, char *argv[])
+{
+ unsigned i;
+ pj_status_t status;
+
+ /* Must init PJLIB first */
+ status = pj_init();
+ if (status != PJ_SUCCESS)
+ return 1;
+
+ /* Get command line options */
+ status = init_options(argc, argv);
+ if (status != PJ_SUCCESS)
+ return 1;
+
+ /* Verify options: */
+
+ /* Auto-quit can not be specified for UAS */
+ if (app.auto_quit && app.uri_to_call.slen == 0) {
+ printf("Error: --auto-quit option only valid for outgoing "
+ "mode (UAC) only\n");
+ return 1;
+ }
+
+ /* Init logging */
+ status = app_logging_init();
+ if (status != PJ_SUCCESS)
+ return 1;
+
+ /* Init SIP etc */
+ status = init_sip();
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Initialization has failed", status);
+ destroy_sip();
+ return 1;
+ }
+
+ /* Register module to log incoming/outgoing messages */
+ pjsip_endpt_register_module(app.sip_endpt, &msg_logger);
+
+ /* Init media */
+ status = init_media();
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Media initialization failed", status);
+ destroy_sip();
+ return 1;
+ }
+
+ /* Start worker threads */
+#if PJ_HAS_THREADS
+ for (i=0; i<app.thread_count; ++i) {
+ pj_thread_create( app.pool, "app", &sip_worker_thread, NULL,
+ 0, 0, &app.sip_thread[i]);
+ }
+#endif
+
+ /* If URL is specified, then make call immediately */
+ if (app.uri_to_call.slen) {
+ unsigned i;
+
+ PJ_LOG(3,(THIS_FILE, "Making %d calls to %s..", app.max_calls,
+ app.uri_to_call.ptr));
+
+ for (i=0; i<app.max_calls; ++i) {
+ status = make_call(&app.uri_to_call);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Error making call", status);
+ break;
+ }
+ pj_thread_sleep(app.call_gap);
+ }
+
+ if (app.auto_quit) {
+ /* Wait for calls to complete */
+ while (app.uac_calls < app.max_calls)
+ pj_thread_sleep(100);
+ pj_thread_sleep(200);
+ } else {
+#if PJ_HAS_THREADS
+ /* Start user interface loop */
+ console_main();
+#endif
+ }
+
+ } else {
+
+ PJ_LOG(3,(THIS_FILE, "Ready for incoming calls (max=%d)",
+ app.max_calls));
+
+#if PJ_HAS_THREADS
+ /* Start user interface loop */
+ console_main();
+#endif
+ }
+
+#if !PJ_HAS_THREADS
+ PJ_LOG(3,(THIS_FILE, "Press Ctrl-C to quit"));
+ for (;;) {
+ pj_time_val t = {0, 10};
+ pjsip_endpt_handle_events(app.sip_endpt, &t);
+ }
+#endif
+
+ /* Shutting down... */
+ destroy_sip();
+ destroy_media();
+
+ if (app.pool) {
+ pj_pool_release(app.pool);
+ app.pool = NULL;
+ pj_caching_pool_destroy(&app.cp);
+ }
+
+ app_logging_shutdown();
+
+ /* Shutdown PJLIB */
+ pj_shutdown();
+
+ return 0;
+}
+
diff --git a/pjsip-apps/src/samples/siprtp_report.c b/pjsip-apps/src/samples/siprtp_report.c
new file mode 100644
index 0000000..6643f9d
--- /dev/null
+++ b/pjsip-apps/src/samples/siprtp_report.c
@@ -0,0 +1,231 @@
+/* $Id: siprtp_report.c 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+/*
+ * DO NOT COMPILE THIS FILE ON ITS OWN!
+ *
+ * This file is included by siprtp.c to implement the reporting capability
+ * to a separate file, so that user can implement different reporting
+ * functionality (such as writing to XML file).
+ */
+
+
+static void print_call(int call_index)
+{
+ struct call *call = &app.call[call_index];
+ int len;
+ pjsip_inv_session *inv = call->inv;
+ pjsip_dialog *dlg = inv->dlg;
+ struct media_stream *audio = &call->media[0];
+ char userinfo[128];
+ char duration[80], last_update[80];
+ char bps[16], ipbps[16], packets[16], bytes[16], ipbytes[16];
+ unsigned decor;
+ pj_time_val now;
+
+
+ decor = pj_log_get_decor();
+ pj_log_set_decor(PJ_LOG_HAS_NEWLINE);
+
+ pj_gettimeofday(&now);
+
+ if (app.report_filename)
+ puts(app.report_filename);
+
+ /* Print duration */
+ if (inv->state >= PJSIP_INV_STATE_CONFIRMED && call->connect_time.sec) {
+
+ PJ_TIME_VAL_SUB(now, call->connect_time);
+
+ sprintf(duration, " [duration: %02ld:%02ld:%02ld.%03ld]",
+ now.sec / 3600,
+ (now.sec % 3600) / 60,
+ (now.sec % 60),
+ now.msec);
+
+ } else {
+ duration[0] = '\0';
+ }
+
+
+
+ /* Call number and state */
+ PJ_LOG(3, (THIS_FILE,
+ "Call #%d: %s%s",
+ call_index, pjsip_inv_state_name(inv->state),
+ duration));
+
+
+
+ /* Call identification */
+ len = pjsip_hdr_print_on(dlg->remote.info, userinfo, sizeof(userinfo));
+ if (len < 0)
+ pj_ansi_strcpy(userinfo, "<--uri too long-->");
+ else
+ userinfo[len] = '\0';
+
+ PJ_LOG(3, (THIS_FILE, " %s", userinfo));
+
+
+ if (call->inv == NULL || call->inv->state < PJSIP_INV_STATE_CONFIRMED ||
+ call->connect_time.sec == 0)
+ {
+ pj_log_set_decor(decor);
+ return;
+ }
+
+
+ /* Signaling quality */
+ {
+ char pdd[64], connectdelay[64];
+ pj_time_val t;
+
+ if (call->response_time.sec) {
+ t = call->response_time;
+ PJ_TIME_VAL_SUB(t, call->start_time);
+ sprintf(pdd, "got 1st response in %ld ms", PJ_TIME_VAL_MSEC(t));
+ } else {
+ pdd[0] = '\0';
+ }
+
+ if (call->connect_time.sec) {
+ t = call->connect_time;
+ PJ_TIME_VAL_SUB(t, call->start_time);
+ sprintf(connectdelay, ", connected after: %ld ms",
+ PJ_TIME_VAL_MSEC(t));
+ } else {
+ connectdelay[0] = '\0';
+ }
+
+ PJ_LOG(3, (THIS_FILE,
+ " Signaling quality: %s%s", pdd, connectdelay));
+ }
+
+
+ PJ_LOG(3, (THIS_FILE,
+ " Stream #0: audio %.*s@%dHz, %dms/frame, %sB/s (%sB/s +IP hdr)",
+ (int)audio->si.fmt.encoding_name.slen,
+ audio->si.fmt.encoding_name.ptr,
+ audio->clock_rate,
+ audio->samples_per_frame * 1000 / audio->clock_rate,
+ good_number(bps, audio->bytes_per_frame * audio->clock_rate / audio->samples_per_frame),
+ good_number(ipbps, (audio->bytes_per_frame+32) * audio->clock_rate / audio->samples_per_frame)));
+
+ if (audio->rtcp.stat.rx.update_cnt == 0)
+ strcpy(last_update, "never");
+ else {
+ pj_gettimeofday(&now);
+ PJ_TIME_VAL_SUB(now, audio->rtcp.stat.rx.update);
+ sprintf(last_update, "%02ldh:%02ldm:%02ld.%03lds ago",
+ now.sec / 3600,
+ (now.sec % 3600) / 60,
+ now.sec % 60,
+ now.msec);
+ }
+
+ PJ_LOG(3, (THIS_FILE,
+ " RX stat last update: %s\n"
+ " total %s packets %sB received (%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",
+ last_update,
+ good_number(packets, audio->rtcp.stat.rx.pkt),
+ good_number(bytes, audio->rtcp.stat.rx.bytes),
+ good_number(ipbytes, audio->rtcp.stat.rx.bytes + audio->rtcp.stat.rx.pkt * 32),
+ "",
+ audio->rtcp.stat.rx.loss,
+ audio->rtcp.stat.rx.loss * 100.0 / (audio->rtcp.stat.rx.pkt + audio->rtcp.stat.rx.loss),
+ audio->rtcp.stat.rx.dup,
+ audio->rtcp.stat.rx.dup * 100.0 / (audio->rtcp.stat.rx.pkt + audio->rtcp.stat.rx.loss),
+ audio->rtcp.stat.rx.reorder,
+ audio->rtcp.stat.rx.reorder * 100.0 / (audio->rtcp.stat.rx.pkt + audio->rtcp.stat.rx.loss),
+ "",
+ audio->rtcp.stat.rx.loss_period.min / 1000.0,
+ audio->rtcp.stat.rx.loss_period.mean / 1000.0,
+ audio->rtcp.stat.rx.loss_period.max / 1000.0,
+ audio->rtcp.stat.rx.loss_period.last / 1000.0,
+ "",
+ audio->rtcp.stat.rx.jitter.min / 1000.0,
+ audio->rtcp.stat.rx.jitter.mean / 1000.0,
+ audio->rtcp.stat.rx.jitter.max / 1000.0,
+ audio->rtcp.stat.rx.jitter.last / 1000.0,
+ ""
+ ));
+
+
+ if (audio->rtcp.stat.tx.update_cnt == 0)
+ strcpy(last_update, "never");
+ else {
+ pj_gettimeofday(&now);
+ PJ_TIME_VAL_SUB(now, audio->rtcp.stat.tx.update);
+ sprintf(last_update, "%02ldh:%02ldm:%02ld.%03lds ago",
+ now.sec / 3600,
+ (now.sec % 3600) / 60,
+ now.sec % 60,
+ now.msec);
+ }
+
+ PJ_LOG(3, (THIS_FILE,
+ " TX stat last update: %s\n"
+ " total %s packets %sB sent (%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",
+ last_update,
+ good_number(packets, audio->rtcp.stat.tx.pkt),
+ good_number(bytes, audio->rtcp.stat.tx.bytes),
+ good_number(ipbytes, audio->rtcp.stat.tx.bytes + audio->rtcp.stat.tx.pkt * 32),
+ "",
+ audio->rtcp.stat.tx.loss,
+ audio->rtcp.stat.tx.loss * 100.0 / (audio->rtcp.stat.tx.pkt + audio->rtcp.stat.tx.loss),
+ audio->rtcp.stat.tx.dup,
+ audio->rtcp.stat.tx.dup * 100.0 / (audio->rtcp.stat.tx.pkt + audio->rtcp.stat.tx.loss),
+ audio->rtcp.stat.tx.reorder,
+ audio->rtcp.stat.tx.reorder * 100.0 / (audio->rtcp.stat.tx.pkt + audio->rtcp.stat.tx.loss),
+ "",
+ audio->rtcp.stat.tx.loss_period.min / 1000.0,
+ audio->rtcp.stat.tx.loss_period.mean / 1000.0,
+ audio->rtcp.stat.tx.loss_period.max / 1000.0,
+ audio->rtcp.stat.tx.loss_period.last / 1000.0,
+ "",
+ audio->rtcp.stat.tx.jitter.min / 1000.0,
+ audio->rtcp.stat.tx.jitter.mean / 1000.0,
+ audio->rtcp.stat.tx.jitter.max / 1000.0,
+ audio->rtcp.stat.tx.jitter.last / 1000.0,
+ ""
+ ));
+
+
+ PJ_LOG(3, (THIS_FILE,
+ " RTT delay : %7.3f %7.3f %7.3f %7.3f%s\n",
+ audio->rtcp.stat.rtt.min / 1000.0,
+ audio->rtcp.stat.rtt.mean / 1000.0,
+ audio->rtcp.stat.rtt.max / 1000.0,
+ audio->rtcp.stat.rtt.last / 1000.0,
+ ""
+ ));
+
+ pj_log_set_decor(decor);
+}
+
diff --git a/pjsip-apps/src/samples/sipstateless.c b/pjsip-apps/src/samples/sipstateless.c
new file mode 100644
index 0000000..0de89a6
--- /dev/null
+++ b/pjsip-apps/src/samples/sipstateless.c
@@ -0,0 +1,243 @@
+/* $Id: sipstateless.c 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/**
+ * sipcore.c
+ *
+ * A simple program to respond any incoming requests (except ACK, of course!)
+ * with any status code (taken from command line argument, with the default
+ * is 501/Not Implemented).
+ */
+
+
+/* Include all headers. */
+#include <pjsip.h>
+#include <pjlib-util.h>
+#include <pjlib.h>
+
+
+/* If this macro is set, UDP transport will be initialized at port 5060 */
+#define HAS_UDP_TRANSPORT
+
+/* If this macro is set, TCP transport will be initialized at port 5060 */
+#define HAS_TCP_TRANSPORT (1 && PJ_HAS_TCP)
+
+/* Log identification */
+#define THIS_FILE "sipstateless.c"
+
+
+/* Global SIP endpoint */
+static pjsip_endpoint *sip_endpt;
+
+/* What response code to be sent (default is 501/Not Implemented) */
+static int code = PJSIP_SC_NOT_IMPLEMENTED;
+
+/* Additional header list */
+struct pjsip_hdr hdr_list;
+
+/* usage() */
+static void usage(void)
+{
+ puts("Usage:");
+ puts(" sipstateless [code] [-H HDR] ..");
+ puts("");
+ puts("Options:");
+ puts(" code SIP status code to send (default: 501/Not Implemented");
+ puts(" -H HDR Specify additional headers to send with response");
+ puts(" This option may be specified more than once.");
+ puts(" Example:");
+ puts(" -H 'Expires: 300' -H 'Contact: <sip:localhost>'");
+}
+
+
+/* Callback to handle incoming requests. */
+static pj_bool_t on_rx_request( pjsip_rx_data *rdata )
+{
+ /* Respond (statelessly) all incoming requests (except ACK!)
+ * with 501 (Not Implemented)
+ */
+ if (rdata->msg_info.msg->line.req.method.id != PJSIP_ACK_METHOD) {
+ pjsip_endpt_respond_stateless( sip_endpt, rdata,
+ code, NULL,
+ &hdr_list, NULL);
+ }
+ return PJ_TRUE;
+}
+
+
+
+/*
+ * main()
+ *
+ */
+int main(int argc, char *argv[])
+{
+ pj_caching_pool cp;
+ pj_pool_t *pool = NULL;
+ pjsip_module mod_app =
+ {
+ NULL, NULL, /* prev, next. */
+ { "mod-app", 7 }, /* Name. */
+ -1, /* Id */
+ PJSIP_MOD_PRIORITY_APPLICATION, /* Priority */
+ NULL, /* load() */
+ NULL, /* start() */
+ NULL, /* stop() */
+ NULL, /* unload() */
+ &on_rx_request, /* on_rx_request() */
+ NULL, /* on_rx_response() */
+ NULL, /* on_tx_request. */
+ NULL, /* on_tx_response() */
+ NULL, /* on_tsx_state() */
+ };
+ int c;
+ pj_status_t status;
+
+ /* Must init PJLIB first: */
+ status = pj_init();
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+
+ /* Then init PJLIB-UTIL: */
+ status = pjlib_util_init();
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ /* Must create a pool factory before we can allocate any memory. */
+ pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);
+
+ /* Create global endpoint: */
+ {
+ /* Endpoint MUST be assigned a globally unique name.
+ * Ideally we should put hostname or public IP address, but
+ * we'll just use an arbitrary name here.
+ */
+
+ /* Create the endpoint: */
+ status = pjsip_endpt_create(&cp.factory, "sipstateless",
+ &sip_endpt);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+ }
+
+ /* Parse arguments */
+ pj_optind = 0;
+ pj_list_init(&hdr_list);
+ while ((c=pj_getopt(argc, argv , "H:")) != -1) {
+ switch (c) {
+ case 'H':
+ if (pool == NULL) {
+ pool = pj_pool_create(&cp.factory, "sipstateless", 1000,
+ 1000, NULL);
+ }
+
+ if (pool) {
+ char *name;
+ name = strtok(pj_optarg, ":");
+ if (name == NULL) {
+ puts("Error: invalid header format");
+ return 1;
+ } else {
+ char *val = strtok(NULL, "\r\n");
+ pjsip_generic_string_hdr *h;
+ pj_str_t hname, hvalue;
+
+ hname = pj_str(name);
+ hvalue = pj_str(val);
+
+ h = pjsip_generic_string_hdr_create(pool, &hname, &hvalue);
+
+ pj_list_push_back(&hdr_list, h);
+
+ PJ_LOG(4,(THIS_FILE, "Header %s: %s added", name, val));
+ }
+ }
+ break;
+ default:
+ puts("Error: invalid argument");
+ usage();
+ return 1;
+ }
+ }
+
+ if (pj_optind != argc) {
+ code = atoi(argv[pj_optind]);
+ if (code < 200 || code > 699) {
+ puts("Error: invalid status code");
+ usage();
+ return 1;
+ }
+ }
+
+ PJ_LOG(4,(THIS_FILE, "Returning %d to incoming requests", code));
+
+
+ /*
+ * Add UDP transport, with hard-coded port
+ */
+#ifdef HAS_UDP_TRANSPORT
+ {
+ pj_sockaddr_in addr;
+
+ addr.sin_family = pj_AF_INET();
+ addr.sin_addr.s_addr = 0;
+ addr.sin_port = pj_htons(5060);
+
+ status = pjsip_udp_transport_start( sip_endpt, &addr, NULL, 1, NULL);
+ if (status != PJ_SUCCESS) {
+ PJ_LOG(3,(THIS_FILE,
+ "Error starting UDP transport (port in use?)"));
+ return 1;
+ }
+ }
+#endif
+
+#if HAS_TCP_TRANSPORT
+ /*
+ * Add UDP transport, with hard-coded port
+ */
+ {
+ pj_sockaddr_in addr;
+
+ addr.sin_family = pj_AF_INET();
+ addr.sin_addr.s_addr = 0;
+ addr.sin_port = pj_htons(5060);
+
+ status = pjsip_tcp_transport_start(sip_endpt, &addr, 1, NULL);
+ if (status != PJ_SUCCESS) {
+ PJ_LOG(3,(THIS_FILE,
+ "Error starting TCP transport (port in use?)"));
+ return 1;
+ }
+ }
+#endif
+
+ /*
+ * Register our module to receive incoming requests.
+ */
+ status = pjsip_endpt_register_module( sip_endpt, &mod_app);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+
+ /* Done. Loop forever to handle incoming events. */
+ PJ_LOG(3,(THIS_FILE, "Press Ctrl-C to quit.."));
+
+ for (;;) {
+ pjsip_endpt_handle_events(sip_endpt, NULL);
+ }
+}
diff --git a/pjsip-apps/src/samples/stateful_proxy.c b/pjsip-apps/src/samples/stateful_proxy.c
new file mode 100644
index 0000000..e8e2c25
--- /dev/null
+++ b/pjsip-apps/src/samples/stateful_proxy.c
@@ -0,0 +1,587 @@
+/* $Id: stateful_proxy.c 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#define THIS_FILE "stateful_proxy.c"
+
+/* Common proxy functions */
+#define STATEFUL 1
+#include "proxy.h"
+
+
+/*
+ * mod_stateful_proxy is the module to receive SIP request and
+ * response message that is outside any transaction context.
+ */
+static pj_bool_t proxy_on_rx_request(pjsip_rx_data *rdata );
+static pj_bool_t proxy_on_rx_response(pjsip_rx_data *rdata );
+
+static pjsip_module mod_stateful_proxy =
+{
+ NULL, NULL, /* prev, next. */
+ { "mod-stateful-proxy", 18 }, /* Name. */
+ -1, /* Id */
+ PJSIP_MOD_PRIORITY_UA_PROXY_LAYER, /* Priority */
+ NULL, /* load() */
+ NULL, /* start() */
+ NULL, /* stop() */
+ NULL, /* unload() */
+ &proxy_on_rx_request, /* on_rx_request() */
+ &proxy_on_rx_response, /* on_rx_response() */
+ NULL, /* on_tx_request. */
+ NULL, /* on_tx_response() */
+ NULL, /* on_tsx_state() */
+};
+
+
+/*
+ * mod_tu (tu=Transaction User) is the module to receive notification
+ * from transaction when the transaction state has changed.
+ */
+static void tu_on_tsx_state(pjsip_transaction *tsx, pjsip_event *event);
+
+static pjsip_module mod_tu =
+{
+ NULL, NULL, /* prev, next. */
+ { "mod-transaction-user", 20 }, /* Name. */
+ -1, /* Id */
+ PJSIP_MOD_PRIORITY_APPLICATION, /* Priority */
+ NULL, /* load() */
+ NULL, /* start() */
+ NULL, /* stop() */
+ NULL, /* unload() */
+ NULL, /* on_rx_request() */
+ NULL, /* on_rx_response() */
+ NULL, /* on_tx_request. */
+ NULL, /* on_tx_response() */
+ &tu_on_tsx_state, /* on_tsx_state() */
+};
+
+
+/* This is the data that is attached to the UAC transaction */
+struct uac_data
+{
+ pjsip_transaction *uas_tsx;
+ pj_timer_entry timer;
+};
+
+
+/* This is the data that is attached to the UAS transaction */
+struct uas_data
+{
+ pjsip_transaction *uac_tsx;
+};
+
+
+
+static pj_status_t init_stateful_proxy(void)
+{
+ pj_status_t status;
+
+ status = pjsip_endpt_register_module( global.endpt, &mod_stateful_proxy);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ status = pjsip_endpt_register_module( global.endpt, &mod_tu);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ return PJ_SUCCESS;
+}
+
+
+/* Callback to be called to handle new incoming requests. */
+static pj_bool_t proxy_on_rx_request( pjsip_rx_data *rdata )
+{
+ pjsip_transaction *uas_tsx, *uac_tsx;
+ struct uac_data *uac_data;
+ struct uas_data *uas_data;
+ pjsip_tx_data *tdata;
+ pj_status_t status;
+
+ if (rdata->msg_info.msg->line.req.method.id != PJSIP_CANCEL_METHOD) {
+
+ /* Verify incoming request */
+ status = proxy_verify_request(rdata);
+ if (status != PJ_SUCCESS) {
+ app_perror("RX invalid request", status);
+ return PJ_TRUE;
+ }
+
+ /*
+ * Request looks sane, next clone the request to create transmit data.
+ */
+ status = pjsip_endpt_create_request_fwd(global.endpt, rdata, NULL,
+ NULL, 0, &tdata);
+ if (status != PJ_SUCCESS) {
+ pjsip_endpt_respond_stateless(global.endpt, rdata,
+ PJSIP_SC_INTERNAL_SERVER_ERROR,
+ NULL, NULL, NULL);
+ return PJ_TRUE;
+ }
+
+
+ /* Process routing */
+ status = proxy_process_routing(tdata);
+ if (status != PJ_SUCCESS) {
+ app_perror("Error processing route", status);
+ return PJ_TRUE;
+ }
+
+ /* Calculate target */
+ status = proxy_calculate_target(rdata, tdata);
+ if (status != PJ_SUCCESS) {
+ app_perror("Error calculating target", status);
+ return PJ_TRUE;
+ }
+
+ /* Everything is set to forward the request. */
+
+ /* If this is an ACK request, forward statelessly.
+ * This happens if the proxy records route and this ACK
+ * is sent for 2xx response. An ACK that is sent for non-2xx
+ * final response will be absorbed by transaction layer, and
+ * it will not be received by on_rx_request() callback.
+ */
+ if (tdata->msg->line.req.method.id == PJSIP_ACK_METHOD) {
+ status = pjsip_endpt_send_request_stateless(global.endpt, tdata,
+ NULL, NULL);
+ if (status != PJ_SUCCESS) {
+ app_perror("Error forwarding request", status);
+ return PJ_TRUE;
+ }
+
+ return PJ_TRUE;
+ }
+
+ /* Create UAC transaction for forwarding the request.
+ * Set our module as the transaction user to receive further
+ * events from this transaction.
+ */
+ status = pjsip_tsx_create_uac(&mod_tu, tdata, &uac_tsx);
+ if (status != PJ_SUCCESS) {
+ pjsip_tx_data_dec_ref(tdata);
+ pjsip_endpt_respond_stateless(global.endpt, rdata,
+ PJSIP_SC_INTERNAL_SERVER_ERROR,
+ NULL, NULL, NULL);
+ return PJ_TRUE;
+ }
+
+ /* Create UAS transaction to handle incoming request */
+ status = pjsip_tsx_create_uas(&mod_tu, rdata, &uas_tsx);
+ if (status != PJ_SUCCESS) {
+ pjsip_tx_data_dec_ref(tdata);
+ pjsip_endpt_respond_stateless(global.endpt, rdata,
+ PJSIP_SC_INTERNAL_SERVER_ERROR,
+ NULL, NULL, NULL);
+ pjsip_tsx_terminate(uac_tsx, PJSIP_SC_INTERNAL_SERVER_ERROR);
+ return PJ_TRUE;
+ }
+
+ /* Feed the request to the UAS transaction to drive it's state
+ * out of NULL state.
+ */
+ pjsip_tsx_recv_msg(uas_tsx, rdata);
+
+ /* Attach a data to the UAC transaction, to be used to find the
+ * UAS transaction when we receive response in the UAC side.
+ */
+ uac_data = (struct uac_data*)
+ pj_pool_alloc(uac_tsx->pool, sizeof(struct uac_data));
+ uac_data->uas_tsx = uas_tsx;
+ uac_tsx->mod_data[mod_tu.id] = (void*)uac_data;
+
+ /* Attach data to the UAS transaction, to find the UAC transaction
+ * when cancelling INVITE request.
+ */
+ uas_data = (struct uas_data*)
+ pj_pool_alloc(uas_tsx->pool, sizeof(struct uas_data));
+ uas_data->uac_tsx = uac_tsx;
+ uas_tsx->mod_data[mod_tu.id] = (void*)uas_data;
+
+ /* Everything is setup, forward the request */
+ status = pjsip_tsx_send_msg(uac_tsx, tdata);
+ if (status != PJ_SUCCESS) {
+ pjsip_tx_data *err_res;
+
+ /* Fail to send request, for some reason */
+
+ /* Destroy transmit data */
+ pjsip_tx_data_dec_ref(tdata);
+
+ /* I think UAC transaction should have been destroyed when
+ * it fails to send request, so no need to destroy it.
+ pjsip_tsx_terminate(uac_tsx, PJSIP_SC_INTERNAL_SERVER_ERROR);
+ */
+
+ /* Send 500/Internal Server Error to UAS transaction */
+ pjsip_endpt_create_response(global.endpt, rdata,
+ 500, NULL, &err_res);
+ pjsip_tsx_send_msg(uas_tsx, err_res);
+
+ return PJ_TRUE;
+ }
+
+ /* Send 100/Trying if this is an INVITE */
+ if (rdata->msg_info.msg->line.req.method.id == PJSIP_INVITE_METHOD) {
+ pjsip_tx_data *res100;
+
+ pjsip_endpt_create_response(global.endpt, rdata, 100, NULL,
+ &res100);
+ pjsip_tsx_send_msg(uas_tsx, res100);
+ }
+
+ } else {
+ /* This is CANCEL request */
+ pjsip_transaction *invite_uas;
+ struct uas_data *uas_data;
+ pj_str_t key;
+
+ /* Find the UAS INVITE transaction */
+ pjsip_tsx_create_key(rdata->tp_info.pool, &key, PJSIP_UAS_ROLE,
+ pjsip_get_invite_method(), rdata);
+ invite_uas = pjsip_tsx_layer_find_tsx(&key, PJ_TRUE);
+ if (!invite_uas) {
+ /* Invite transaction not found, respond CANCEL with 481 */
+ pjsip_endpt_respond_stateless(global.endpt, rdata, 481, NULL,
+ NULL, NULL);
+ return PJ_TRUE;
+ }
+
+ /* Respond 200 OK to CANCEL */
+ pjsip_endpt_respond(global.endpt, NULL, rdata, 200, NULL, NULL,
+ NULL, NULL);
+
+ /* Send CANCEL to cancel the UAC transaction.
+ * The UAS INVITE transaction will get final response when
+ * we receive final response from the UAC INVITE transaction.
+ */
+ uas_data = (struct uas_data*) invite_uas->mod_data[mod_tu.id];
+ if (uas_data->uac_tsx && uas_data->uac_tsx->status_code < 200) {
+ pjsip_tx_data *cancel;
+
+ pj_mutex_lock(uas_data->uac_tsx->mutex);
+
+ pjsip_endpt_create_cancel(global.endpt, uas_data->uac_tsx->last_tx,
+ &cancel);
+ pjsip_endpt_send_request(global.endpt, cancel, -1, NULL, NULL);
+
+ pj_mutex_unlock(uas_data->uac_tsx->mutex);
+ }
+
+ /* Unlock UAS tsx because it is locked in find_tsx() */
+ pj_mutex_unlock(invite_uas->mutex);
+ }
+
+ return PJ_TRUE;
+}
+
+
+/* Callback to be called to handle incoming response outside
+ * any transactions. This happens for example when 2xx/OK
+ * for INVITE is received and transaction will be destroyed
+ * immediately, so we need to forward the subsequent 2xx/OK
+ * retransmission statelessly.
+ */
+static pj_bool_t proxy_on_rx_response( pjsip_rx_data *rdata )
+{
+ pjsip_tx_data *tdata;
+ pjsip_response_addr res_addr;
+ pjsip_via_hdr *hvia;
+ pj_status_t status;
+
+ /* Create response to be forwarded upstream (Via will be stripped here) */
+ status = pjsip_endpt_create_response_fwd(global.endpt, rdata, 0, &tdata);
+ if (status != PJ_SUCCESS) {
+ app_perror("Error creating response", status);
+ return PJ_TRUE;
+ }
+
+ /* Get topmost Via header */
+ hvia = (pjsip_via_hdr*) pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL);
+ if (hvia == NULL) {
+ /* Invalid response! Just drop it */
+ pjsip_tx_data_dec_ref(tdata);
+ return PJ_TRUE;
+ }
+
+ /* Calculate the address to forward the response */
+ pj_bzero(&res_addr, sizeof(res_addr));
+ res_addr.dst_host.type = PJSIP_TRANSPORT_UDP;
+ res_addr.dst_host.flag =
+ pjsip_transport_get_flag_from_type(PJSIP_TRANSPORT_UDP);
+
+ /* Destination address is Via's received param */
+ res_addr.dst_host.addr.host = hvia->recvd_param;
+ if (res_addr.dst_host.addr.host.slen == 0) {
+ /* Someone has messed up our Via header! */
+ res_addr.dst_host.addr.host = hvia->sent_by.host;
+ }
+
+ /* Destination port is the rport */
+ if (hvia->rport_param != 0 && hvia->rport_param != -1)
+ res_addr.dst_host.addr.port = hvia->rport_param;
+
+ if (res_addr.dst_host.addr.port == 0) {
+ /* Ugh, original sender didn't put rport!
+ * At best, can only send the response to the port in Via.
+ */
+ res_addr.dst_host.addr.port = hvia->sent_by.port;
+ }
+
+ /* Forward response */
+ status = pjsip_endpt_send_response(global.endpt, &res_addr, tdata,
+ NULL, NULL);
+ if (status != PJ_SUCCESS) {
+ app_perror("Error forwarding response", status);
+ return PJ_TRUE;
+ }
+
+ return PJ_TRUE;
+}
+
+
+/* Callback to be called to handle transaction state changed. */
+static void tu_on_tsx_state(pjsip_transaction *tsx, pjsip_event *event)
+{
+ struct uac_data *uac_data;
+ pj_status_t status;
+
+ if (tsx->role == PJSIP_ROLE_UAS) {
+ if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
+ struct uas_data *uas_data;
+
+ uas_data = (struct uas_data*) tsx->mod_data[mod_tu.id];
+ if (uas_data->uac_tsx) {
+ uac_data = (struct uac_data*)
+ uas_data->uac_tsx->mod_data[mod_tu.id];
+ uac_data->uas_tsx = NULL;
+ }
+
+ }
+ return;
+ }
+
+ /* Get the data that we attached to the UAC transaction previously */
+ uac_data = (struct uac_data*) tsx->mod_data[mod_tu.id];
+
+
+ /* Handle incoming response */
+ if (event->body.tsx_state.type == PJSIP_EVENT_RX_MSG) {
+
+ pjsip_rx_data *rdata;
+ pjsip_response_addr res_addr;
+ pjsip_via_hdr *hvia;
+ pjsip_tx_data *tdata;
+
+ rdata = event->body.tsx_state.src.rdata;
+
+ /* Do not forward 100 response for INVITE (we already responded
+ * INVITE with 100)
+ */
+ if (tsx->method.id == PJSIP_INVITE_METHOD &&
+ rdata->msg_info.msg->line.status.code == 100)
+ {
+ return;
+ }
+
+ /* Create response to be forwarded upstream
+ * (Via will be stripped here)
+ */
+ status = pjsip_endpt_create_response_fwd(global.endpt, rdata, 0,
+ &tdata);
+ if (status != PJ_SUCCESS) {
+ app_perror("Error creating response", status);
+ return;
+ }
+
+ /* Get topmost Via header of the new response */
+ hvia = (pjsip_via_hdr*) pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA,
+ NULL);
+ if (hvia == NULL) {
+ /* Invalid response! Just drop it */
+ pjsip_tx_data_dec_ref(tdata);
+ return;
+ }
+
+ /* Calculate the address to forward the response */
+ pj_bzero(&res_addr, sizeof(res_addr));
+ res_addr.dst_host.type = PJSIP_TRANSPORT_UDP;
+ res_addr.dst_host.flag =
+ pjsip_transport_get_flag_from_type(PJSIP_TRANSPORT_UDP);
+
+ /* Destination address is Via's received param */
+ res_addr.dst_host.addr.host = hvia->recvd_param;
+ if (res_addr.dst_host.addr.host.slen == 0) {
+ /* Someone has messed up our Via header! */
+ res_addr.dst_host.addr.host = hvia->sent_by.host;
+ }
+
+ /* Destination port is the rport */
+ if (hvia->rport_param != 0 && hvia->rport_param != -1)
+ res_addr.dst_host.addr.port = hvia->rport_param;
+
+ if (res_addr.dst_host.addr.port == 0) {
+ /* Ugh, original sender didn't put rport!
+ * At best, can only send the response to the port in Via.
+ */
+ res_addr.dst_host.addr.port = hvia->sent_by.port;
+ }
+
+ /* Forward response with the UAS transaction */
+ pjsip_tsx_send_msg(uac_data->uas_tsx, tdata);
+
+ }
+
+ /* If UAC transaction is terminated, terminate the UAS as well.
+ * This could happen because of:
+ * - timeout on the UAC side
+ * - receipt of 2xx response to INVITE
+ */
+ if (tsx->state == PJSIP_TSX_STATE_TERMINATED && uac_data &&
+ uac_data->uas_tsx)
+ {
+
+ pjsip_transaction *uas_tsx;
+ struct uas_data *uas_data;
+
+ uas_tsx = uac_data->uas_tsx;
+ uas_data = (struct uas_data*) uas_tsx->mod_data[mod_tu.id];
+ uas_data->uac_tsx = NULL;
+
+ if (event->body.tsx_state.type == PJSIP_EVENT_TIMER) {
+
+ /* Send 408/Timeout if this is an INVITE transaction, since
+ * we must have sent provisional response before. For non
+ * INVITE transaction, just destroy it.
+ */
+ if (tsx->method.id == PJSIP_INVITE_METHOD) {
+
+ pjsip_tx_data *tdata = uas_tsx->last_tx;
+
+ tdata->msg->line.status.code = PJSIP_SC_REQUEST_TIMEOUT;
+ tdata->msg->line.status.reason = pj_str("Request timed out");
+ tdata->msg->body = NULL;
+
+ pjsip_tx_data_add_ref(tdata);
+ pjsip_tx_data_invalidate_msg(tdata);
+
+ pjsip_tsx_send_msg(uas_tsx, tdata);
+
+ } else {
+ /* For non-INVITE, just destroy the UAS transaction */
+ pjsip_tsx_terminate(uas_tsx, PJSIP_SC_REQUEST_TIMEOUT);
+ }
+
+ } else if (event->body.tsx_state.type == PJSIP_EVENT_RX_MSG) {
+
+ if (uas_tsx->state < PJSIP_TSX_STATE_TERMINATED) {
+ pjsip_msg *msg;
+ int code;
+
+ msg = event->body.tsx_state.src.rdata->msg_info.msg;
+ code = msg->line.status.code;
+
+ uac_data->uas_tsx = NULL;
+ pjsip_tsx_terminate(uas_tsx, code);
+ }
+ }
+ }
+}
+
+
+/*
+ * main()
+ */
+int main(int argc, char *argv[])
+{
+ pj_status_t status;
+
+ global.port = 5060;
+ global.record_route = 0;
+
+ pj_log_set_level(4);
+
+ status = init_options(argc, argv);
+ if (status != PJ_SUCCESS)
+ return 1;
+
+ status = init_stack();
+ if (status != PJ_SUCCESS) {
+ app_perror("Error initializing stack", status);
+ return 1;
+ }
+
+ status = init_proxy();
+ if (status != PJ_SUCCESS) {
+ app_perror("Error initializing proxy", status);
+ return 1;
+ }
+
+ status = init_stateful_proxy();
+ if (status != PJ_SUCCESS) {
+ app_perror("Error initializing stateful proxy", status);
+ return 1;
+ }
+
+#if PJ_HAS_THREADS
+ status = pj_thread_create(global.pool, "sproxy", &worker_thread,
+ NULL, 0, 0, &global.thread);
+ if (status != PJ_SUCCESS) {
+ app_perror("Error creating thread", status);
+ return 1;
+ }
+
+ while (!global.quit_flag) {
+ char line[10];
+
+ puts("\n"
+ "Menu:\n"
+ " q quit\n"
+ " d dump status\n"
+ " dd dump detailed status\n"
+ "");
+
+ if (fgets(line, sizeof(line), stdin) == NULL) {
+ puts("EOF while reading stdin, will quit now..");
+ global.quit_flag = PJ_TRUE;
+ break;
+ }
+
+ if (line[0] == 'q') {
+ global.quit_flag = PJ_TRUE;
+ } else if (line[0] == 'd') {
+ pj_bool_t detail = (line[1] == 'd');
+ pjsip_endpt_dump(global.endpt, detail);
+ pjsip_tsx_layer_dump(detail);
+ }
+ }
+
+ pj_thread_join(global.thread);
+
+#else
+ puts("\nPress Ctrl-C to quit\n");
+ for (;;) {
+ pj_time_val delay = {0, 0};
+ pjsip_endpt_handle_events(global.endpt, &delay);
+ }
+#endif
+
+ destroy_stack();
+
+ return 0;
+}
+
diff --git a/pjsip-apps/src/samples/stateless_proxy.c b/pjsip-apps/src/samples/stateless_proxy.c
new file mode 100644
index 0000000..826385c
--- /dev/null
+++ b/pjsip-apps/src/samples/stateless_proxy.c
@@ -0,0 +1,255 @@
+/* $Id: stateless_proxy.c 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#define THIS_FILE "stateless_proxy.c"
+
+/* Common proxy functions */
+#define STATEFUL 0
+#include "proxy.h"
+
+
+/* Callback to be called to handle incoming requests. */
+static pj_bool_t on_rx_request( pjsip_rx_data *rdata );
+
+/* Callback to be called to handle incoming response. */
+static pj_bool_t on_rx_response( pjsip_rx_data *rdata );
+
+
+static pj_status_t init_stateless_proxy(void)
+{
+ static pjsip_module mod_stateless_proxy =
+ {
+ NULL, NULL, /* prev, next. */
+ { "mod-stateless-proxy", 19 }, /* Name. */
+ -1, /* Id */
+ PJSIP_MOD_PRIORITY_UA_PROXY_LAYER, /* Priority */
+ NULL, /* load() */
+ NULL, /* start() */
+ NULL, /* stop() */
+ NULL, /* unload() */
+ &on_rx_request, /* on_rx_request() */
+ &on_rx_response, /* on_rx_response() */
+ NULL, /* on_tx_request. */
+ NULL, /* on_tx_response() */
+ NULL, /* on_tsx_state() */
+ };
+
+ pj_status_t status;
+
+ /* Register our module to receive incoming requests. */
+ status = pjsip_endpt_register_module( global.endpt, &mod_stateless_proxy);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ return PJ_SUCCESS;
+}
+
+
+/* Callback to be called to handle incoming requests. */
+static pj_bool_t on_rx_request( pjsip_rx_data *rdata )
+{
+ pjsip_tx_data *tdata;
+ pj_status_t status;
+
+
+ /* Verify incoming request */
+ status = proxy_verify_request(rdata);
+ if (status != PJ_SUCCESS) {
+ app_perror("RX invalid request", status);
+ return PJ_TRUE;
+ }
+
+ /*
+ * Request looks sane, next clone the request to create transmit data.
+ */
+ status = pjsip_endpt_create_request_fwd(global.endpt, rdata, NULL,
+ NULL, 0, &tdata);
+ if (status != PJ_SUCCESS) {
+ pjsip_endpt_respond_stateless(global.endpt, rdata,
+ PJSIP_SC_INTERNAL_SERVER_ERROR, NULL,
+ NULL, NULL);
+ return PJ_TRUE;
+ }
+
+
+ /* Process routing */
+ status = proxy_process_routing(tdata);
+ if (status != PJ_SUCCESS) {
+ app_perror("Error processing route", status);
+ return PJ_TRUE;
+ }
+
+ /* Calculate target */
+ status = proxy_calculate_target(rdata, tdata);
+ if (status != PJ_SUCCESS) {
+ app_perror("Error calculating target", status);
+ return PJ_TRUE;
+ }
+
+ /* Target is set, forward the request */
+ status = pjsip_endpt_send_request_stateless(global.endpt, tdata,
+ NULL, NULL);
+ if (status != PJ_SUCCESS) {
+ app_perror("Error forwarding request", status);
+ return PJ_TRUE;
+ }
+
+ return PJ_TRUE;
+}
+
+
+/* Callback to be called to handle incoming response. */
+static pj_bool_t on_rx_response( pjsip_rx_data *rdata )
+{
+ pjsip_tx_data *tdata;
+ pjsip_response_addr res_addr;
+ pjsip_via_hdr *hvia;
+ pj_status_t status;
+
+ /* Create response to be forwarded upstream (Via will be stripped here) */
+ status = pjsip_endpt_create_response_fwd(global.endpt, rdata, 0, &tdata);
+ if (status != PJ_SUCCESS) {
+ app_perror("Error creating response", status);
+ return PJ_TRUE;
+ }
+
+ /* Get topmost Via header */
+ hvia = (pjsip_via_hdr*) pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL);
+ if (hvia == NULL) {
+ /* Invalid response! Just drop it */
+ pjsip_tx_data_dec_ref(tdata);
+ return PJ_TRUE;
+ }
+
+ /* Calculate the address to forward the response */
+ pj_bzero(&res_addr, sizeof(res_addr));
+ res_addr.dst_host.type = PJSIP_TRANSPORT_UDP;
+ res_addr.dst_host.flag = pjsip_transport_get_flag_from_type(PJSIP_TRANSPORT_UDP);
+
+ /* Destination address is Via's received param */
+ res_addr.dst_host.addr.host = hvia->recvd_param;
+ if (res_addr.dst_host.addr.host.slen == 0) {
+ /* Someone has messed up our Via header! */
+ res_addr.dst_host.addr.host = hvia->sent_by.host;
+ }
+
+ /* Destination port is the rpot */
+ if (hvia->rport_param != 0 && hvia->rport_param != -1)
+ res_addr.dst_host.addr.port = hvia->rport_param;
+
+ if (res_addr.dst_host.addr.port == 0) {
+ /* Ugh, original sender didn't put rport!
+ * At best, can only send the response to the port in Via.
+ */
+ res_addr.dst_host.addr.port = hvia->sent_by.port;
+ }
+
+ /* Forward response */
+ status = pjsip_endpt_send_response(global.endpt, &res_addr, tdata,
+ NULL, NULL);
+ if (status != PJ_SUCCESS) {
+ app_perror("Error forwarding response", status);
+ return PJ_TRUE;
+ }
+
+ return PJ_TRUE;
+}
+
+
+/*
+ * main()
+ */
+int main(int argc, char *argv[])
+{
+ pj_status_t status;
+
+ global.port = 5060;
+ pj_log_set_level(4);
+
+ status = init_options(argc, argv);
+ if (status != PJ_SUCCESS)
+ return 1;
+
+ status = init_stack();
+ if (status != PJ_SUCCESS) {
+ app_perror("Error initializing stack", status);
+ return 1;
+ }
+
+ status = init_proxy();
+ if (status != PJ_SUCCESS) {
+ app_perror("Error initializing proxy", status);
+ return 1;
+ }
+
+ status = init_stateless_proxy();
+ if (status != PJ_SUCCESS) {
+ app_perror("Error initializing stateless proxy", status);
+ return 1;
+ }
+
+#if PJ_HAS_THREADS
+ status = pj_thread_create(global.pool, "sproxy", &worker_thread,
+ NULL, 0, 0, &global.thread);
+ if (status != PJ_SUCCESS) {
+ app_perror("Error creating thread", status);
+ return 1;
+ }
+
+ while (!global.quit_flag) {
+ char line[10];
+
+ puts("\n"
+ "Menu:\n"
+ " q quit\n"
+ " d dump status\n"
+ " dd dump detailed status\n"
+ "");
+
+ if (fgets(line, sizeof(line), stdin) == NULL) {
+ puts("EOF while reading stdin, will quit now..");
+ global.quit_flag = PJ_TRUE;
+ break;
+ }
+
+ if (line[0] == 'q') {
+ global.quit_flag = PJ_TRUE;
+ } else if (line[0] == 'd') {
+ pj_bool_t detail = (line[1] == 'd');
+ pjsip_endpt_dump(global.endpt, detail);
+#if STATEFUL
+ pjsip_tsx_layer_dump(detail);
+#endif
+ }
+ }
+
+ pj_thread_join(global.thread);
+
+#else
+ puts("\nPress Ctrl-C to quit\n");
+ for (;;) {
+ pj_time_val delay = {0, 0};
+ pjsip_endpt_handle_events(global.endpt, &delay);
+ }
+#endif
+
+ destroy_stack();
+
+ return 0;
+}
+
diff --git a/pjsip-apps/src/samples/stereotest.c b/pjsip-apps/src/samples/stereotest.c
new file mode 100644
index 0000000..8931270
--- /dev/null
+++ b/pjsip-apps/src/samples/stereotest.c
@@ -0,0 +1,336 @@
+/* $Id: stereotest.c 3664 2011-07-19 03:42:28Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/**
+ * \page page_pjmedia_samples_stereo_c Samples: Using Stereo Port
+ *
+ * This example demonstrates how to use @ref PJMEDIA_STEREO_PORT to
+ * change the channel count of the media streams.
+ *
+ * This file is pjsip-apps/src/samples/stereotest.c
+ *
+ * \includelineno stereotest.c
+ */
+
+#include <pjmedia.h>
+#include <pjlib-util.h>
+#include <pjlib.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "util.h"
+
+#define REC_CLOCK_RATE 16000
+#define PTIME 20
+
+#define MODE_PLAY 1
+#define MODE_RECORD 2
+
+
+/* For logging purpose. */
+#define THIS_FILE "stereotest.c"
+
+
+static const char *desc =
+" FILE \n"
+" \n"
+" stereotest.c \n"
+" \n"
+" PURPOSE \n"
+" \n"
+" Demonstrate how use stereo port to play a WAV file to sound \n"
+" device or record to a WAV file from sound device with different \n"
+" channel count. \n"
+" \n"
+" USAGE \n"
+" \n"
+" stereotest [options] WAV \n"
+" \n"
+" Options: \n"
+" -m, --mode=N Operation mode: 1 = playing, 2 = recording.\n"
+" -C, --rec-ch-cnt=N Number of channel for recording file. \n"
+" -c, --snd-ch-cnt=N Number of channel for opening sound device.\n"
+" \n";
+
+int main(int argc, char *argv[])
+{
+ pj_caching_pool cp;
+ pjmedia_endpt *med_endpt;
+ pj_pool_t *pool;
+
+ pjmedia_port *file_port = NULL;
+ pjmedia_port *stereo_port = NULL;
+ pjmedia_snd_port *snd_port = NULL;
+
+ int dev_id = -1;
+ char tmp[10];
+ pj_status_t status;
+
+ char *wav_file = NULL;
+ unsigned mode = 0;
+ unsigned rec_ch_cnt = 1;
+ unsigned snd_ch_cnt = 2;
+
+ enum {
+ OPT_MODE = 'm',
+ OPT_REC_CHANNEL = 'C',
+ OPT_SND_CHANNEL = 'c',
+ };
+
+ struct pj_getopt_option long_options[] = {
+ { "mode", 1, 0, OPT_MODE },
+ { "rec-ch-cnt", 1, 0, OPT_REC_CHANNEL },
+ { "snd-ch-cnt", 1, 0, OPT_SND_CHANNEL },
+ { NULL, 0, 0, 0 },
+ };
+
+ int c;
+ int option_index;
+
+ /* Must init PJLIB first: */
+ status = pj_init();
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ /* Parse arguments */
+ pj_optind = 0;
+ while((c=pj_getopt_long(argc,argv, "m:C:c:", long_options, &option_index))!=-1) {
+
+ switch (c) {
+ case OPT_MODE:
+ if (mode) {
+ app_perror(THIS_FILE, "Cannot record and play at once!",
+ PJ_EINVAL);
+ return 1;
+ }
+ mode = atoi(pj_optarg);
+ break;
+
+ case OPT_REC_CHANNEL:
+ rec_ch_cnt = atoi(pj_optarg);
+ break;
+
+ case OPT_SND_CHANNEL:
+ snd_ch_cnt = atoi(pj_optarg);
+ break;
+
+ default:
+ printf("Invalid options %s\n", argv[pj_optind]);
+ puts(desc);
+ return 1;
+ }
+
+ }
+
+ wav_file = argv[pj_optind];
+
+ /* Verify arguments. */
+ if (!wav_file) {
+ app_perror(THIS_FILE, "WAV file not specified!", PJ_EINVAL);
+ puts(desc);
+ return 1;
+ }
+ if (!snd_ch_cnt || !rec_ch_cnt || rec_ch_cnt > 6) {
+ app_perror(THIS_FILE, "Invalid or too many channel count!", PJ_EINVAL);
+ puts(desc);
+ return 1;
+ }
+ if (mode != MODE_RECORD && mode != MODE_PLAY) {
+ app_perror(THIS_FILE, "Invalid operation mode!", PJ_EINVAL);
+ puts(desc);
+ return 1;
+ }
+
+ /* Must create a pool factory before we can allocate any memory. */
+ pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);
+
+ /*
+ * Initialize media endpoint.
+ * This will implicitly initialize PJMEDIA too.
+ */
+ status = pjmedia_endpt_create(&cp.factory, NULL, 1, &med_endpt);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ /* Create memory pool for our file player */
+ pool = pj_pool_create( &cp.factory, /* pool factory */
+ "app", /* pool name. */
+ 4000, /* init size */
+ 4000, /* increment size */
+ NULL /* callback on error */
+ );
+
+ if (mode == MODE_PLAY) {
+ /* Create WAVE file player port. */
+ status = pjmedia_wav_player_port_create( pool, wav_file, PTIME, 0,
+ 0, &file_port);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to open file", status);
+ return 1;
+ }
+
+ /* Create sound player port. */
+ status = pjmedia_snd_port_create_player(
+ pool, /* pool */
+ dev_id, /* device id. */
+ PJMEDIA_PIA_SRATE(&file_port->info),/* clock rate. */
+ snd_ch_cnt, /* # of channels. */
+ snd_ch_cnt * PTIME * /* samples per frame. */
+ PJMEDIA_PIA_SRATE(&file_port->info) / 1000,
+ PJMEDIA_PIA_BITS(&file_port->info),/* bits per sample. */
+ 0, /* options */
+ &snd_port /* returned port */
+ );
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to open sound device", status);
+ return 1;
+ }
+
+ if (snd_ch_cnt != PJMEDIA_PIA_CCNT(&file_port->info)) {
+ status = pjmedia_stereo_port_create( pool,
+ file_port,
+ snd_ch_cnt,
+ 0,
+ &stereo_port);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to create stereo port", status);
+ return 1;
+ }
+
+ status = pjmedia_snd_port_connect(snd_port, stereo_port);
+ } else {
+ status = pjmedia_snd_port_connect(snd_port, file_port);
+ }
+
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to connect sound port", status);
+ return 1;
+ }
+
+ } else {
+ /* Create WAVE file writer port. */
+ status = pjmedia_wav_writer_port_create(pool, wav_file,
+ REC_CLOCK_RATE,
+ rec_ch_cnt,
+ rec_ch_cnt * PTIME *
+ REC_CLOCK_RATE / 1000,
+ NBITS,
+ 0, 0,
+ &file_port);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to open file", status);
+ return 1;
+ }
+
+ /* Create sound player port. */
+ status = pjmedia_snd_port_create_rec(
+ pool, /* pool */
+ dev_id, /* device id. */
+ REC_CLOCK_RATE, /* clock rate. */
+ snd_ch_cnt, /* # of channels. */
+ snd_ch_cnt * PTIME *
+ REC_CLOCK_RATE / 1000, /* samples per frame. */
+ NBITS, /* bits per sample. */
+ 0, /* options */
+ &snd_port /* returned port */
+ );
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to open sound device", status);
+ return 1;
+ }
+
+ if (rec_ch_cnt != snd_ch_cnt) {
+ status = pjmedia_stereo_port_create( pool,
+ file_port,
+ snd_ch_cnt,
+ 0,
+ &stereo_port);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to create stereo port", status);
+ return 1;
+ }
+
+ status = pjmedia_snd_port_connect(snd_port, stereo_port);
+ } else {
+ status = pjmedia_snd_port_connect(snd_port, file_port);
+ }
+
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to connect sound port", status);
+ return 1;
+ }
+ }
+
+ /* Dump memory usage */
+ dump_pool_usage(THIS_FILE, &cp);
+
+ /*
+ * File should be playing and looping now, using sound device's thread.
+ */
+
+
+ /* Sleep to allow log messages to flush */
+ pj_thread_sleep(100);
+
+ printf("Mode = %s\n", (mode == MODE_PLAY? "playing" : "recording") );
+ printf("File port channel count = %d\n", PJMEDIA_PIA_CCNT(&file_port->info));
+ printf("Sound port channel count = %d\n",
+ PJMEDIA_PIA_CCNT(&pjmedia_snd_port_get_port(snd_port)->info));
+ puts("");
+ puts("Press <ENTER> to stop and quit");
+
+ if (fgets(tmp, sizeof(tmp), stdin) == NULL) {
+ puts("EOF while reading stdin, will quit now..");
+ }
+
+ /* Start deinitialization: */
+
+
+ /* Destroy sound device */
+ status = pjmedia_snd_port_destroy( snd_port );
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+
+ /* Destroy stereo port and file_port.
+ * Stereo port will destroy all downstream ports (e.g. the file port)
+ */
+ status = pjmedia_port_destroy( stereo_port? stereo_port : file_port);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+
+ /* Release application pool */
+ pj_pool_release( pool );
+
+ /* Destroy media endpoint. */
+ pjmedia_endpt_destroy( med_endpt );
+
+ /* Destroy pool factory */
+ pj_caching_pool_destroy( &cp );
+
+ /* Shutdown PJLIB */
+ pj_shutdown();
+
+
+ /* Done. */
+ return 0;
+
+}
+
+
+
diff --git a/pjsip-apps/src/samples/streamutil.c b/pjsip-apps/src/samples/streamutil.c
new file mode 100644
index 0000000..a59621b
--- /dev/null
+++ b/pjsip-apps/src/samples/streamutil.c
@@ -0,0 +1,1174 @@
+/* $Id: streamutil.c 3664 2011-07-19 03:42:28Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+/**
+ * \page page_pjmedia_samples_streamutil_c Samples: Remote Streaming
+ *
+ * This example mainly demonstrates how to stream media file to remote
+ * peer using RTP.
+ *
+ * This file is pjsip-apps/src/samples/streamutil.c
+ *
+ * \includelineno streamutil.c
+ */
+
+#include <pjlib.h>
+#include <pjlib-util.h>
+#include <pjmedia.h>
+#include <pjmedia-codec.h>
+#include <pjmedia/transport_srtp.h>
+
+#include <stdlib.h> /* atoi() */
+#include <stdio.h>
+
+#include "util.h"
+
+
+static const char *desc =
+ " streamutil \n"
+ " \n"
+ " PURPOSE: \n"
+ " Demonstrate how to use pjmedia stream component to transmit/receive \n"
+ " RTP packets to/from sound device. \n"
+ "\n"
+ "\n"
+ " USAGE: \n"
+ " streamutil [options] \n"
+ "\n"
+ "\n"
+ " Options:\n"
+ " --codec=CODEC Set the codec name. \n"
+ " --local-port=PORT Set local RTP port (default=4000) \n"
+ " --remote=IP:PORT Set the remote peer. If this option is set, \n"
+ " the program will transmit RTP audio to the \n"
+ " specified address. (default: recv only) \n"
+ " --play-file=WAV Send audio from the WAV file instead of from \n"
+ " the sound device. \n"
+ " --record-file=WAV Record incoming audio to WAV file instead of \n"
+ " playing it to sound device. \n"
+ " --send-recv Set stream direction to bidirectional. \n"
+ " --send-only Set stream direction to send only \n"
+ " --recv-only Set stream direction to recv only (default) \n"
+
+#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
+ " --use-srtp[=NAME] Enable SRTP with crypto suite NAME \n"
+ " e.g: AES_CM_128_HMAC_SHA1_80 (default), \n"
+ " AES_CM_128_HMAC_SHA1_32 \n"
+ " Use this option along with the TX & RX keys, \n"
+ " formated of 60 hex digits (e.g: E148DA..) \n"
+ " --srtp-tx-key SRTP key for transmiting \n"
+ " --srtp-rx-key SRTP key for receiving \n"
+#endif
+
+ "\n"
+;
+
+
+
+
+#define THIS_FILE "stream.c"
+
+
+
+/* Prototype */
+static void print_stream_stat(pjmedia_stream *stream,
+ const pjmedia_codec_param *codec_param);
+
+/* Prototype for LIBSRTP utility in file datatypes.c */
+int hex_string_to_octet_string(char *raw, char *hex, int len);
+
+/*
+ * Register all codecs.
+ */
+static pj_status_t init_codecs(pjmedia_endpt *med_endpt)
+{
+ return pjmedia_codec_register_audio_codecs(med_endpt, NULL);
+}
+
+
+/*
+ * Create stream based on the codec, dir, remote address, etc.
+ */
+static pj_status_t create_stream( pj_pool_t *pool,
+ pjmedia_endpt *med_endpt,
+ const pjmedia_codec_info *codec_info,
+ pjmedia_dir dir,
+ pj_uint16_t local_port,
+ const pj_sockaddr_in *rem_addr,
+#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
+ pj_bool_t use_srtp,
+ const pj_str_t *crypto_suite,
+ const pj_str_t *srtp_tx_key,
+ const pj_str_t *srtp_rx_key,
+#endif
+ pjmedia_stream **p_stream )
+{
+ pjmedia_stream_info info;
+ pjmedia_transport *transport = NULL;
+ pj_status_t status;
+#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
+ pjmedia_transport *srtp_tp = NULL;
+#endif
+
+
+ /* Reset stream info. */
+ pj_bzero(&info, sizeof(info));
+
+
+ /* Initialize stream info formats */
+ info.type = PJMEDIA_TYPE_AUDIO;
+ info.dir = dir;
+ pj_memcpy(&info.fmt, codec_info, sizeof(pjmedia_codec_info));
+ info.tx_pt = codec_info->pt;
+ info.ssrc = pj_rand();
+
+#if PJMEDIA_HAS_RTCP_XR && PJMEDIA_STREAM_ENABLE_XR
+ /* Set default RTCP XR enabled/disabled */
+ info.rtcp_xr_enabled = PJ_TRUE;
+#endif
+
+ /* Copy remote address */
+ pj_memcpy(&info.rem_addr, rem_addr, sizeof(pj_sockaddr_in));
+
+ /* If remote address is not set, set to an arbitrary address
+ * (otherwise stream will assert).
+ */
+ if (info.rem_addr.addr.sa_family == 0) {
+ const pj_str_t addr = pj_str("127.0.0.1");
+ pj_sockaddr_in_init(&info.rem_addr.ipv4, &addr, 0);
+ }
+
+ /* Create media transport */
+ status = pjmedia_transport_udp_create(med_endpt, NULL, local_port,
+ 0, &transport);
+ if (status != PJ_SUCCESS)
+ return status;
+
+#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
+ /* Check if SRTP enabled */
+ if (use_srtp) {
+ pjmedia_srtp_crypto tx_plc, rx_plc;
+
+ status = pjmedia_transport_srtp_create(med_endpt, transport,
+ NULL, &srtp_tp);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ pj_bzero(&tx_plc, sizeof(pjmedia_srtp_crypto));
+ pj_bzero(&rx_plc, sizeof(pjmedia_srtp_crypto));
+
+ tx_plc.key = *srtp_tx_key;
+ tx_plc.name = *crypto_suite;
+ rx_plc.key = *srtp_rx_key;
+ rx_plc.name = *crypto_suite;
+
+ status = pjmedia_transport_srtp_start(srtp_tp, &tx_plc, &rx_plc);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ transport = srtp_tp;
+ }
+#endif
+
+ /* Now that the stream info is initialized, we can create the
+ * stream.
+ */
+
+ status = pjmedia_stream_create( med_endpt, pool, &info,
+ transport,
+ NULL, p_stream);
+
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Error creating stream", status);
+ pjmedia_transport_close(transport);
+ return status;
+ }
+
+
+ return PJ_SUCCESS;
+}
+
+
+/*
+ * usage()
+ */
+static void usage()
+{
+ puts(desc);
+}
+
+/*
+ * main()
+ */
+int main(int argc, char *argv[])
+{
+ pj_caching_pool cp;
+ pjmedia_endpt *med_endpt;
+ pj_pool_t *pool;
+ pjmedia_port *rec_file_port = NULL, *play_file_port = NULL;
+ pjmedia_master_port *master_port = NULL;
+ pjmedia_snd_port *snd_port = NULL;
+ pjmedia_stream *stream = NULL;
+ pjmedia_port *stream_port;
+ char tmp[10];
+ pj_status_t status;
+
+#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
+ /* SRTP variables */
+ pj_bool_t use_srtp = PJ_FALSE;
+ char tmp_tx_key[64];
+ char tmp_rx_key[64];
+ pj_str_t srtp_tx_key = {NULL, 0};
+ pj_str_t srtp_rx_key = {NULL, 0};
+ pj_str_t srtp_crypto_suite = {NULL, 0};
+ int tmp_key_len;
+#endif
+
+ /* Default values */
+ const pjmedia_codec_info *codec_info;
+ pjmedia_codec_param codec_param;
+ pjmedia_dir dir = PJMEDIA_DIR_DECODING;
+ pj_sockaddr_in remote_addr;
+ pj_uint16_t local_port = 4000;
+ char *codec_id = NULL;
+ char *rec_file = NULL;
+ char *play_file = NULL;
+
+ enum {
+ OPT_CODEC = 'c',
+ OPT_LOCAL_PORT = 'p',
+ OPT_REMOTE = 'r',
+ OPT_PLAY_FILE = 'w',
+ OPT_RECORD_FILE = 'R',
+ OPT_SEND_RECV = 'b',
+ OPT_SEND_ONLY = 's',
+ OPT_RECV_ONLY = 'i',
+#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
+ OPT_USE_SRTP = 'S',
+#endif
+ OPT_SRTP_TX_KEY = 'x',
+ OPT_SRTP_RX_KEY = 'y',
+ OPT_HELP = 'h',
+ };
+
+ struct pj_getopt_option long_options[] = {
+ { "codec", 1, 0, OPT_CODEC },
+ { "local-port", 1, 0, OPT_LOCAL_PORT },
+ { "remote", 1, 0, OPT_REMOTE },
+ { "play-file", 1, 0, OPT_PLAY_FILE },
+ { "record-file", 1, 0, OPT_RECORD_FILE },
+ { "send-recv", 0, 0, OPT_SEND_RECV },
+ { "send-only", 0, 0, OPT_SEND_ONLY },
+ { "recv-only", 0, 0, OPT_RECV_ONLY },
+#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
+ { "use-srtp", 2, 0, OPT_USE_SRTP },
+ { "srtp-tx-key", 1, 0, OPT_SRTP_TX_KEY },
+ { "srtp-rx-key", 1, 0, OPT_SRTP_RX_KEY },
+#endif
+ { "help", 0, 0, OPT_HELP },
+ { NULL, 0, 0, 0 },
+ };
+
+ int c;
+ int option_index;
+
+
+ pj_bzero(&remote_addr, sizeof(remote_addr));
+
+
+ /* init PJLIB : */
+ status = pj_init();
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+
+ /* Parse arguments */
+ pj_optind = 0;
+ while((c=pj_getopt_long(argc,argv, "h", long_options, &option_index))!=-1) {
+
+ switch (c) {
+ case OPT_CODEC:
+ codec_id = pj_optarg;
+ break;
+
+ case OPT_LOCAL_PORT:
+ local_port = (pj_uint16_t) atoi(pj_optarg);
+ if (local_port < 1) {
+ printf("Error: invalid local port %s\n", pj_optarg);
+ return 1;
+ }
+ break;
+
+ case OPT_REMOTE:
+ {
+ pj_str_t ip = pj_str(strtok(pj_optarg, ":"));
+ pj_uint16_t port = (pj_uint16_t) atoi(strtok(NULL, ":"));
+
+ status = pj_sockaddr_in_init(&remote_addr, &ip, port);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Invalid remote address", status);
+ return 1;
+ }
+ }
+ break;
+
+ case OPT_PLAY_FILE:
+ play_file = pj_optarg;
+ break;
+
+ case OPT_RECORD_FILE:
+ rec_file = pj_optarg;
+ break;
+
+ case OPT_SEND_RECV:
+ dir = PJMEDIA_DIR_ENCODING_DECODING;
+ break;
+
+ case OPT_SEND_ONLY:
+ dir = PJMEDIA_DIR_ENCODING;
+ break;
+
+ case OPT_RECV_ONLY:
+ dir = PJMEDIA_DIR_DECODING;
+ break;
+
+#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
+ case OPT_USE_SRTP:
+ use_srtp = PJ_TRUE;
+ if (pj_optarg) {
+ pj_strset(&srtp_crypto_suite, pj_optarg, strlen(pj_optarg));
+ } else {
+ srtp_crypto_suite = pj_str("AES_CM_128_HMAC_SHA1_80");
+ }
+ break;
+
+ case OPT_SRTP_TX_KEY:
+ tmp_key_len = hex_string_to_octet_string(tmp_tx_key, pj_optarg, strlen(pj_optarg));
+ pj_strset(&srtp_tx_key, tmp_tx_key, tmp_key_len/2);
+ break;
+
+ case OPT_SRTP_RX_KEY:
+ tmp_key_len = hex_string_to_octet_string(tmp_rx_key, pj_optarg, strlen(pj_optarg));
+ pj_strset(&srtp_rx_key, tmp_rx_key, tmp_key_len/2);
+ break;
+#endif
+
+ case OPT_HELP:
+ usage();
+ return 1;
+
+ default:
+ printf("Invalid options %s\n", argv[pj_optind]);
+ return 1;
+ }
+
+ }
+
+
+ /* Verify arguments. */
+ if (dir & PJMEDIA_DIR_ENCODING) {
+ if (remote_addr.sin_addr.s_addr == 0) {
+ printf("Error: remote address must be set\n");
+ return 1;
+ }
+ }
+
+ if (play_file != NULL && dir != PJMEDIA_DIR_ENCODING) {
+ printf("Direction is set to --send-only because of --play-file\n");
+ dir = PJMEDIA_DIR_ENCODING;
+ }
+
+#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
+ /* SRTP validation */
+ if (use_srtp) {
+ if (!srtp_tx_key.slen || !srtp_rx_key.slen)
+ {
+ printf("Error: Key for each SRTP stream direction must be set\n");
+ return 1;
+ }
+ }
+#endif
+
+ /* Must create a pool factory before we can allocate any memory. */
+ pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);
+
+ /*
+ * Initialize media endpoint.
+ * This will implicitly initialize PJMEDIA too.
+ */
+ status = pjmedia_endpt_create(&cp.factory, NULL, 1, &med_endpt);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ /* Create memory pool for application purpose */
+ pool = pj_pool_create( &cp.factory, /* pool factory */
+ "app", /* pool name. */
+ 4000, /* init size */
+ 4000, /* increment size */
+ NULL /* callback on error */
+ );
+
+
+ /* Register all supported codecs */
+ status = init_codecs(med_endpt);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+
+ /* Find which codec to use. */
+ if (codec_id) {
+ unsigned count = 1;
+ pj_str_t str_codec_id = pj_str(codec_id);
+ pjmedia_codec_mgr *codec_mgr = pjmedia_endpt_get_codec_mgr(med_endpt);
+ status = pjmedia_codec_mgr_find_codecs_by_id( codec_mgr,
+ &str_codec_id, &count,
+ &codec_info, NULL);
+ if (status != PJ_SUCCESS) {
+ printf("Error: unable to find codec %s\n", codec_id);
+ return 1;
+ }
+ } else {
+ /* Default to pcmu */
+ pjmedia_codec_mgr_get_codec_info( pjmedia_endpt_get_codec_mgr(med_endpt),
+ 0, &codec_info);
+ }
+
+ /* Create stream based on program arguments */
+ status = create_stream(pool, med_endpt, codec_info, dir, local_port,
+ &remote_addr,
+#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
+ use_srtp, &srtp_crypto_suite,
+ &srtp_tx_key, &srtp_rx_key,
+#endif
+ &stream);
+ if (status != PJ_SUCCESS)
+ goto on_exit;
+
+ /* Get codec default param for info */
+ status = pjmedia_codec_mgr_get_default_param(
+ pjmedia_endpt_get_codec_mgr(med_endpt),
+ codec_info,
+ &codec_param);
+ /* Should be ok, as create_stream() above succeeded */
+ pj_assert(status == PJ_SUCCESS);
+
+ /* Get the port interface of the stream */
+ status = pjmedia_stream_get_port( stream, &stream_port);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+
+ if (play_file) {
+ unsigned wav_ptime;
+
+ wav_ptime = PJMEDIA_PIA_PTIME(&stream_port->info);
+ status = pjmedia_wav_player_port_create(pool, play_file, wav_ptime,
+ 0, -1, &play_file_port);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to use file", status);
+ goto on_exit;
+ }
+
+ status = pjmedia_master_port_create(pool, play_file_port, stream_port,
+ 0, &master_port);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to create master port", status);
+ goto on_exit;
+ }
+
+ status = pjmedia_master_port_start(master_port);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Error starting master port", status);
+ goto on_exit;
+ }
+
+ printf("Playing from WAV file %s..\n", play_file);
+
+ } else if (rec_file) {
+
+ status = pjmedia_wav_writer_port_create(pool, rec_file,
+ PJMEDIA_PIA_SRATE(&stream_port->info),
+ PJMEDIA_PIA_CCNT(&stream_port->info),
+ PJMEDIA_PIA_SPF(&stream_port->info),
+ PJMEDIA_PIA_BITS(&stream_port->info),
+ 0, 0, &rec_file_port);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to use file", status);
+ goto on_exit;
+ }
+
+ status = pjmedia_master_port_create(pool, stream_port, rec_file_port,
+ 0, &master_port);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to create master port", status);
+ goto on_exit;
+ }
+
+ status = pjmedia_master_port_start(master_port);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Error starting master port", status);
+ goto on_exit;
+ }
+
+ printf("Recording to WAV file %s..\n", rec_file);
+
+ } else {
+
+ /* Create sound device port. */
+ if (dir == PJMEDIA_DIR_ENCODING_DECODING)
+ status = pjmedia_snd_port_create(pool, -1, -1,
+ PJMEDIA_PIA_SRATE(&stream_port->info),
+ PJMEDIA_PIA_CCNT(&stream_port->info),
+ PJMEDIA_PIA_SPF(&stream_port->info),
+ PJMEDIA_PIA_BITS(&stream_port->info),
+ 0, &snd_port);
+ else if (dir == PJMEDIA_DIR_ENCODING)
+ status = pjmedia_snd_port_create_rec(pool, -1,
+ PJMEDIA_PIA_SRATE(&stream_port->info),
+ PJMEDIA_PIA_CCNT(&stream_port->info),
+ PJMEDIA_PIA_SPF(&stream_port->info),
+ PJMEDIA_PIA_BITS(&stream_port->info),
+ 0, &snd_port);
+ else
+ status = pjmedia_snd_port_create_player(pool, -1,
+ PJMEDIA_PIA_SRATE(&stream_port->info),
+ PJMEDIA_PIA_CCNT(&stream_port->info),
+ PJMEDIA_PIA_SPF(&stream_port->info),
+ PJMEDIA_PIA_BITS(&stream_port->info),
+ 0, &snd_port);
+
+
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to create sound port", status);
+ goto on_exit;
+ }
+
+ /* Connect sound port to stream */
+ status = pjmedia_snd_port_connect( snd_port, stream_port );
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ }
+
+ /* Start streaming */
+ pjmedia_stream_start(stream);
+
+
+ /* Done */
+
+ if (dir == PJMEDIA_DIR_DECODING)
+ printf("Stream is active, dir is recv-only, local port is %d\n",
+ local_port);
+ else if (dir == PJMEDIA_DIR_ENCODING)
+ printf("Stream is active, dir is send-only, sending to %s:%d\n",
+ pj_inet_ntoa(remote_addr.sin_addr),
+ pj_ntohs(remote_addr.sin_port));
+ else
+ printf("Stream is active, send/recv, local port is %d, "
+ "sending to %s:%d\n",
+ local_port,
+ pj_inet_ntoa(remote_addr.sin_addr),
+ pj_ntohs(remote_addr.sin_port));
+
+
+ for (;;) {
+
+ puts("");
+ puts("Commands:");
+ puts(" s Display media statistics");
+ puts(" q Quit");
+ puts("");
+
+ printf("Command: "); fflush(stdout);
+
+ if (fgets(tmp, sizeof(tmp), stdin) == NULL) {
+ puts("EOF while reading stdin, will quit now..");
+ break;
+ }
+
+ if (tmp[0] == 's')
+ print_stream_stat(stream, &codec_param);
+ else if (tmp[0] == 'q')
+ break;
+
+ }
+
+
+
+ /* Start deinitialization: */
+on_exit:
+
+ /* Destroy sound device */
+ if (snd_port) {
+ pjmedia_snd_port_destroy( snd_port );
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+ }
+
+ /* If there is master port, then we just need to destroy master port
+ * (it will recursively destroy upstream and downstream ports, which
+ * in this case are file_port and stream_port).
+ */
+ if (master_port) {
+ pjmedia_master_port_destroy(master_port, PJ_TRUE);
+ play_file_port = NULL;
+ stream = NULL;
+ }
+
+ /* Destroy stream */
+ if (stream) {
+ pjmedia_transport *tp;
+
+ tp = pjmedia_stream_get_transport(stream);
+ pjmedia_stream_destroy(stream);
+
+ pjmedia_transport_close(tp);
+ }
+
+ /* Destroy file ports */
+ if (play_file_port)
+ pjmedia_port_destroy( play_file_port );
+ if (rec_file_port)
+ pjmedia_port_destroy( rec_file_port );
+
+
+ /* Release application pool */
+ pj_pool_release( pool );
+
+ /* Destroy media endpoint. */
+ pjmedia_endpt_destroy( med_endpt );
+
+ /* Destroy pool factory */
+ pj_caching_pool_destroy( &cp );
+
+ /* Shutdown PJLIB */
+ pj_shutdown();
+
+
+ return (status == PJ_SUCCESS) ? 0 : 1;
+}
+
+
+
+
+static const char *good_number(char *buf, pj_int32_t val)
+{
+ if (val < 1000) {
+ pj_ansi_sprintf(buf, "%d", val);
+ } else if (val < 1000000) {
+ pj_ansi_sprintf(buf, "%d.%dK",
+ val / 1000,
+ (val % 1000) / 100);
+ } else {
+ pj_ansi_sprintf(buf, "%d.%02dM",
+ val / 1000000,
+ (val % 1000000) / 10000);
+ }
+
+ return buf;
+}
+
+
+#define SAMPLES_TO_USEC(usec, samples, clock_rate) \
+ do { \
+ if (samples <= 4294) \
+ usec = samples * 1000000 / clock_rate; \
+ else { \
+ usec = samples * 1000 / clock_rate; \
+ usec *= 1000; \
+ } \
+ } while(0)
+
+#define PRINT_VOIP_MTC_VAL(s, v) \
+ if (v == 127) \
+ sprintf(s, "(na)"); \
+ else \
+ sprintf(s, "%d", v)
+
+
+/*
+ * Print stream statistics
+ */
+static void print_stream_stat(pjmedia_stream *stream,
+ const pjmedia_codec_param *codec_param)
+{
+ char duration[80], last_update[80];
+ char bps[16], ipbps[16], packets[16], bytes[16], ipbytes[16];
+ pjmedia_port *port;
+ pjmedia_rtcp_stat stat;
+ pj_time_val now;
+
+
+ pj_gettimeofday(&now);
+ pjmedia_stream_get_stat(stream, &stat);
+ pjmedia_stream_get_port(stream, &port);
+
+ puts("Stream statistics:");
+
+ /* Print duration */
+ PJ_TIME_VAL_SUB(now, stat.start);
+ sprintf(duration, " Duration: %02ld:%02ld:%02ld.%03ld",
+ now.sec / 3600,
+ (now.sec % 3600) / 60,
+ (now.sec % 60),
+ now.msec);
+
+
+ printf(" Info: audio %dHz, %dms/frame, %sB/s (%sB/s +IP hdr)\n",
+ PJMEDIA_PIA_SRATE(&port->info),
+ PJMEDIA_PIA_PTIME(&port->info),
+ good_number(bps, (codec_param->info.avg_bps+7)/8),
+ good_number(ipbps, ((codec_param->info.avg_bps+7)/8) +
+ (40 * 1000 /
+ codec_param->setting.frm_per_pkt /
+ codec_param->info.frm_ptime)));
+
+ if (stat.rx.update_cnt == 0)
+ strcpy(last_update, "never");
+ else {
+ pj_gettimeofday(&now);
+ PJ_TIME_VAL_SUB(now, stat.rx.update);
+ sprintf(last_update, "%02ldh:%02ldm:%02ld.%03lds ago",
+ now.sec / 3600,
+ (now.sec % 3600) / 60,
+ now.sec % 60,
+ now.msec);
+ }
+
+ printf(" RX stat last update: %s\n"
+ " total %s packets %sB received (%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 dev\n"
+ " loss period: %7.3f %7.3f %7.3f %7.3f %7.3f%s\n"
+ " jitter : %7.3f %7.3f %7.3f %7.3f %7.3f%s\n",
+ last_update,
+ good_number(packets, stat.rx.pkt),
+ good_number(bytes, stat.rx.bytes),
+ good_number(ipbytes, stat.rx.bytes + stat.rx.pkt * 32),
+ "",
+ stat.rx.loss,
+ stat.rx.loss * 100.0 / (stat.rx.pkt + stat.rx.loss),
+ stat.rx.dup,
+ stat.rx.dup * 100.0 / (stat.rx.pkt + stat.rx.loss),
+ stat.rx.reorder,
+ stat.rx.reorder * 100.0 / (stat.rx.pkt + stat.rx.loss),
+ "",
+ stat.rx.loss_period.min / 1000.0,
+ stat.rx.loss_period.mean / 1000.0,
+ stat.rx.loss_period.max / 1000.0,
+ stat.rx.loss_period.last / 1000.0,
+ pj_math_stat_get_stddev(&stat.rx.loss_period) / 1000.0,
+ "",
+ stat.rx.jitter.min / 1000.0,
+ stat.rx.jitter.mean / 1000.0,
+ stat.rx.jitter.max / 1000.0,
+ stat.rx.jitter.last / 1000.0,
+ pj_math_stat_get_stddev(&stat.rx.jitter) / 1000.0,
+ ""
+ );
+
+
+ if (stat.tx.update_cnt == 0)
+ strcpy(last_update, "never");
+ else {
+ pj_gettimeofday(&now);
+ PJ_TIME_VAL_SUB(now, stat.tx.update);
+ sprintf(last_update, "%02ldh:%02ldm:%02ld.%03lds ago",
+ now.sec / 3600,
+ (now.sec % 3600) / 60,
+ now.sec % 60,
+ now.msec);
+ }
+
+ printf(" TX stat last update: %s\n"
+ " total %s packets %sB sent (%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 dev\n"
+ " loss period: %7.3f %7.3f %7.3f %7.3f %7.3f%s\n"
+ " jitter : %7.3f %7.3f %7.3f %7.3f %7.3f%s\n",
+ last_update,
+ good_number(packets, stat.tx.pkt),
+ good_number(bytes, stat.tx.bytes),
+ good_number(ipbytes, stat.tx.bytes + stat.tx.pkt * 32),
+ "",
+ stat.tx.loss,
+ stat.tx.loss * 100.0 / (stat.tx.pkt + stat.tx.loss),
+ stat.tx.dup,
+ stat.tx.dup * 100.0 / (stat.tx.pkt + stat.tx.loss),
+ stat.tx.reorder,
+ stat.tx.reorder * 100.0 / (stat.tx.pkt + stat.tx.loss),
+ "",
+ stat.tx.loss_period.min / 1000.0,
+ stat.tx.loss_period.mean / 1000.0,
+ stat.tx.loss_period.max / 1000.0,
+ stat.tx.loss_period.last / 1000.0,
+ pj_math_stat_get_stddev(&stat.tx.loss_period) / 1000.0,
+ "",
+ stat.tx.jitter.min / 1000.0,
+ stat.tx.jitter.mean / 1000.0,
+ stat.tx.jitter.max / 1000.0,
+ stat.tx.jitter.last / 1000.0,
+ pj_math_stat_get_stddev(&stat.tx.jitter) / 1000.0,
+ ""
+ );
+
+
+ printf(" RTT delay : %7.3f %7.3f %7.3f %7.3f %7.3f%s\n",
+ stat.rtt.min / 1000.0,
+ stat.rtt.mean / 1000.0,
+ stat.rtt.max / 1000.0,
+ stat.rtt.last / 1000.0,
+ pj_math_stat_get_stddev(&stat.rtt) / 1000.0,
+ ""
+ );
+
+#if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0)
+ /* RTCP XR Reports */
+ do {
+ char loss[16], dup[16];
+ char jitter[80];
+ char toh[80];
+ char plc[16], jba[16], jbr[16];
+ char signal_lvl[16], noise_lvl[16], rerl[16];
+ char r_factor[16], ext_r_factor[16], mos_lq[16], mos_cq[16];
+ pjmedia_rtcp_xr_stat xr_stat;
+
+ if (pjmedia_stream_get_stat_xr(stream, &xr_stat) != PJ_SUCCESS)
+ break;
+
+ puts("\nExtended reports:");
+
+ /* Statistics Summary */
+ puts(" Statistics Summary");
+
+ if (xr_stat.rx.stat_sum.l)
+ sprintf(loss, "%d", xr_stat.rx.stat_sum.lost);
+ else
+ sprintf(loss, "(na)");
+
+ if (xr_stat.rx.stat_sum.d)
+ sprintf(dup, "%d", xr_stat.rx.stat_sum.dup);
+ else
+ sprintf(dup, "(na)");
+
+ if (xr_stat.rx.stat_sum.j) {
+ unsigned jmin, jmax, jmean, jdev;
+
+ SAMPLES_TO_USEC(jmin, xr_stat.rx.stat_sum.jitter.min,
+ port->info.fmt.det.aud.clock_rate);
+ SAMPLES_TO_USEC(jmax, xr_stat.rx.stat_sum.jitter.max,
+ port->info.fmt.det.aud.clock_rate);
+ SAMPLES_TO_USEC(jmean, xr_stat.rx.stat_sum.jitter.mean,
+ port->info.fmt.det.aud.clock_rate);
+ SAMPLES_TO_USEC(jdev,
+ pj_math_stat_get_stddev(&xr_stat.rx.stat_sum.jitter),
+ port->info.fmt.det.aud.clock_rate);
+ sprintf(jitter, "%7.3f %7.3f %7.3f %7.3f",
+ jmin/1000.0, jmean/1000.0, jmax/1000.0, jdev/1000.0);
+ } else
+ sprintf(jitter, "(report not available)");
+
+ if (xr_stat.rx.stat_sum.t) {
+ sprintf(toh, "%11d %11d %11d %11d",
+ xr_stat.rx.stat_sum.toh.min,
+ xr_stat.rx.stat_sum.toh.mean,
+ xr_stat.rx.stat_sum.toh.max,
+ pj_math_stat_get_stddev(&xr_stat.rx.stat_sum.toh));
+ } else
+ sprintf(toh, "(report not available)");
+
+ if (xr_stat.rx.stat_sum.update.sec == 0)
+ strcpy(last_update, "never");
+ else {
+ pj_gettimeofday(&now);
+ PJ_TIME_VAL_SUB(now, xr_stat.rx.stat_sum.update);
+ sprintf(last_update, "%02ldh:%02ldm:%02ld.%03lds ago",
+ now.sec / 3600,
+ (now.sec % 3600) / 60,
+ now.sec % 60,
+ now.msec);
+ }
+
+ printf(" RX last update: %s\n"
+ " begin seq=%d, end seq=%d%s\n"
+ " pkt loss=%s, dup=%s%s\n"
+ " (msec) min avg max dev\n"
+ " jitter : %s\n"
+ " toh : %s\n",
+ last_update,
+ xr_stat.rx.stat_sum.begin_seq, xr_stat.rx.stat_sum.end_seq,
+ "",
+ loss, dup,
+ "",
+ jitter,
+ toh
+ );
+
+ if (xr_stat.tx.stat_sum.l)
+ sprintf(loss, "%d", xr_stat.tx.stat_sum.lost);
+ else
+ sprintf(loss, "(na)");
+
+ if (xr_stat.tx.stat_sum.d)
+ sprintf(dup, "%d", xr_stat.tx.stat_sum.dup);
+ else
+ sprintf(dup, "(na)");
+
+ if (xr_stat.tx.stat_sum.j) {
+ unsigned jmin, jmax, jmean, jdev;
+
+ SAMPLES_TO_USEC(jmin, xr_stat.tx.stat_sum.jitter.min,
+ port->info.fmt.det.aud.clock_rate);
+ SAMPLES_TO_USEC(jmax, xr_stat.tx.stat_sum.jitter.max,
+ port->info.fmt.det.aud.clock_rate);
+ SAMPLES_TO_USEC(jmean, xr_stat.tx.stat_sum.jitter.mean,
+ port->info.fmt.det.aud.clock_rate);
+ SAMPLES_TO_USEC(jdev,
+ pj_math_stat_get_stddev(&xr_stat.tx.stat_sum.jitter),
+ port->info.fmt.det.aud.clock_rate);
+ sprintf(jitter, "%7.3f %7.3f %7.3f %7.3f",
+ jmin/1000.0, jmean/1000.0, jmax/1000.0, jdev/1000.0);
+ } else
+ sprintf(jitter, "(report not available)");
+
+ if (xr_stat.tx.stat_sum.t) {
+ sprintf(toh, "%11d %11d %11d %11d",
+ xr_stat.tx.stat_sum.toh.min,
+ xr_stat.tx.stat_sum.toh.mean,
+ xr_stat.tx.stat_sum.toh.max,
+ pj_math_stat_get_stddev(&xr_stat.rx.stat_sum.toh));
+ } else
+ sprintf(toh, "(report not available)");
+
+ if (xr_stat.tx.stat_sum.update.sec == 0)
+ strcpy(last_update, "never");
+ else {
+ pj_gettimeofday(&now);
+ PJ_TIME_VAL_SUB(now, xr_stat.tx.stat_sum.update);
+ sprintf(last_update, "%02ldh:%02ldm:%02ld.%03lds ago",
+ now.sec / 3600,
+ (now.sec % 3600) / 60,
+ now.sec % 60,
+ now.msec);
+ }
+
+ printf(" TX last update: %s\n"
+ " begin seq=%d, end seq=%d%s\n"
+ " pkt loss=%s, dup=%s%s\n"
+ " (msec) min avg max dev\n"
+ " jitter : %s\n"
+ " toh : %s\n",
+ last_update,
+ xr_stat.tx.stat_sum.begin_seq, xr_stat.tx.stat_sum.end_seq,
+ "",
+ loss, dup,
+ "",
+ jitter,
+ toh
+ );
+
+ /* VoIP Metrics */
+ puts(" VoIP Metrics");
+
+ PRINT_VOIP_MTC_VAL(signal_lvl, xr_stat.rx.voip_mtc.signal_lvl);
+ PRINT_VOIP_MTC_VAL(noise_lvl, xr_stat.rx.voip_mtc.noise_lvl);
+ PRINT_VOIP_MTC_VAL(rerl, xr_stat.rx.voip_mtc.rerl);
+ PRINT_VOIP_MTC_VAL(r_factor, xr_stat.rx.voip_mtc.r_factor);
+ PRINT_VOIP_MTC_VAL(ext_r_factor, xr_stat.rx.voip_mtc.ext_r_factor);
+ PRINT_VOIP_MTC_VAL(mos_lq, xr_stat.rx.voip_mtc.mos_lq);
+ PRINT_VOIP_MTC_VAL(mos_cq, xr_stat.rx.voip_mtc.mos_cq);
+
+ switch ((xr_stat.rx.voip_mtc.rx_config>>6) & 3) {
+ case PJMEDIA_RTCP_XR_PLC_DIS:
+ sprintf(plc, "DISABLED");
+ break;
+ case PJMEDIA_RTCP_XR_PLC_ENH:
+ sprintf(plc, "ENHANCED");
+ break;
+ case PJMEDIA_RTCP_XR_PLC_STD:
+ sprintf(plc, "STANDARD");
+ break;
+ case PJMEDIA_RTCP_XR_PLC_UNK:
+ default:
+ sprintf(plc, "UNKNOWN");
+ break;
+ }
+
+ switch ((xr_stat.rx.voip_mtc.rx_config>>4) & 3) {
+ case PJMEDIA_RTCP_XR_JB_FIXED:
+ sprintf(jba, "FIXED");
+ break;
+ case PJMEDIA_RTCP_XR_JB_ADAPTIVE:
+ sprintf(jba, "ADAPTIVE");
+ break;
+ default:
+ sprintf(jba, "UNKNOWN");
+ break;
+ }
+
+ sprintf(jbr, "%d", xr_stat.rx.voip_mtc.rx_config & 0x0F);
+
+ if (xr_stat.rx.voip_mtc.update.sec == 0)
+ strcpy(last_update, "never");
+ else {
+ pj_gettimeofday(&now);
+ PJ_TIME_VAL_SUB(now, xr_stat.rx.voip_mtc.update);
+ sprintf(last_update, "%02ldh:%02ldm:%02ld.%03lds ago",
+ now.sec / 3600,
+ (now.sec % 3600) / 60,
+ now.sec % 60,
+ now.msec);
+ }
+
+ printf(" RX last update: %s\n"
+ " packets : loss rate=%d (%.2f%%), discard rate=%d (%.2f%%)\n"
+ " burst : density=%d (%.2f%%), duration=%d%s\n"
+ " gap : density=%d (%.2f%%), duration=%d%s\n"
+ " delay : round trip=%d%s, end system=%d%s\n"
+ " level : signal=%s%s, noise=%s%s, RERL=%s%s\n"
+ " quality : R factor=%s, ext R factor=%s\n"
+ " MOS LQ=%s, MOS CQ=%s\n"
+ " config : PLC=%s, JB=%s, JB rate=%s, Gmin=%d\n"
+ " JB delay : cur=%d%s, max=%d%s, abs max=%d%s\n",
+ last_update,
+ /* pakcets */
+ xr_stat.rx.voip_mtc.loss_rate, xr_stat.rx.voip_mtc.loss_rate*100.0/256,
+ xr_stat.rx.voip_mtc.discard_rate, xr_stat.rx.voip_mtc.discard_rate*100.0/256,
+ /* burst */
+ xr_stat.rx.voip_mtc.burst_den, xr_stat.rx.voip_mtc.burst_den*100.0/256,
+ xr_stat.rx.voip_mtc.burst_dur, "ms",
+ /* gap */
+ xr_stat.rx.voip_mtc.gap_den, xr_stat.rx.voip_mtc.gap_den*100.0/256,
+ xr_stat.rx.voip_mtc.gap_dur, "ms",
+ /* delay */
+ xr_stat.rx.voip_mtc.rnd_trip_delay, "ms",
+ xr_stat.rx.voip_mtc.end_sys_delay, "ms",
+ /* level */
+ signal_lvl, "dB",
+ noise_lvl, "dB",
+ rerl, "",
+ /* quality */
+ r_factor, ext_r_factor, mos_lq, mos_cq,
+ /* config */
+ plc, jba, jbr, xr_stat.rx.voip_mtc.gmin,
+ /* JB delay */
+ xr_stat.rx.voip_mtc.jb_nom, "ms",
+ xr_stat.rx.voip_mtc.jb_max, "ms",
+ xr_stat.rx.voip_mtc.jb_abs_max, "ms"
+ );
+
+ PRINT_VOIP_MTC_VAL(signal_lvl, xr_stat.tx.voip_mtc.signal_lvl);
+ PRINT_VOIP_MTC_VAL(noise_lvl, xr_stat.tx.voip_mtc.noise_lvl);
+ PRINT_VOIP_MTC_VAL(rerl, xr_stat.tx.voip_mtc.rerl);
+ PRINT_VOIP_MTC_VAL(r_factor, xr_stat.tx.voip_mtc.r_factor);
+ PRINT_VOIP_MTC_VAL(ext_r_factor, xr_stat.tx.voip_mtc.ext_r_factor);
+ PRINT_VOIP_MTC_VAL(mos_lq, xr_stat.tx.voip_mtc.mos_lq);
+ PRINT_VOIP_MTC_VAL(mos_cq, xr_stat.tx.voip_mtc.mos_cq);
+
+ switch ((xr_stat.tx.voip_mtc.rx_config>>6) & 3) {
+ case PJMEDIA_RTCP_XR_PLC_DIS:
+ sprintf(plc, "DISABLED");
+ break;
+ case PJMEDIA_RTCP_XR_PLC_ENH:
+ sprintf(plc, "ENHANCED");
+ break;
+ case PJMEDIA_RTCP_XR_PLC_STD:
+ sprintf(plc, "STANDARD");
+ break;
+ case PJMEDIA_RTCP_XR_PLC_UNK:
+ default:
+ sprintf(plc, "unknown");
+ break;
+ }
+
+ switch ((xr_stat.tx.voip_mtc.rx_config>>4) & 3) {
+ case PJMEDIA_RTCP_XR_JB_FIXED:
+ sprintf(jba, "FIXED");
+ break;
+ case PJMEDIA_RTCP_XR_JB_ADAPTIVE:
+ sprintf(jba, "ADAPTIVE");
+ break;
+ default:
+ sprintf(jba, "unknown");
+ break;
+ }
+
+ sprintf(jbr, "%d", xr_stat.tx.voip_mtc.rx_config & 0x0F);
+
+ if (xr_stat.tx.voip_mtc.update.sec == 0)
+ strcpy(last_update, "never");
+ else {
+ pj_gettimeofday(&now);
+ PJ_TIME_VAL_SUB(now, xr_stat.tx.voip_mtc.update);
+ sprintf(last_update, "%02ldh:%02ldm:%02ld.%03lds ago",
+ now.sec / 3600,
+ (now.sec % 3600) / 60,
+ now.sec % 60,
+ now.msec);
+ }
+
+ printf(" TX last update: %s\n"
+ " packets : loss rate=%d (%.2f%%), discard rate=%d (%.2f%%)\n"
+ " burst : density=%d (%.2f%%), duration=%d%s\n"
+ " gap : density=%d (%.2f%%), duration=%d%s\n"
+ " delay : round trip=%d%s, end system=%d%s\n"
+ " level : signal=%s%s, noise=%s%s, RERL=%s%s\n"
+ " quality : R factor=%s, ext R factor=%s\n"
+ " MOS LQ=%s, MOS CQ=%s\n"
+ " config : PLC=%s, JB=%s, JB rate=%s, Gmin=%d\n"
+ " JB delay : cur=%d%s, max=%d%s, abs max=%d%s\n",
+ last_update,
+ /* pakcets */
+ xr_stat.tx.voip_mtc.loss_rate, xr_stat.tx.voip_mtc.loss_rate*100.0/256,
+ xr_stat.tx.voip_mtc.discard_rate, xr_stat.tx.voip_mtc.discard_rate*100.0/256,
+ /* burst */
+ xr_stat.tx.voip_mtc.burst_den, xr_stat.tx.voip_mtc.burst_den*100.0/256,
+ xr_stat.tx.voip_mtc.burst_dur, "ms",
+ /* gap */
+ xr_stat.tx.voip_mtc.gap_den, xr_stat.tx.voip_mtc.gap_den*100.0/256,
+ xr_stat.tx.voip_mtc.gap_dur, "ms",
+ /* delay */
+ xr_stat.tx.voip_mtc.rnd_trip_delay, "ms",
+ xr_stat.tx.voip_mtc.end_sys_delay, "ms",
+ /* level */
+ signal_lvl, "dB",
+ noise_lvl, "dB",
+ rerl, "",
+ /* quality */
+ r_factor, ext_r_factor, mos_lq, mos_cq,
+ /* config */
+ plc, jba, jbr, xr_stat.tx.voip_mtc.gmin,
+ /* JB delay */
+ xr_stat.tx.voip_mtc.jb_nom, "ms",
+ xr_stat.tx.voip_mtc.jb_max, "ms",
+ xr_stat.tx.voip_mtc.jb_abs_max, "ms"
+ );
+
+
+ /* RTT delay (by receiver side) */
+ printf(" (msec) min avg max last dev\n");
+ printf(" RTT delay : %7.3f %7.3f %7.3f %7.3f %7.3f%s\n",
+ xr_stat.rtt.min / 1000.0,
+ xr_stat.rtt.mean / 1000.0,
+ xr_stat.rtt.max / 1000.0,
+ xr_stat.rtt.last / 1000.0,
+ pj_math_stat_get_stddev(&xr_stat.rtt) / 1000.0,
+ ""
+ );
+ } while (0);
+#endif /* PJMEDIA_HAS_RTCP_XR */
+
+}
+
diff --git a/pjsip-apps/src/samples/strerror.c b/pjsip-apps/src/samples/strerror.c
new file mode 100644
index 0000000..b03e8c1
--- /dev/null
+++ b/pjsip-apps/src/samples/strerror.c
@@ -0,0 +1,71 @@
+/* $Id: strerror.c 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/**
+ * \page page_strerror_c Samples: Print out error message
+ *
+ * This file is pjsip-apps/src/samples/strerror.c
+ *
+ * \includelineno strerror.c
+ */
+
+
+#include <pjlib.h>
+#include <pjlib-util.h>
+#include <pjsip.h>
+#include <pjmedia.h>
+#include <pjnath.h>
+#include <pjsip_simple.h>
+
+/*
+ * main()
+ */
+int main(int argc, char *argv[])
+{
+ pj_caching_pool cp;
+ pjmedia_endpt *med_ept;
+ pjsip_endpoint *sip_ept;
+ char errmsg[PJ_ERR_MSG_SIZE];
+ pj_status_t code;
+
+ if (argc != 2) {
+ puts("Usage: strerror ERRNUM");
+ return 1;
+ }
+
+ pj_log_set_level(3);
+
+ pj_init();
+ pj_caching_pool_init(&cp, NULL, 0);
+ pjlib_util_init();
+ pjnath_init();
+ pjmedia_endpt_create(&cp.factory, NULL, 0, &med_ept);
+ pjsip_endpt_create(&cp.factory, "localhost", &sip_ept);
+ pjsip_evsub_init_module(sip_ept);
+
+ code = atoi(argv[1]);
+ pj_strerror(code, errmsg, sizeof(errmsg));
+
+ printf("Status %d: %s\n", code, errmsg);
+
+ pj_shutdown();
+ return 0;
+}
+
diff --git a/pjsip-apps/src/samples/tonegen.c b/pjsip-apps/src/samples/tonegen.c
new file mode 100644
index 0000000..5190186
--- /dev/null
+++ b/pjsip-apps/src/samples/tonegen.c
@@ -0,0 +1,159 @@
+/* $Id: tonegen.c 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/**
+ * \page page_pjmedia_samples_tonegen_c Samples: Sine Wave/Dual-Tone Generation
+ *
+ * This is a simple program to generate a tone and write the samples to
+ * a raw PCM file. The main purpose of this file is to analyze the
+ * quality of the tones/sine wave generated by PJMEDIA tone/sine wave
+ * generator.
+ *
+ * This file is pjsip-apps/src/samples/tonegen.c
+ *
+ * \includelineno tonegen.c
+ */
+
+
+#include <pjmedia.h>
+#include <pjlib.h>
+
+#define SAMPLES_PER_FRAME 64
+#define ON_DURATION 100
+#define OFF_DURATION 100
+
+
+/*
+ * main()
+ */
+int main()
+{
+ pj_caching_pool cp;
+ pjmedia_endpt *med_endpt;
+ pj_pool_t *pool;
+ pjmedia_port *port;
+ unsigned i;
+ pj_status_t status;
+
+
+ /* Must init PJLIB first: */
+ status = pj_init();
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ /* Must create a pool factory before we can allocate any memory. */
+ pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);
+
+ /*
+ * Initialize media endpoint.
+ * This will implicitly initialize PJMEDIA too.
+ */
+ status = pjmedia_endpt_create(&cp.factory, NULL, 1, &med_endpt);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ /* Create memory pool for our file player */
+ pool = pj_pool_create( &cp.factory, /* pool factory */
+ "app", /* pool name. */
+ 4000, /* init size */
+ 4000, /* increment size */
+ NULL /* callback on error */
+ );
+
+ status = pjmedia_tonegen_create(pool, 8000, 1, SAMPLES_PER_FRAME, 16, 0, &port);
+ if (status != PJ_SUCCESS)
+ return 1;
+
+ {
+ pjmedia_tone_desc tones[3];
+
+ tones[0].freq1 = 200;
+ tones[0].freq2 = 0;
+ tones[0].on_msec = ON_DURATION;
+ tones[0].off_msec = OFF_DURATION;
+
+ tones[1].freq1 = 400;
+ tones[1].freq2 = 0;
+ tones[1].on_msec = ON_DURATION;
+ tones[1].off_msec = OFF_DURATION;
+
+ tones[2].freq1 = 800;
+ tones[2].freq2 = 0;
+ tones[2].on_msec = ON_DURATION;
+ tones[2].off_msec = OFF_DURATION;
+
+ status = pjmedia_tonegen_play(port, 3, tones, 0);
+ PJ_ASSERT_RETURN(status==PJ_SUCCESS, 1);
+ }
+
+ {
+ pjmedia_tone_digit digits[2];
+
+ digits[0].digit = '0';
+ digits[0].on_msec = ON_DURATION;
+ digits[0].off_msec = OFF_DURATION;
+
+ digits[1].digit = '0';
+ digits[1].on_msec = ON_DURATION;
+ digits[1].off_msec = OFF_DURATION;
+
+ status = pjmedia_tonegen_play_digits(port, 2, digits, 0);
+ PJ_ASSERT_RETURN(status==PJ_SUCCESS, 1);
+ }
+
+ {
+ pjmedia_frame frm;
+ FILE *f;
+ void *buf;
+
+ buf = pj_pool_alloc(pool, 2*8000);
+ frm.buf = buf;
+
+ f = fopen("tonegen.pcm", "wb");
+
+ for (i=0; i<8000/SAMPLES_PER_FRAME; ++i) {
+ int count;
+ pjmedia_port_get_frame(port, &frm);
+ count = fwrite(buf, SAMPLES_PER_FRAME, 2, f);
+ if (count != 2)
+ break;
+ }
+
+ pj_assert(pjmedia_tonegen_is_busy(port) == 0);
+ fclose(f);
+ }
+
+ /* Delete port */
+ pjmedia_port_destroy(port);
+
+ /* Release application pool */
+ pj_pool_release( pool );
+
+ /* Destroy media endpoint. */
+ pjmedia_endpt_destroy( med_endpt );
+
+ /* Destroy pool factory */
+ pj_caching_pool_destroy( &cp );
+
+ /* Shutdown PJLIB */
+ pj_shutdown();
+
+
+ /* Done. */
+ return 0;
+}
diff --git a/pjsip-apps/src/samples/util.h b/pjsip-apps/src/samples/util.h
new file mode 100644
index 0000000..40a8f6e
--- /dev/null
+++ b/pjsip-apps/src/samples/util.h
@@ -0,0 +1,173 @@
+/* $Id: util.h 3550 2011-05-05 05:33:27Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <stdlib.h> /* strtol() */
+
+/* Util to display the error message for the specified error code */
+static int app_perror( const char *sender, const char *title,
+ pj_status_t status)
+{
+ char errmsg[PJ_ERR_MSG_SIZE];
+
+ pj_strerror(status, errmsg, sizeof(errmsg));
+
+ PJ_LOG(3,(sender, "%s: %s [code=%d]", title, errmsg, status));
+ return 1;
+}
+
+
+
+/* Constants */
+#define CLOCK_RATE 44100
+#define NSAMPLES (CLOCK_RATE * 20 / 1000)
+#define NCHANNELS 1
+#define NBITS 16
+
+/*
+ * Common sound options.
+ */
+#define SND_USAGE \
+" -d, --dev=NUM Sound device use device id NUM (default=-1) \n"\
+" -r, --rate=HZ Set clock rate in samples per sec (default=44100)\n"\
+" -c, --channel=NUM Set # of channels (default=1 for mono). \n"\
+" -f, --frame=NUM Set # of samples per frame (default equival 20ms)\n"\
+" -b, --bit=NUM Set # of bits per sample (default=16) \n"
+
+
+/*
+ * This utility function parses the command line and look for
+ * common sound options.
+ */
+pj_status_t get_snd_options(const char *app_name,
+ int argc,
+ char *argv[],
+ int *dev_id,
+ int *clock_rate,
+ int *channel_count,
+ int *samples_per_frame,
+ int *bits_per_sample)
+{
+ struct pj_getopt_option long_options[] = {
+ { "dev", 1, 0, 'd' },
+ { "rate", 1, 0, 'r' },
+ { "channel", 1, 0, 'c' },
+ { "frame", 1, 0, 'f' },
+ { "bit", 1, 0, 'b' },
+ { NULL, 0, 0, 0 },
+ };
+ int c;
+ int option_index;
+ long val;
+ char *err;
+
+ *samples_per_frame = 0;
+
+ pj_optind = 0;
+ while((c=pj_getopt_long(argc,argv, "d:r:c:f:b:",
+ long_options, &option_index))!=-1)
+ {
+
+ switch (c) {
+ case 'd':
+ /* device */
+ val = strtol(pj_optarg, &err, 10);
+ if (*err) {
+ PJ_LOG(3,(app_name, "Error: invalid value for device id"));
+ return PJ_EINVAL;
+ }
+ *dev_id = val;
+ break;
+
+ case 'r':
+ /* rate */
+ val = strtol(pj_optarg, &err, 10);
+ if (*err) {
+ PJ_LOG(3,(app_name, "Error: invalid value for clock rate"));
+ return PJ_EINVAL;
+ }
+ *clock_rate = val;
+ break;
+
+ case 'c':
+ /* channel count */
+ val = strtol(pj_optarg, &err, 10);
+ if (*err) {
+ PJ_LOG(3,(app_name, "Error: invalid channel count"));
+ return PJ_EINVAL;
+ }
+ *channel_count = val;
+ break;
+
+ case 'f':
+ /* frame count/samples per frame */
+ val = strtol(pj_optarg, &err, 10);
+ if (*err) {
+ PJ_LOG(3,(app_name, "Error: invalid samples per frame"));
+ return PJ_EINVAL;
+ }
+ *samples_per_frame = val;
+ break;
+
+ case 'b':
+ /* bit per sample */
+ val = strtol(pj_optarg, &err, 10);
+ if (*err) {
+ PJ_LOG(3,(app_name, "Error: invalid samples bits per sample"));
+ return PJ_EINVAL;
+ }
+ *bits_per_sample = val;
+ break;
+
+ default:
+ /* Unknown options */
+ PJ_LOG(3,(app_name, "Error: unknown options '%c'", pj_optopt));
+ return PJ_EINVAL;
+ }
+
+ }
+
+ if (*samples_per_frame == 0) {
+ *samples_per_frame = *clock_rate * *channel_count * 20 / 1000;
+ }
+
+ return 0;
+}
+
+
+/* Dump memory pool usage. */
+void dump_pool_usage( const char *app_name, pj_caching_pool *cp )
+{
+#if !defined(PJ_HAS_POOL_ALT_API) || PJ_HAS_POOL_ALT_API==0
+ pj_pool_t *p;
+ unsigned total_alloc = 0;
+ unsigned total_used = 0;
+
+ /* Accumulate memory usage in active list. */
+ p = cp->used_list.next;
+ while (p != (pj_pool_t*) &cp->used_list) {
+ total_alloc += pj_pool_get_capacity(p);
+ total_used += pj_pool_get_used_size(p);
+ p = p->next;
+ }
+
+ PJ_LOG(3, (app_name, "Total pool memory allocated=%d KB, used=%d KB",
+ total_alloc / 1000,
+ total_used / 1000));
+#endif
+}
diff --git a/pjsip-apps/src/samples/vid_streamutil.c b/pjsip-apps/src/samples/vid_streamutil.c
new file mode 100644
index 0000000..b56c398
--- /dev/null
+++ b/pjsip-apps/src/samples/vid_streamutil.c
@@ -0,0 +1,967 @@
+/* $Id: vid_streamutil.c 4084 2012-04-25 07:13:05Z ming $ */
+/*
+ * Copyright (C) 2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+/**
+ * \page page_pjmedia_samples_vid_streamutil_c Samples: Video Streaming
+ *
+ * This example mainly demonstrates how to stream video to remote
+ * peer using RTP.
+ *
+ * This file is pjsip-apps/src/samples/vid_streamutil.c
+ *
+ * \includelineno vid_streamutil.c
+ */
+
+#include <pjlib.h>
+#include <pjlib-util.h>
+#include <pjmedia.h>
+#include <pjmedia-codec.h>
+#include <pjmedia/transport_srtp.h>
+
+
+#if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
+
+
+#include <stdlib.h> /* atoi() */
+#include <stdio.h>
+
+#include "util.h"
+
+
+static const char *desc =
+ " vid_streamutil \n"
+ "\n"
+ " PURPOSE: \n"
+ " Demonstrate how to use pjmedia video stream component to \n"
+ " transmit/receive RTP packets to/from video device/file. \n"
+ "\n"
+ "\n"
+ " USAGE: \n"
+ " vid_streamutil [options] \n"
+ "\n"
+ "\n"
+ " Options: \n"
+ " --codec=CODEC Set the codec name. \n"
+ " --local-port=PORT Set local RTP port (default=4000) \n"
+ " --remote=IP:PORT Set the remote peer. If this option is set, \n"
+ " the program will transmit RTP audio to the \n"
+ " specified address. (default: recv only) \n"
+ " --play-file=AVI Send video from the AVI file instead of from \n"
+ " the video device. \n"
+ " --send-recv Set stream direction to bidirectional. \n"
+ " --send-only Set stream direction to send only \n"
+ " --recv-only Set stream direction to recv only (default) \n"
+
+ " --send-width Video width to be sent \n"
+ " --send-height Video height to be sent \n"
+ " --send-width and --send-height not applicable \n"
+ " for file streaming (see --play-file) \n"
+
+ " --send-pt Payload type for sending \n"
+ " --recv-pt Payload type for receiving \n"
+
+#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
+ " --use-srtp[=NAME] Enable SRTP with crypto suite NAME \n"
+ " e.g: AES_CM_128_HMAC_SHA1_80 (default), \n"
+ " AES_CM_128_HMAC_SHA1_32 \n"
+ " Use this option along with the TX & RX keys, \n"
+ " formated of 60 hex digits (e.g: E148DA..) \n"
+ " --srtp-tx-key SRTP key for transmiting \n"
+ " --srtp-rx-key SRTP key for receiving \n"
+#endif
+
+ "\n"
+;
+
+#define THIS_FILE "vid_streamutil.c"
+
+
+/* If set, local renderer will be created to play original file */
+#define HAS_LOCAL_RENDERER_FOR_PLAY_FILE 1
+
+
+/* Default width and height for the renderer, better be set to maximum
+ * acceptable size.
+ */
+#define DEF_RENDERER_WIDTH 640
+#define DEF_RENDERER_HEIGHT 480
+
+
+/* Prototype */
+static void print_stream_stat(pjmedia_vid_stream *stream,
+ const pjmedia_vid_codec_param *codec_param);
+
+/* Prototype for LIBSRTP utility in file datatypes.c */
+int hex_string_to_octet_string(char *raw, char *hex, int len);
+
+/*
+ * Register all codecs.
+ */
+static pj_status_t init_codecs(pj_pool_factory *pf)
+{
+ pj_status_t status;
+
+ /* To suppress warning about unused var when all codecs are disabled */
+ PJ_UNUSED_ARG(status);
+
+#if defined(PJMEDIA_HAS_FFMPEG_VID_CODEC) && PJMEDIA_HAS_FFMPEG_VID_CODEC != 0
+ status = pjmedia_codec_ffmpeg_vid_init(NULL, pf);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+#endif
+
+ return PJ_SUCCESS;
+}
+
+/*
+ * Register all codecs.
+ */
+static void deinit_codecs()
+{
+#if defined(PJMEDIA_HAS_FFMPEG_VID_CODEC) && PJMEDIA_HAS_FFMPEG_VID_CODEC != 0
+ pjmedia_codec_ffmpeg_vid_deinit();
+#endif
+}
+
+static pj_status_t create_file_player( pj_pool_t *pool,
+ const char *file_name,
+ pjmedia_port **p_play_port)
+{
+ pjmedia_avi_streams *avi_streams;
+ pjmedia_avi_stream *vid_stream;
+ pjmedia_port *play_port;
+ pj_status_t status;
+
+ status = pjmedia_avi_player_create_streams(pool, file_name, 0, &avi_streams);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ vid_stream = pjmedia_avi_streams_get_stream_by_media(avi_streams,
+ 0,
+ PJMEDIA_TYPE_VIDEO);
+ if (!vid_stream)
+ return PJ_ENOTFOUND;
+
+ play_port = pjmedia_avi_stream_get_port(vid_stream);
+ pj_assert(play_port);
+
+ *p_play_port = play_port;
+
+ return PJ_SUCCESS;
+}
+
+/*
+ * Create stream based on the codec, dir, remote address, etc.
+ */
+static pj_status_t create_stream( pj_pool_t *pool,
+ pjmedia_endpt *med_endpt,
+ const pjmedia_vid_codec_info *codec_info,
+ pjmedia_vid_codec_param *codec_param,
+ pjmedia_dir dir,
+ pj_int8_t rx_pt,
+ pj_int8_t tx_pt,
+ pj_uint16_t local_port,
+ const pj_sockaddr_in *rem_addr,
+#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
+ pj_bool_t use_srtp,
+ const pj_str_t *crypto_suite,
+ const pj_str_t *srtp_tx_key,
+ const pj_str_t *srtp_rx_key,
+#endif
+ pjmedia_vid_stream **p_stream )
+{
+ pjmedia_vid_stream_info info;
+ pjmedia_transport *transport = NULL;
+ pj_status_t status;
+#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
+ pjmedia_transport *srtp_tp = NULL;
+#endif
+
+ /* Reset stream info. */
+ pj_bzero(&info, sizeof(info));
+
+ /* Initialize stream info formats */
+ info.type = PJMEDIA_TYPE_VIDEO;
+ info.dir = dir;
+ info.codec_info = *codec_info;
+ info.tx_pt = (tx_pt == -1)? codec_info->pt : tx_pt;
+ info.rx_pt = (rx_pt == -1)? codec_info->pt : rx_pt;
+ info.ssrc = pj_rand();
+ if (codec_param)
+ info.codec_param = codec_param;
+
+ /* Copy remote address */
+ pj_memcpy(&info.rem_addr, rem_addr, sizeof(pj_sockaddr_in));
+
+ /* If remote address is not set, set to an arbitrary address
+ * (otherwise stream will assert).
+ */
+ if (info.rem_addr.addr.sa_family == 0) {
+ const pj_str_t addr = pj_str("127.0.0.1");
+ pj_sockaddr_in_init(&info.rem_addr.ipv4, &addr, 0);
+ }
+
+ /* Create media transport */
+ status = pjmedia_transport_udp_create(med_endpt, NULL, local_port,
+ 0, &transport);
+ if (status != PJ_SUCCESS)
+ return status;
+
+#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
+ /* Check if SRTP enabled */
+ if (use_srtp) {
+ pjmedia_srtp_crypto tx_plc, rx_plc;
+
+ status = pjmedia_transport_srtp_create(med_endpt, transport,
+ NULL, &srtp_tp);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ pj_bzero(&tx_plc, sizeof(pjmedia_srtp_crypto));
+ pj_bzero(&rx_plc, sizeof(pjmedia_srtp_crypto));
+
+ tx_plc.key = *srtp_tx_key;
+ tx_plc.name = *crypto_suite;
+ rx_plc.key = *srtp_rx_key;
+ rx_plc.name = *crypto_suite;
+
+ status = pjmedia_transport_srtp_start(srtp_tp, &tx_plc, &rx_plc);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ transport = srtp_tp;
+ }
+#endif
+
+ /* Now that the stream info is initialized, we can create the
+ * stream.
+ */
+
+ status = pjmedia_vid_stream_create( med_endpt, pool, &info,
+ transport,
+ NULL, p_stream);
+
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Error creating stream", status);
+ pjmedia_transport_close(transport);
+ return status;
+ }
+
+
+ return PJ_SUCCESS;
+}
+
+
+typedef struct play_file_data
+{
+ const char *file_name;
+ pjmedia_port *play_port;
+ pjmedia_port *stream_port;
+ pjmedia_vid_codec *decoder;
+ pjmedia_port *renderer;
+ void *read_buf;
+ pj_size_t read_buf_size;
+ void *dec_buf;
+ pj_size_t dec_buf_size;
+} play_file_data;
+
+
+static void clock_cb(const pj_timestamp *ts, void *user_data)
+{
+ play_file_data *play_file = (play_file_data*)user_data;
+ pjmedia_frame read_frame, write_frame;
+ pj_status_t status;
+
+ PJ_UNUSED_ARG(ts);
+
+ /* Read frame from file */
+ read_frame.buf = play_file->read_buf;
+ read_frame.size = play_file->read_buf_size;
+ pjmedia_port_get_frame(play_file->play_port, &read_frame);
+
+ /* Decode frame, if needed */
+ if (play_file->decoder) {
+ pjmedia_vid_codec *decoder = play_file->decoder;
+
+ write_frame.buf = play_file->dec_buf;
+ write_frame.size = play_file->dec_buf_size;
+ status = pjmedia_vid_codec_decode(decoder, 1, &read_frame,
+ write_frame.size, &write_frame);
+ if (status != PJ_SUCCESS)
+ return;
+ } else {
+ write_frame = read_frame;
+ }
+
+ /* Display frame locally */
+ if (play_file->renderer)
+ pjmedia_port_put_frame(play_file->renderer, &write_frame);
+
+ /* Send frame */
+ pjmedia_port_put_frame(play_file->stream_port, &write_frame);
+}
+
+
+/*
+ * usage()
+ */
+static void usage()
+{
+ puts(desc);
+}
+
+/*
+ * main()
+ */
+int main(int argc, char *argv[])
+{
+ pj_caching_pool cp;
+ pjmedia_endpt *med_endpt;
+ pj_pool_t *pool;
+ pjmedia_vid_stream *stream = NULL;
+ pjmedia_port *enc_port, *dec_port;
+ pj_status_t status;
+
+ pjmedia_vid_port *capture=NULL, *renderer=NULL;
+ pjmedia_vid_port_param vpp;
+
+#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
+ /* SRTP variables */
+ pj_bool_t use_srtp = PJ_FALSE;
+ char tmp_tx_key[64];
+ char tmp_rx_key[64];
+ pj_str_t srtp_tx_key = {NULL, 0};
+ pj_str_t srtp_rx_key = {NULL, 0};
+ pj_str_t srtp_crypto_suite = {NULL, 0};
+ int tmp_key_len;
+#endif
+
+ /* Default values */
+ const pjmedia_vid_codec_info *codec_info;
+ pjmedia_vid_codec_param codec_param;
+ pjmedia_dir dir = PJMEDIA_DIR_DECODING;
+ pj_sockaddr_in remote_addr;
+ pj_uint16_t local_port = 4000;
+ char *codec_id = NULL;
+ pjmedia_rect_size tx_size = {0};
+ pj_int8_t rx_pt = -1, tx_pt = -1;
+
+ play_file_data play_file = { NULL };
+ pjmedia_port *play_port = NULL;
+ pjmedia_vid_codec *play_decoder = NULL;
+ pjmedia_clock *play_clock = NULL;
+
+ enum {
+ OPT_CODEC = 'c',
+ OPT_LOCAL_PORT = 'p',
+ OPT_REMOTE = 'r',
+ OPT_PLAY_FILE = 'f',
+ OPT_SEND_RECV = 'b',
+ OPT_SEND_ONLY = 's',
+ OPT_RECV_ONLY = 'i',
+ OPT_SEND_WIDTH = 'W',
+ OPT_SEND_HEIGHT = 'H',
+ OPT_RECV_PT = 't',
+ OPT_SEND_PT = 'T',
+#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
+ OPT_USE_SRTP = 'S',
+#endif
+ OPT_SRTP_TX_KEY = 'x',
+ OPT_SRTP_RX_KEY = 'y',
+ OPT_HELP = 'h',
+ };
+
+ struct pj_getopt_option long_options[] = {
+ { "codec", 1, 0, OPT_CODEC },
+ { "local-port", 1, 0, OPT_LOCAL_PORT },
+ { "remote", 1, 0, OPT_REMOTE },
+ { "play-file", 1, 0, OPT_PLAY_FILE },
+ { "send-recv", 0, 0, OPT_SEND_RECV },
+ { "send-only", 0, 0, OPT_SEND_ONLY },
+ { "recv-only", 0, 0, OPT_RECV_ONLY },
+ { "send-width", 1, 0, OPT_SEND_WIDTH },
+ { "send-height", 1, 0, OPT_SEND_HEIGHT },
+ { "recv-pt", 1, 0, OPT_RECV_PT },
+ { "send-pt", 1, 0, OPT_SEND_PT },
+#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
+ { "use-srtp", 2, 0, OPT_USE_SRTP },
+ { "srtp-tx-key", 1, 0, OPT_SRTP_TX_KEY },
+ { "srtp-rx-key", 1, 0, OPT_SRTP_RX_KEY },
+#endif
+ { "help", 0, 0, OPT_HELP },
+ { NULL, 0, 0, 0 },
+ };
+
+ int c;
+ int option_index;
+
+
+ pj_bzero(&remote_addr, sizeof(remote_addr));
+
+
+ /* init PJLIB : */
+ status = pj_init();
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+
+ /* Parse arguments */
+ pj_optind = 0;
+ while((c=pj_getopt_long(argc,argv, "h", long_options, &option_index))!=-1)
+ {
+ switch (c) {
+ case OPT_CODEC:
+ codec_id = pj_optarg;
+ break;
+
+ case OPT_LOCAL_PORT:
+ local_port = (pj_uint16_t) atoi(pj_optarg);
+ if (local_port < 1) {
+ printf("Error: invalid local port %s\n", pj_optarg);
+ return 1;
+ }
+ break;
+
+ case OPT_REMOTE:
+ {
+ pj_str_t ip = pj_str(strtok(pj_optarg, ":"));
+ pj_uint16_t port = (pj_uint16_t) atoi(strtok(NULL, ":"));
+
+ status = pj_sockaddr_in_init(&remote_addr, &ip, port);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Invalid remote address", status);
+ return 1;
+ }
+ }
+ break;
+
+ case OPT_PLAY_FILE:
+ play_file.file_name = pj_optarg;
+ break;
+
+ case OPT_SEND_RECV:
+ dir = PJMEDIA_DIR_ENCODING_DECODING;
+ break;
+
+ case OPT_SEND_ONLY:
+ dir = PJMEDIA_DIR_ENCODING;
+ break;
+
+ case OPT_RECV_ONLY:
+ dir = PJMEDIA_DIR_DECODING;
+ break;
+
+ case OPT_SEND_WIDTH:
+ tx_size.w = (unsigned)atoi(pj_optarg);
+ break;
+
+ case OPT_SEND_HEIGHT:
+ tx_size.h = (unsigned)atoi(pj_optarg);
+ break;
+
+ case OPT_RECV_PT:
+ rx_pt = (pj_int8_t)atoi(pj_optarg);
+ break;
+
+ case OPT_SEND_PT:
+ tx_pt = (pj_int8_t)atoi(pj_optarg);
+ break;
+
+#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
+ case OPT_USE_SRTP:
+ use_srtp = PJ_TRUE;
+ if (pj_optarg) {
+ pj_strset(&srtp_crypto_suite, pj_optarg, strlen(pj_optarg));
+ } else {
+ srtp_crypto_suite = pj_str("AES_CM_128_HMAC_SHA1_80");
+ }
+ break;
+
+ case OPT_SRTP_TX_KEY:
+ tmp_key_len = hex_string_to_octet_string(tmp_tx_key, pj_optarg,
+ strlen(pj_optarg));
+ pj_strset(&srtp_tx_key, tmp_tx_key, tmp_key_len/2);
+ break;
+
+ case OPT_SRTP_RX_KEY:
+ tmp_key_len = hex_string_to_octet_string(tmp_rx_key, pj_optarg,
+ strlen(pj_optarg));
+ pj_strset(&srtp_rx_key, tmp_rx_key, tmp_key_len/2);
+ break;
+#endif
+
+ case OPT_HELP:
+ usage();
+ return 1;
+
+ default:
+ printf("Invalid options %s\n", argv[pj_optind]);
+ return 1;
+ }
+
+ }
+
+
+ /* Verify arguments. */
+ if (dir & PJMEDIA_DIR_ENCODING) {
+ if (remote_addr.sin_addr.s_addr == 0) {
+ printf("Error: remote address must be set\n");
+ return 1;
+ }
+ }
+
+ if (play_file.file_name != NULL && dir != PJMEDIA_DIR_ENCODING) {
+ printf("Direction is set to --send-only because of --play-file\n");
+ dir = PJMEDIA_DIR_ENCODING;
+ }
+
+#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
+ /* SRTP validation */
+ if (use_srtp) {
+ if (!srtp_tx_key.slen || !srtp_rx_key.slen)
+ {
+ printf("Error: Key for each SRTP stream direction must be set\n");
+ return 1;
+ }
+ }
+#endif
+
+ /* Must create a pool factory before we can allocate any memory. */
+ pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);
+
+ /*
+ * Initialize media endpoint.
+ * This will implicitly initialize PJMEDIA too.
+ */
+ status = pjmedia_endpt_create(&cp.factory, NULL, 1, &med_endpt);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ /* Create memory pool for application purpose */
+ pool = pj_pool_create( &cp.factory, /* pool factory */
+ "app", /* pool name. */
+ 4000, /* init size */
+ 4000, /* increment size */
+ NULL /* callback on error */
+ );
+
+ /* Init video format manager */
+ pjmedia_video_format_mgr_create(pool, 64, 0, NULL);
+
+ /* Init video converter manager */
+ pjmedia_converter_mgr_create(pool, NULL);
+
+ /* Init event manager */
+ pjmedia_event_mgr_create(pool, 0, NULL);
+
+ /* Init video codec manager */
+ pjmedia_vid_codec_mgr_create(pool, NULL);
+
+ /* Init video subsystem */
+ pjmedia_vid_dev_subsys_init(&cp.factory);
+
+ /* Register all supported codecs */
+ status = init_codecs(&cp.factory);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+
+ /* Find which codec to use. */
+ if (codec_id) {
+ unsigned count = 1;
+ pj_str_t str_codec_id = pj_str(codec_id);
+
+ status = pjmedia_vid_codec_mgr_find_codecs_by_id(NULL,
+ &str_codec_id, &count,
+ &codec_info, NULL);
+ if (status != PJ_SUCCESS) {
+ printf("Error: unable to find codec %s\n", codec_id);
+ return 1;
+ }
+ } else {
+ static pjmedia_vid_codec_info info[1];
+ unsigned count = PJ_ARRAY_SIZE(info);
+
+ /* Default to first codec */
+ pjmedia_vid_codec_mgr_enum_codecs(NULL, &count, info, NULL);
+ codec_info = &info[0];
+ }
+
+ /* Get codec default param for info */
+ status = pjmedia_vid_codec_mgr_get_default_param(NULL, codec_info,
+ &codec_param);
+ pj_assert(status == PJ_SUCCESS);
+
+ /* Set outgoing video size */
+ if (tx_size.w && tx_size.h)
+ codec_param.enc_fmt.det.vid.size = tx_size;
+
+#if DEF_RENDERER_WIDTH && DEF_RENDERER_HEIGHT
+ /* Set incoming video size */
+ if (DEF_RENDERER_WIDTH > codec_param.dec_fmt.det.vid.size.w)
+ codec_param.dec_fmt.det.vid.size.w = DEF_RENDERER_WIDTH;
+ if (DEF_RENDERER_HEIGHT > codec_param.dec_fmt.det.vid.size.h)
+ codec_param.dec_fmt.det.vid.size.h = DEF_RENDERER_HEIGHT;
+#endif
+
+ if (play_file.file_name) {
+ pjmedia_video_format_detail *file_vfd;
+ pjmedia_clock_param clock_param;
+ char fmt_name[5];
+
+ /* Create file player */
+ status = create_file_player(pool, play_file.file_name, &play_port);
+ if (status != PJ_SUCCESS)
+ goto on_exit;
+
+ /* Collect format info */
+ file_vfd = pjmedia_format_get_video_format_detail(&play_port->info.fmt,
+ PJ_TRUE);
+ PJ_LOG(2, (THIS_FILE, "Reading video stream %dx%d %s @%.2ffps",
+ file_vfd->size.w, file_vfd->size.h,
+ pjmedia_fourcc_name(play_port->info.fmt.id, fmt_name),
+ (1.0*file_vfd->fps.num/file_vfd->fps.denum)));
+
+ /* Allocate file read buffer */
+ play_file.read_buf_size = PJMEDIA_MAX_VIDEO_ENC_FRAME_SIZE;
+ play_file.read_buf = pj_pool_zalloc(pool, play_file.read_buf_size);
+
+ /* Create decoder, if the file and the stream uses different codec */
+ if (codec_info->fmt_id != (pjmedia_format_id)play_port->info.fmt.id) {
+ const pjmedia_video_format_info *dec_vfi;
+ pjmedia_video_apply_fmt_param dec_vafp = {0};
+ const pjmedia_vid_codec_info *codec_info2;
+ pjmedia_vid_codec_param codec_param2;
+
+ /* Find decoder */
+ status = pjmedia_vid_codec_mgr_get_codec_info2(NULL,
+ play_port->info.fmt.id,
+ &codec_info2);
+ if (status != PJ_SUCCESS)
+ goto on_exit;
+
+ /* Init decoder */
+ status = pjmedia_vid_codec_mgr_alloc_codec(NULL, codec_info2,
+ &play_decoder);
+ if (status != PJ_SUCCESS)
+ goto on_exit;
+
+ status = play_decoder->op->init(play_decoder, pool);
+ if (status != PJ_SUCCESS)
+ goto on_exit;
+
+ /* Open decoder */
+ status = pjmedia_vid_codec_mgr_get_default_param(NULL, codec_info2,
+ &codec_param2);
+ if (status != PJ_SUCCESS)
+ goto on_exit;
+
+ codec_param2.dir = PJMEDIA_DIR_DECODING;
+ status = play_decoder->op->open(play_decoder, &codec_param2);
+ if (status != PJ_SUCCESS)
+ goto on_exit;
+
+ /* Get decoder format info and apply param */
+ dec_vfi = pjmedia_get_video_format_info(NULL,
+ codec_info2->dec_fmt_id[0]);
+ if (!dec_vfi || !dec_vfi->apply_fmt) {
+ status = PJ_ENOTSUP;
+ goto on_exit;
+ }
+ dec_vafp.size = file_vfd->size;
+ (*dec_vfi->apply_fmt)(dec_vfi, &dec_vafp);
+
+ /* Allocate buffer to receive decoder output */
+ play_file.dec_buf_size = dec_vafp.framebytes;
+ play_file.dec_buf = pj_pool_zalloc(pool, play_file.dec_buf_size);
+ }
+
+ /* Create player clock */
+ clock_param.usec_interval = PJMEDIA_PTIME(&file_vfd->fps);
+ clock_param.clock_rate = codec_info->clock_rate;
+ status = pjmedia_clock_create2(pool, &clock_param,
+ PJMEDIA_CLOCK_NO_HIGHEST_PRIO,
+ &clock_cb, &play_file, &play_clock);
+ if (status != PJ_SUCCESS)
+ goto on_exit;
+
+ /* Override stream codec param for encoding direction */
+ codec_param.enc_fmt.det.vid.size = file_vfd->size;
+ codec_param.enc_fmt.det.vid.fps = file_vfd->fps;
+
+ } else {
+ pjmedia_vid_port_param_default(&vpp);
+
+ /* Set as active for all video devices */
+ vpp.active = PJ_TRUE;
+
+ /* Create video device port. */
+ if (dir & PJMEDIA_DIR_ENCODING) {
+ /* Create capture */
+ status = pjmedia_vid_dev_default_param(
+ pool,
+ PJMEDIA_VID_DEFAULT_CAPTURE_DEV,
+ &vpp.vidparam);
+ if (status != PJ_SUCCESS)
+ goto on_exit;
+
+ pjmedia_format_copy(&vpp.vidparam.fmt, &codec_param.enc_fmt);
+ vpp.vidparam.fmt.id = codec_param.dec_fmt.id;
+ vpp.vidparam.dir = PJMEDIA_DIR_CAPTURE;
+
+ status = pjmedia_vid_port_create(pool, &vpp, &capture);
+ if (status != PJ_SUCCESS)
+ goto on_exit;
+ }
+
+ if (dir & PJMEDIA_DIR_DECODING) {
+ /* Create renderer */
+ status = pjmedia_vid_dev_default_param(
+ pool,
+ PJMEDIA_VID_DEFAULT_RENDER_DEV,
+ &vpp.vidparam);
+ if (status != PJ_SUCCESS)
+ goto on_exit;
+
+ pjmedia_format_copy(&vpp.vidparam.fmt, &codec_param.dec_fmt);
+ vpp.vidparam.dir = PJMEDIA_DIR_RENDER;
+ vpp.vidparam.disp_size = vpp.vidparam.fmt.det.vid.size;
+ vpp.vidparam.flags |= PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW_FLAGS;
+ vpp.vidparam.window_flags = PJMEDIA_VID_DEV_WND_BORDER |
+ PJMEDIA_VID_DEV_WND_RESIZABLE;
+
+ status = pjmedia_vid_port_create(pool, &vpp, &renderer);
+ if (status != PJ_SUCCESS)
+ goto on_exit;
+ }
+ }
+
+ /* Set to ignore fmtp */
+ codec_param.ignore_fmtp = PJ_TRUE;
+
+ /* Create stream based on program arguments */
+ status = create_stream(pool, med_endpt, codec_info, &codec_param,
+ dir, rx_pt, tx_pt, local_port, &remote_addr,
+#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
+ use_srtp, &srtp_crypto_suite,
+ &srtp_tx_key, &srtp_rx_key,
+#endif
+ &stream);
+ if (status != PJ_SUCCESS)
+ goto on_exit;
+
+ /* Get the port interface of the stream */
+ status = pjmedia_vid_stream_get_port(stream, PJMEDIA_DIR_ENCODING,
+ &enc_port);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ status = pjmedia_vid_stream_get_port(stream, PJMEDIA_DIR_DECODING,
+ &dec_port);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ /* Start streaming */
+ status = pjmedia_vid_stream_start(stream);
+ if (status != PJ_SUCCESS)
+ goto on_exit;
+
+ /* Start renderer */
+ if (renderer) {
+ status = pjmedia_vid_port_connect(renderer, dec_port, PJ_FALSE);
+ if (status != PJ_SUCCESS)
+ goto on_exit;
+ status = pjmedia_vid_port_start(renderer);
+ if (status != PJ_SUCCESS)
+ goto on_exit;
+ }
+
+ /* Start capture */
+ if (capture) {
+ status = pjmedia_vid_port_connect(capture, enc_port, PJ_FALSE);
+ if (status != PJ_SUCCESS)
+ goto on_exit;
+ status = pjmedia_vid_port_start(capture);
+ if (status != PJ_SUCCESS)
+ goto on_exit;
+ }
+
+ /* Start playing file */
+ if (play_file.file_name) {
+
+#if HAS_LOCAL_RENDERER_FOR_PLAY_FILE
+ /* Create local renderer */
+ pjmedia_vid_port_param_default(&vpp);
+ vpp.active = PJ_FALSE;
+ status = pjmedia_vid_dev_default_param(
+ pool,
+ PJMEDIA_VID_DEFAULT_RENDER_DEV,
+ &vpp.vidparam);
+ if (status != PJ_SUCCESS)
+ goto on_exit;
+
+ vpp.vidparam.dir = PJMEDIA_DIR_RENDER;
+ pjmedia_format_copy(&vpp.vidparam.fmt, &codec_param.dec_fmt);
+ vpp.vidparam.fmt.det.vid.size = play_port->info.fmt.det.vid.size;
+ vpp.vidparam.fmt.det.vid.fps = play_port->info.fmt.det.vid.fps;
+ vpp.vidparam.disp_size = vpp.vidparam.fmt.det.vid.size;
+ vpp.vidparam.flags |= PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW_FLAGS;
+ vpp.vidparam.window_flags = PJMEDIA_VID_DEV_WND_BORDER |
+ PJMEDIA_VID_DEV_WND_RESIZABLE;
+
+ status = pjmedia_vid_port_create(pool, &vpp, &renderer);
+ if (status != PJ_SUCCESS)
+ goto on_exit;
+ status = pjmedia_vid_port_start(renderer);
+ if (status != PJ_SUCCESS)
+ goto on_exit;
+#endif
+
+ /* Init play file data */
+ play_file.play_port = play_port;
+ play_file.stream_port = enc_port;
+ play_file.decoder = play_decoder;
+ if (renderer) {
+ play_file.renderer = pjmedia_vid_port_get_passive_port(renderer);
+ }
+
+ status = pjmedia_clock_start(play_clock);
+ if (status != PJ_SUCCESS)
+ goto on_exit;
+ }
+
+ /* Done */
+
+ if (dir == PJMEDIA_DIR_DECODING)
+ printf("Stream is active, dir is recv-only, local port is %d\n",
+ local_port);
+ else if (dir == PJMEDIA_DIR_ENCODING)
+ printf("Stream is active, dir is send-only, sending to %s:%d\n",
+ pj_inet_ntoa(remote_addr.sin_addr),
+ pj_ntohs(remote_addr.sin_port));
+ else
+ printf("Stream is active, send/recv, local port is %d, "
+ "sending to %s:%d\n",
+ local_port,
+ pj_inet_ntoa(remote_addr.sin_addr),
+ pj_ntohs(remote_addr.sin_port));
+
+ if (dir & PJMEDIA_DIR_ENCODING)
+ PJ_LOG(2, (THIS_FILE, "Sending %dx%d %.*s @%.2ffps",
+ codec_param.enc_fmt.det.vid.size.w,
+ codec_param.enc_fmt.det.vid.size.h,
+ codec_info->encoding_name.slen,
+ codec_info->encoding_name.ptr,
+ (1.0*codec_param.enc_fmt.det.vid.fps.num/
+ codec_param.enc_fmt.det.vid.fps.denum)));
+
+ for (;;) {
+ char tmp[10];
+
+ puts("");
+ puts("Commands:");
+ puts(" q Quit");
+ puts("");
+
+ printf("Command: "); fflush(stdout);
+
+ if (fgets(tmp, sizeof(tmp), stdin) == NULL) {
+ puts("EOF while reading stdin, will quit now..");
+ break;
+ }
+
+ if (tmp[0] == 'q')
+ break;
+
+ }
+
+
+
+ /* Start deinitialization: */
+on_exit:
+
+ /* Stop video devices */
+ if (capture)
+ pjmedia_vid_port_stop(capture);
+ if (renderer)
+ pjmedia_vid_port_stop(renderer);
+
+ /* Stop and destroy file clock */
+ if (play_clock) {
+ pjmedia_clock_stop(play_clock);
+ pjmedia_clock_destroy(play_clock);
+ }
+
+ /* Destroy file reader/player */
+ if (play_port)
+ pjmedia_port_destroy(play_port);
+
+ /* Destroy file decoder */
+ if (play_decoder) {
+ play_decoder->op->close(play_decoder);
+ pjmedia_vid_codec_mgr_dealloc_codec(NULL, play_decoder);
+ }
+
+ /* Destroy video devices */
+ if (capture)
+ pjmedia_vid_port_destroy(capture);
+ if (renderer)
+ pjmedia_vid_port_destroy(renderer);
+
+ /* Destroy stream */
+ if (stream) {
+ pjmedia_transport *tp;
+
+ tp = pjmedia_vid_stream_get_transport(stream);
+ pjmedia_vid_stream_destroy(stream);
+
+ pjmedia_transport_close(tp);
+ }
+
+ /* Deinit codecs */
+ deinit_codecs();
+
+ /* Shutdown video subsystem */
+ pjmedia_vid_dev_subsys_shutdown();
+
+ /* Destroy event manager */
+ pjmedia_event_mgr_destroy(NULL);
+
+ /* Release application pool */
+ pj_pool_release( pool );
+
+ /* Destroy media endpoint. */
+ pjmedia_endpt_destroy( med_endpt );
+
+ /* Destroy pool factory */
+ pj_caching_pool_destroy( &cp );
+
+ /* Shutdown PJLIB */
+ pj_shutdown();
+
+ return (status == PJ_SUCCESS) ? 0 : 1;
+}
+
+
+#else
+
+int main(int argc, char *argv[])
+{
+ PJ_UNUSED_ARG(argc);
+ PJ_UNUSED_ARG(argv);
+ puts("Error: this sample requires video capability (PJMEDIA_HAS_VIDEO == 1)");
+ return -1;
+}
+
+#endif /* PJMEDIA_HAS_VIDEO */
diff --git a/pjsip-apps/src/symbian_ua/main_symbian.cpp b/pjsip-apps/src/symbian_ua/main_symbian.cpp
new file mode 100644
index 0000000..cb9b0bc
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua/main_symbian.cpp
@@ -0,0 +1,82 @@
+/* $Id: main_symbian.cpp 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include "ua.h"
+
+#include <e32std.h>
+#include <e32base.h>
+#include <e32std.h>
+#include <stdlib.h>
+
+
+// Global Variables
+CConsoleBase* console;
+
+// Needed by APS
+//TPtrC APP_UID = _L("200235D3");
+TPtrC APP_UID = _L("A000000D");
+
+
+////////////////////////////////////////////////////////////////////////////
+
+LOCAL_C void DoStartL()
+{
+ CActiveScheduler *scheduler = new (ELeave) CActiveScheduler;
+ CleanupStack::PushL(scheduler);
+ CActiveScheduler::Install(scheduler);
+
+ ua_main();
+
+ CActiveScheduler::Install(NULL);
+ CleanupStack::Pop(scheduler);
+ delete scheduler;
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+
+// E32Main()
+GLDEF_C TInt E32Main()
+{
+ // Mark heap usage
+ __UHEAP_MARK;
+
+ // Create cleanup stack
+ CTrapCleanup* cleanup = CTrapCleanup::New();
+
+ // Create output console
+ TRAPD(createError, console = Console::NewL(_L("Console"), TSize(KConsFullScreen,KConsFullScreen)));
+ if (createError)
+ return createError;
+
+ TRAPD(startError, DoStartL());
+
+ console->Printf(_L("[press any key to close]\n"));
+ console->Getch();
+
+ delete console;
+ delete cleanup;
+
+ CloseSTDLIB();
+
+ // Mark end of heap usage, detect memory leaks
+ __UHEAP_MARKEND;
+ return KErrNone;
+}
+
diff --git a/pjsip-apps/src/symbian_ua/symbian_ua_reg.rss b/pjsip-apps/src/symbian_ua/symbian_ua_reg.rss
new file mode 100644
index 0000000..a513665
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua/symbian_ua_reg.rss
@@ -0,0 +1,10 @@
+#include <appinfo.rh>
+
+UID2 KUidAppRegistrationResourceFile
+UID3 0xA000000D
+
+RESOURCE APP_REGISTRATION_INFO
+{
+ app_file="symbian_ua";
+}
+
diff --git a/pjsip-apps/src/symbian_ua/ua.cpp b/pjsip-apps/src/symbian_ua/ua.cpp
new file mode 100644
index 0000000..53e2329
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua/ua.cpp
@@ -0,0 +1,1186 @@
+/* $Id: ua.cpp 3999 2012-03-30 07:10:13Z bennylp $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <pjsua-lib/pjsua.h>
+#include <pjsua-lib/pjsua_internal.h>
+//#include <pjmedia/symbian_sound_aps.h>
+#include "ua.h"
+
+#define THIS_FILE "symbian_ua.cpp"
+#define CON_LOG_LEVEL 3 // console log level
+#define FILE_LOG_LEVEL 4 // logfile log level
+
+//
+// Basic config.
+//
+#define SIP_PORT 5060
+
+
+//
+// Destination URI (to make call, or to subscribe presence)
+//
+#define SIP_DST_URI "<sip:100@pjsip.lab>"
+
+//
+// Account
+//
+#define HAS_SIP_ACCOUNT 0 // 1 to enable registration
+#define SIP_DOMAIN "pjsip.lab"
+#define SIP_USER "400"
+#define SIP_PASSWD "400"
+
+//
+// Outbound proxy for all accounts
+//
+#define SIP_PROXY NULL
+//#define SIP_PROXY "<sip:192.168.0.8;lr>"
+
+//
+// SIP transports
+//
+#define ENABLE_SIP_UDP 1
+#define ENABLE_SIP_TCP 0 // experimental
+#define ENABLE_SIP_TLS 0 // experimental
+
+//
+// Configure nameserver if DNS SRV is to be used with both SIP
+// or STUN (for STUN see other settings below)
+//
+#define NAMESERVER NULL
+//#define NAMESERVER "192.168.0.2"
+
+//
+// STUN server
+#if 0
+ // Use this to have the STUN server resolved normally
+# define STUN_DOMAIN NULL
+# define STUN_SERVER "stun.pjsip.org"
+#elif 0
+ // Use this to have the STUN server resolved with DNS SRV
+# define STUN_DOMAIN "pjsip.org"
+# define STUN_SERVER NULL
+#else
+ // Use this to disable STUN
+# define STUN_DOMAIN NULL
+# define STUN_SERVER NULL
+#endif
+
+//
+// Use ICE?
+//
+#define USE_ICE 1
+
+//
+// Use SRTP?
+//
+#define USE_SRTP PJSUA_DEFAULT_USE_SRTP
+
+//
+// Set QoS on transports? Yes!
+// As an example, we set SIP transports DSCP value to CS3 (DSCP
+// value 24 or 0x18), for no reason, and tag RTP/RTCP packets
+// with VOICE type.
+//
+#define SIP_QOS_DSCP 0x18
+#define RTP_QOS_TYPE PJ_QOS_TYPE_VOICE
+
+
+//
+// Globals
+//
+static pjsua_acc_id g_acc_id = PJSUA_INVALID_ID;
+static pjsua_call_id g_call_id = PJSUA_INVALID_ID;
+static pjsua_buddy_id g_buddy_id = PJSUA_INVALID_ID;
+
+
+/* Callback called by the library upon receiving incoming call */
+static void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id,
+ pjsip_rx_data *rdata)
+{
+ pjsua_call_info ci;
+
+ PJ_UNUSED_ARG(acc_id);
+ PJ_UNUSED_ARG(rdata);
+
+ if (g_call_id != PJSUA_INVALID_ID) {
+ pjsua_call_answer(call_id, PJSIP_SC_BUSY_HERE, NULL, NULL);
+ return;
+ }
+
+ pjsua_call_get_info(call_id, &ci);
+
+ PJ_LOG(3,(THIS_FILE, "Incoming call from %.*s!!",
+ (int)ci.remote_info.slen,
+ ci.remote_info.ptr));
+
+ g_call_id = call_id;
+
+ /* Automatically answer incoming calls with 180/Ringing */
+ pjsua_call_answer(call_id, 180, NULL, NULL);
+}
+
+/* Callback called by the library when call's state has changed */
+static void on_call_state(pjsua_call_id call_id, pjsip_event *e)
+{
+ pjsua_call_info ci;
+
+ PJ_UNUSED_ARG(e);
+
+ pjsua_call_get_info(call_id, &ci);
+
+ if (ci.state == PJSIP_INV_STATE_DISCONNECTED) {
+ if (call_id == g_call_id)
+ g_call_id = PJSUA_INVALID_ID;
+ } else if (ci.state != PJSIP_INV_STATE_INCOMING) {
+ if (g_call_id == PJSUA_INVALID_ID)
+ g_call_id = call_id;
+ }
+
+ PJ_LOG(3,(THIS_FILE, "Call %d state=%.*s", call_id,
+ (int)ci.state_text.slen,
+ ci.state_text.ptr));
+}
+
+/* Callback called by the library when call's media state has changed */
+static void on_call_media_state(pjsua_call_id call_id)
+{
+ pjsua_call_info ci;
+
+ pjsua_call_get_info(call_id, &ci);
+
+ if (ci.media_status == PJSUA_CALL_MEDIA_ACTIVE) {
+ // When media is active, connect call to sound device.
+ pjsua_conf_connect(ci.conf_slot, 0);
+ pjsua_conf_connect(0, ci.conf_slot);
+ }
+}
+
+
+/* Handler on buddy state changed. */
+static void on_buddy_state(pjsua_buddy_id buddy_id)
+{
+ pjsua_buddy_info info;
+ pjsua_buddy_get_info(buddy_id, &info);
+
+ PJ_LOG(3,(THIS_FILE, "%.*s status is %.*s",
+ (int)info.uri.slen,
+ info.uri.ptr,
+ (int)info.status_text.slen,
+ info.status_text.ptr));
+}
+
+
+/* Incoming IM message (i.e. MESSAGE request)! */
+static void on_pager(pjsua_call_id call_id, const pj_str_t *from,
+ const pj_str_t *to, const pj_str_t *contact,
+ const pj_str_t *mime_type, const pj_str_t *text)
+{
+ /* Note: call index may be -1 */
+ PJ_UNUSED_ARG(call_id);
+ PJ_UNUSED_ARG(to);
+ PJ_UNUSED_ARG(contact);
+ PJ_UNUSED_ARG(mime_type);
+
+ PJ_LOG(3,(THIS_FILE,"MESSAGE from %.*s: %.*s",
+ (int)from->slen, from->ptr,
+ (int)text->slen, text->ptr));
+}
+
+
+/* Received typing indication */
+static void on_typing(pjsua_call_id call_id, const pj_str_t *from,
+ const pj_str_t *to, const pj_str_t *contact,
+ pj_bool_t is_typing)
+{
+ PJ_UNUSED_ARG(call_id);
+ PJ_UNUSED_ARG(to);
+ PJ_UNUSED_ARG(contact);
+
+ PJ_LOG(3,(THIS_FILE, "IM indication: %.*s %s",
+ (int)from->slen, from->ptr,
+ (is_typing?"is typing..":"has stopped typing")));
+}
+
+
+/* Call transfer request status. */
+static void on_call_transfer_status(pjsua_call_id call_id,
+ int status_code,
+ const pj_str_t *status_text,
+ pj_bool_t final,
+ pj_bool_t *p_cont)
+{
+ PJ_LOG(3,(THIS_FILE, "Call %d: transfer status=%d (%.*s) %s",
+ call_id, status_code,
+ (int)status_text->slen, status_text->ptr,
+ (final ? "[final]" : "")));
+
+ if (status_code/100 == 2) {
+ PJ_LOG(3,(THIS_FILE,
+ "Call %d: call transfered successfully, disconnecting call",
+ call_id));
+ pjsua_call_hangup(call_id, PJSIP_SC_GONE, NULL, NULL);
+ *p_cont = PJ_FALSE;
+ }
+}
+
+
+/* NAT detection result */
+static void on_nat_detect(const pj_stun_nat_detect_result *res)
+{
+ if (res->status != PJ_SUCCESS) {
+ pjsua_perror(THIS_FILE, "NAT detection failed", res->status);
+ } else {
+ PJ_LOG(3, (THIS_FILE, "NAT detected as %s", res->nat_type_name));
+ }
+}
+
+/* Notification that call is being replaced. */
+static void on_call_replaced(pjsua_call_id old_call_id,
+ pjsua_call_id new_call_id)
+{
+ pjsua_call_info old_ci, new_ci;
+
+ pjsua_call_get_info(old_call_id, &old_ci);
+ pjsua_call_get_info(new_call_id, &new_ci);
+
+ PJ_LOG(3,(THIS_FILE, "Call %d with %.*s is being replaced by "
+ "call %d with %.*s",
+ old_call_id,
+ (int)old_ci.remote_info.slen, old_ci.remote_info.ptr,
+ new_call_id,
+ (int)new_ci.remote_info.slen, new_ci.remote_info.ptr));
+}
+
+/*
+ * Transport status notification
+ */
+static void on_transport_state(pjsip_transport *tp,
+ pjsip_transport_state state,
+ const pjsip_transport_state_info *info)
+{
+ char host_port[128];
+
+ pj_ansi_snprintf(host_port, sizeof(host_port), "[%.*s:%d]",
+ (int)tp->remote_name.host.slen,
+ tp->remote_name.host.ptr,
+ tp->remote_name.port);
+
+ switch (state) {
+ case PJSIP_TP_STATE_CONNECTED:
+ {
+ PJ_LOG(3,(THIS_FILE, "SIP transport %s is connected to %s",
+ tp->type_name, host_port));
+ }
+ break;
+
+ case PJSIP_TP_STATE_DISCONNECTED:
+ {
+ char buf[100];
+
+ snprintf(buf, sizeof(buf), "SIP transport %s is disconnected from %s",
+ tp->type_name, host_port);
+ pjsua_perror(THIS_FILE, buf, info->status);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+#if defined(PJSIP_HAS_TLS_TRANSPORT) && PJSIP_HAS_TLS_TRANSPORT!=0
+
+ if (!pj_ansi_stricmp(tp->type_name, "tls") && info->ext_info &&
+ state == PJSIP_TP_STATE_CONNECTED)
+ {
+ pjsip_tls_state_info *tls_info = (pjsip_tls_state_info*)info->ext_info;
+ pj_ssl_sock_info *ssl_sock_info = (pj_ssl_sock_info*)
+ tls_info->ssl_sock_info;
+ char buf[2048];
+
+ /* Dump server TLS certificate */
+ pj_ssl_cert_info_dump(ssl_sock_info->remote_cert_info, " ",
+ buf, sizeof(buf));
+ PJ_LOG(4,(THIS_FILE, "TLS cert info of %s:\n%s", host_port, buf));
+ }
+
+#endif
+}
+
+
+//#include<e32debug.h>
+
+/* Logging callback */
+static void log_writer(int level, const char *buf, int len)
+{
+ static wchar_t buf16[PJ_LOG_MAX_SIZE];
+
+ PJ_UNUSED_ARG(level);
+
+ pj_ansi_to_unicode(buf, len, buf16, PJ_ARRAY_SIZE(buf16));
+
+ TPtrC16 aBuf((const TUint16*)buf16, (TInt)len);
+ //RDebug::Print(aBuf);
+ console->Write(aBuf);
+
+}
+
+/*
+ * app_startup()
+ *
+ * url may contain URL to call.
+ */
+static pj_status_t app_startup()
+{
+ pj_status_t status;
+
+ /* Redirect log before pjsua_init() */
+ pj_log_set_log_func(&log_writer);
+
+ /* Set log level */
+ pj_log_set_level(CON_LOG_LEVEL);
+
+ /* Create pjsua first! */
+ status = pjsua_create();
+ if (status != PJ_SUCCESS) {
+ pjsua_perror(THIS_FILE, "pjsua_create() error", status);
+ return status;
+ }
+
+ /* Init pjsua */
+ pjsua_config cfg;
+ pjsua_logging_config log_cfg;
+ pjsua_media_config med_cfg;
+
+ pjsua_config_default(&cfg);
+ cfg.max_calls = 2;
+ cfg.thread_cnt = 0; // Disable threading on Symbian
+ cfg.use_srtp = USE_SRTP;
+ cfg.srtp_secure_signaling = 0;
+
+ cfg.cb.on_incoming_call = &on_incoming_call;
+ cfg.cb.on_call_media_state = &on_call_media_state;
+ cfg.cb.on_call_state = &on_call_state;
+ cfg.cb.on_buddy_state = &on_buddy_state;
+ cfg.cb.on_pager = &on_pager;
+ cfg.cb.on_typing = &on_typing;
+ cfg.cb.on_call_transfer_status = &on_call_transfer_status;
+ cfg.cb.on_call_replaced = &on_call_replaced;
+ cfg.cb.on_nat_detect = &on_nat_detect;
+ cfg.cb.on_transport_state = &on_transport_state;
+
+ if (SIP_PROXY) {
+ cfg.outbound_proxy_cnt = 1;
+ cfg.outbound_proxy[0] = pj_str(SIP_PROXY);
+ }
+
+ if (NAMESERVER) {
+ cfg.nameserver_count = 1;
+ cfg.nameserver[0] = pj_str(NAMESERVER);
+ }
+
+ if (NAMESERVER && STUN_DOMAIN) {
+ cfg.stun_domain = pj_str(STUN_DOMAIN);
+ } else if (STUN_SERVER) {
+ cfg.stun_host = pj_str(STUN_SERVER);
+ }
+
+
+ pjsua_logging_config_default(&log_cfg);
+ log_cfg.level = FILE_LOG_LEVEL;
+ log_cfg.console_level = CON_LOG_LEVEL;
+ log_cfg.cb = &log_writer;
+ log_cfg.log_filename = pj_str("C:\\data\\symbian_ua.log");
+
+ pjsua_media_config_default(&med_cfg);
+ med_cfg.thread_cnt = 0; // Disable threading on Symbian
+ med_cfg.has_ioqueue = PJ_FALSE;
+ med_cfg.clock_rate = 8000;
+ med_cfg.audio_frame_ptime = 40;
+ med_cfg.ec_tail_len = 0;
+ med_cfg.enable_ice = USE_ICE;
+ med_cfg.snd_auto_close_time = 0; // wait for 0 seconds idle before sound dev get auto-closed
+ //med_cfg.no_vad = PJ_TRUE;
+
+ status = pjsua_init(&cfg, &log_cfg, &med_cfg);
+ if (status != PJ_SUCCESS) {
+ pjsua_perror(THIS_FILE, "pjsua_init() error", status);
+ pjsua_destroy();
+ return status;
+ }
+
+ /* Adjust Speex priority and enable only the narrowband */
+ {
+ pj_str_t codec_id = pj_str("speex/8000");
+ pjmedia_codec_mgr_set_codec_priority(
+ pjmedia_endpt_get_codec_mgr(pjsua_var.med_endpt),
+ &codec_id, PJMEDIA_CODEC_PRIO_NORMAL+1);
+
+ codec_id = pj_str("speex/16000");
+ pjmedia_codec_mgr_set_codec_priority(
+ pjmedia_endpt_get_codec_mgr(pjsua_var.med_endpt),
+ &codec_id, PJMEDIA_CODEC_PRIO_DISABLED);
+
+ codec_id = pj_str("speex/32000");
+ pjmedia_codec_mgr_set_codec_priority(
+ pjmedia_endpt_get_codec_mgr(pjsua_var.med_endpt),
+ &codec_id, PJMEDIA_CODEC_PRIO_DISABLED);
+ }
+
+
+ pjsua_transport_config tcfg;
+ pjsua_transport_id tid;
+
+#if ENABLE_SIP_UDP
+ /* Add UDP transport. */
+ pjsua_transport_config_default(&tcfg);
+ tcfg.port = SIP_PORT;
+ if (SIP_QOS_DSCP) {
+ tcfg.qos_params.flags |= PJ_QOS_PARAM_HAS_DSCP;
+ tcfg.qos_params.dscp_val = SIP_QOS_DSCP;
+ }
+ status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, &tcfg, &tid);
+ if (status != PJ_SUCCESS) {
+ pjsua_perror(THIS_FILE, "Error creating UDP transport", status);
+ pjsua_destroy();
+ return status;
+ }
+#endif
+
+#if ENABLE_SIP_TCP
+ /* Add TCP transport */
+ pjsua_transport_config_default(&tcfg);
+ tcfg.port = SIP_PORT;
+ if (SIP_QOS_DSCP) {
+ tcfg.qos_params.flags |= PJ_QOS_PARAM_HAS_DSCP;
+ tcfg.qos_params.dscp_val = SIP_QOS_DSCP;
+ }
+ status = pjsua_transport_create(PJSIP_TRANSPORT_TCP, &tcfg, &tid);
+ if (status != PJ_SUCCESS) {
+ pjsua_perror(THIS_FILE, "Error creating TCP transport", status);
+ pjsua_destroy();
+ return status;
+ }
+#endif
+
+#if ENABLE_SIP_TLS
+ /* Add TLS transport */
+ pjsua_transport_config_default(&tcfg);
+ tcfg.port = SIP_PORT + 1;
+ if (SIP_QOS_DSCP) {
+ tcfg.qos_params.flags |= PJ_QOS_PARAM_HAS_DSCP;
+ tcfg.qos_params.dscp_val = SIP_QOS_DSCP;
+ tcfg.tls_setting.qos_params = tcfg.qos_params;
+ }
+ status = pjsua_transport_create(PJSIP_TRANSPORT_TLS, &tcfg, &tid);
+ if (status != PJ_SUCCESS) {
+ pjsua_perror(THIS_FILE, "Error creating TLS transport", status);
+ pjsua_destroy();
+ return status;
+ }
+#endif
+
+ /* Add account for the transport */
+ pjsua_acc_add_local(tid, PJ_TRUE, &g_acc_id);
+
+#if DISABLED_FOR_TICKET_1185
+ /* Create media transports */
+ pjsua_transport_config mtcfg;
+ pjsua_transport_config_default(&mtcfg);
+ mtcfg.port = 4000;
+ mtcfg.qos_type = RTP_QOS_TYPE;
+ status = pjsua_media_transports_create(&mtcfg);
+ if (status != PJ_SUCCESS) {
+ pjsua_perror(THIS_FILE, "Error creating media transports", status);
+ pjsua_destroy();
+ return status;
+ }
+#endif
+
+ /* Initialization is done, now start pjsua */
+ status = pjsua_start();
+ if (status != PJ_SUCCESS) {
+ pjsua_perror(THIS_FILE, "Error starting pjsua", status);
+ pjsua_destroy();
+ return status;
+ }
+
+ /* Register to SIP server by creating SIP account. */
+ if (HAS_SIP_ACCOUNT) {
+ pjsua_acc_config cfg;
+
+ pjsua_acc_config_default(&cfg);
+ cfg.id = pj_str("sip:" SIP_USER "@" SIP_DOMAIN);
+ cfg.reg_uri = pj_str("sip:" SIP_DOMAIN);
+ cfg.cred_count = 1;
+ cfg.cred_info[0].realm = pj_str("*");
+ cfg.cred_info[0].scheme = pj_str("digest");
+ cfg.cred_info[0].username = pj_str(SIP_USER);
+ cfg.cred_info[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
+ cfg.cred_info[0].data = pj_str(SIP_PASSWD);
+
+ status = pjsua_acc_add(&cfg, PJ_TRUE, &g_acc_id);
+ if (status != PJ_SUCCESS) {
+ pjsua_perror(THIS_FILE, "Error adding account", status);
+ pjsua_destroy();
+ return status;
+ }
+ }
+
+ if (SIP_DST_URI) {
+ pjsua_buddy_config bcfg;
+
+ pjsua_buddy_config_default(&bcfg);
+ bcfg.uri = pj_str(SIP_DST_URI);
+ bcfg.subscribe = PJ_FALSE;
+
+ pjsua_buddy_add(&bcfg, &g_buddy_id);
+ }
+ return PJ_SUCCESS;
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+/*
+ * The interractive console UI
+ */
+#include <e32base.h>
+
+class ConsoleUI : public CActive
+{
+public:
+ ConsoleUI(CConsoleBase *con);
+ ~ConsoleUI();
+
+ // Run console UI
+ void Run();
+
+ // Stop
+ void Stop();
+
+protected:
+ // Cancel asynchronous read.
+ void DoCancel();
+
+ // Implementation: called when read has completed.
+ void RunL();
+
+private:
+ CConsoleBase *con_;
+};
+
+
+ConsoleUI::ConsoleUI(CConsoleBase *con)
+: CActive(EPriorityStandard), con_(con)
+{
+ CActiveScheduler::Add(this);
+}
+
+ConsoleUI::~ConsoleUI()
+{
+ Stop();
+}
+
+// Run console UI
+void ConsoleUI::Run()
+{
+ con_->Read(iStatus);
+ SetActive();
+}
+
+// Stop console UI
+void ConsoleUI::Stop()
+{
+ Cancel();
+}
+
+// Cancel asynchronous read.
+void ConsoleUI::DoCancel()
+{
+ con_->ReadCancel();
+}
+
+static void PrintMainMenu()
+{
+ const char *menu =
+ "\n\n"
+ "Main Menu:\n"
+ " d Enable/disable codecs\n"
+ " m Call " SIP_DST_URI "\n"
+ " a Answer call\n"
+ " g Hangup all calls\n"
+ " t Toggle audio route\n"
+#if !defined(PJMEDIA_CONF_USE_SWITCH_BOARD) || PJMEDIA_CONF_USE_SWITCH_BOARD==0
+ " j Toggle loopback audio\n"
+#endif
+ "up/dn Increase/decrease output volume\n"
+ " s Subscribe " SIP_DST_URI "\n"
+ " S Unsubscribe presence\n"
+ " o Set account online\n"
+ " O Set account offline\n"
+ " w Quit\n";
+
+ PJ_LOG(3, (THIS_FILE, menu));
+}
+
+static void PrintCodecMenu()
+{
+ const char *menu =
+ "\n\n"
+ "Codec Menu:\n"
+ " a Enable all codecs\n"
+#if PJMEDIA_HAS_PASSTHROUGH_CODECS && PJMEDIA_HAS_PASSTHROUGH_CODEC_AMR
+ " d Enable only AMR\n"
+#endif
+#if PJMEDIA_HAS_PASSTHROUGH_CODECS && PJMEDIA_HAS_PASSTHROUGH_CODEC_G729
+ " g Enable only G.729\n"
+#endif
+#if PJMEDIA_HAS_PASSTHROUGH_CODECS && PJMEDIA_HAS_PASSTHROUGH_CODEC_ILBC
+ " j Enable only iLBC\n"
+#endif
+ " m Enable only Speex\n"
+ " p Enable only GSM\n"
+ " t Enable only PCMU\n"
+ " w Enable only PCMA\n";
+
+ PJ_LOG(3, (THIS_FILE, menu));
+}
+
+static void HandleMainMenu(TKeyCode kc) {
+ switch (kc) {
+
+ case EKeyUpArrow:
+ case EKeyDownArrow:
+ {
+ unsigned vol;
+ pj_status_t status;
+
+ status = pjsua_snd_get_setting(
+ PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING, &vol);
+ if (status == PJ_SUCCESS) {
+ if (kc == EKeyUpArrow)
+ vol = PJ_MIN(100, vol+10);
+ else
+ vol = (vol>=10 ? vol-10 : 0);
+ status = pjsua_snd_set_setting(
+ PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING,
+ &vol, PJ_TRUE);
+ }
+
+ if (status == PJ_SUCCESS) {
+ PJ_LOG(3,(THIS_FILE, "Output volume set to %d", vol));
+ } else {
+ pjsua_perror(THIS_FILE, "Error setting volume", status);
+ }
+ }
+ break;
+
+ case 't':
+ {
+ pjmedia_aud_dev_route route;
+ pj_status_t status;
+
+ status = pjsua_snd_get_setting(PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE,
+ &route);
+
+ if (status == PJ_SUCCESS) {
+ if (route == PJMEDIA_AUD_DEV_ROUTE_LOUDSPEAKER)
+ route = PJMEDIA_AUD_DEV_ROUTE_EARPIECE;
+ else
+ route = PJMEDIA_AUD_DEV_ROUTE_LOUDSPEAKER;
+
+ status = pjsua_snd_set_setting(
+ PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE,
+ &route, PJ_TRUE);
+ }
+
+ if (status != PJ_SUCCESS)
+ pjsua_perror(THIS_FILE, "Error switch audio route", status);
+ }
+ break;
+
+ case 'j':
+ {
+ static pj_bool_t loopback_active = PJ_FALSE;
+ if (!loopback_active)
+ pjsua_conf_connect(0, 0);
+ else
+ pjsua_conf_disconnect(0, 0);
+ loopback_active = !loopback_active;
+ }
+ break;
+
+ case 'm':
+ if (g_call_id != PJSUA_INVALID_ID) {
+ PJ_LOG(3,(THIS_FILE, "Another call is active"));
+ break;
+ }
+
+ if (pjsua_verify_url(SIP_DST_URI) == PJ_SUCCESS) {
+ pj_str_t dst = pj_str(SIP_DST_URI);
+ pjsua_call_make_call(g_acc_id, &dst, 0, NULL,
+ NULL, &g_call_id);
+ } else {
+ PJ_LOG(3,(THIS_FILE, "Invalid SIP URI"));
+ }
+ break;
+ case 'a':
+ if (g_call_id != PJSUA_INVALID_ID)
+ pjsua_call_answer(g_call_id, 200, NULL, NULL);
+ break;
+ case 'g':
+ pjsua_call_hangup_all();
+ break;
+ case 's':
+ case 'S':
+ if (g_buddy_id != PJSUA_INVALID_ID)
+ pjsua_buddy_subscribe_pres(g_buddy_id, kc=='s');
+ break;
+ case 'o':
+ case 'O':
+ pjsua_acc_set_online_status(g_acc_id, kc=='o');
+ break;
+
+ default:
+ PJ_LOG(3,(THIS_FILE, "Keycode '%c' (%d) is pressed", kc, kc));
+ break;
+ }
+
+ PrintMainMenu();
+}
+
+static void HandleCodecMenu(TKeyCode kc) {
+ const pj_str_t ID_ALL = {"*", 1};
+ pj_str_t codec = {NULL, 0};
+
+ if (kc == 'a') {
+ pjsua_codec_set_priority(&ID_ALL, PJMEDIA_CODEC_PRIO_NORMAL);
+ PJ_LOG(3,(THIS_FILE, "All codecs activated"));
+ } else {
+ switch (kc) {
+ case 'd':
+ codec = pj_str("AMR");
+ break;
+ case 'g':
+ codec = pj_str("G729");
+ break;
+ case 'j':
+ codec = pj_str("ILBC");
+ break;
+ case 'm':
+ codec = pj_str("SPEEX/8000");
+ break;
+ case 'p':
+ codec = pj_str("GSM");
+ break;
+ case 't':
+ codec = pj_str("PCMU");
+ break;
+ case 'w':
+ codec = pj_str("PCMA");
+ break;
+ default:
+ PJ_LOG(3,(THIS_FILE, "Keycode '%c' (%d) is pressed", kc, kc));
+ break;
+ }
+
+ if (codec.slen) {
+ pj_status_t status;
+
+ pjsua_codec_set_priority(&ID_ALL, PJMEDIA_CODEC_PRIO_DISABLED);
+
+ status = pjsua_codec_set_priority(&codec,
+ PJMEDIA_CODEC_PRIO_NORMAL);
+ if (status == PJ_SUCCESS)
+ PJ_LOG(3,(THIS_FILE, "%s activated", codec.ptr));
+ else
+ PJ_LOG(3,(THIS_FILE, "Failed activating %s, err=%d",
+ codec.ptr, status));
+ }
+ }
+}
+
+// Implementation: called when read has completed.
+void ConsoleUI::RunL()
+{
+ enum {
+ MENU_TYPE_MAIN = 0,
+ MENU_TYPE_CODEC = 1
+ };
+ static int menu_type = MENU_TYPE_MAIN;
+ TKeyCode kc = con_->KeyCode();
+ pj_bool_t reschedule = PJ_TRUE;
+
+ if (menu_type == MENU_TYPE_MAIN) {
+ if (kc == 'w') {
+ CActiveScheduler::Stop();
+ reschedule = PJ_FALSE;
+ } else if (kc == 'd') {
+ menu_type = MENU_TYPE_CODEC;
+ PrintCodecMenu();
+ } else {
+ HandleMainMenu(kc);
+ }
+ } else {
+ HandleCodecMenu(kc);
+
+ menu_type = MENU_TYPE_MAIN;
+ PrintMainMenu();
+ }
+
+ if (reschedule)
+ Run();
+}
+
+#if 0
+// IP networking related testing
+static pj_status_t test_addr(void)
+{
+ int af;
+ unsigned i, count;
+ pj_addrinfo ai[8];
+ pj_sockaddr ifs[8];
+ const pj_str_t *hostname;
+ pj_hostent he;
+ pj_status_t status;
+
+ pj_log_set_log_func(&log_writer);
+
+ status = pj_init();
+ if (status != PJ_SUCCESS) {
+ pjsua_perror(THIS_FILE, "pj_init() error", status);
+ return status;
+ }
+
+ af = pj_AF_INET();
+
+#if 0
+ pj_in_addr in_addr;
+ pj_str_t aa = pj_str("1.1.1.1");
+ in_addr = pj_inet_addr(&aa);
+ char *the_addr = pj_inet_ntoa(in_addr);
+ PJ_LOG(3,(THIS_FILE, "IP addr=%s", the_addr));
+
+ aa = pj_str("192.168.0.15");
+ in_addr = pj_inet_addr(&aa);
+ the_addr = pj_inet_ntoa(in_addr);
+ PJ_LOG(3,(THIS_FILE, "IP addr=%s", the_addr));
+
+ aa = pj_str("2.2.2.2");
+ in_addr = pj_inet_addr(&aa);
+ the_addr = pj_inet_ntoa(in_addr);
+ PJ_LOG(3,(THIS_FILE, "IP addr=%s", the_addr));
+
+ return -1;
+#endif
+
+ // Hostname
+ hostname = pj_gethostname();
+ if (hostname == NULL) {
+ status = PJ_ERESOLVE;
+ pjsua_perror(THIS_FILE, "pj_gethostname() error", status);
+ goto on_return;
+ }
+
+ PJ_LOG(3,(THIS_FILE, "Hostname: %.*s", hostname->slen, hostname->ptr));
+
+ // Gethostbyname
+ status = pj_gethostbyname(hostname, &he);
+ if (status != PJ_SUCCESS) {
+ pjsua_perror(THIS_FILE, "pj_gethostbyname() error", status);
+ } else {
+ PJ_LOG(3,(THIS_FILE, "gethostbyname: %s",
+ pj_inet_ntoa(*(pj_in_addr*)he.h_addr)));
+ }
+
+ // Getaddrinfo
+ count = PJ_ARRAY_SIZE(ai);
+ status = pj_getaddrinfo(af, hostname, &count, ai);
+ if (status != PJ_SUCCESS) {
+ pjsua_perror(THIS_FILE, "pj_getaddrinfo() error", status);
+ } else {
+ for (i=0; i<count; ++i) {
+ char ipaddr[PJ_INET6_ADDRSTRLEN+2];
+ PJ_LOG(3,(THIS_FILE, "Addrinfo: %s",
+ pj_sockaddr_print(&ai[i].ai_addr, ipaddr, sizeof(ipaddr), 2)));
+ }
+ }
+
+ // Enum interface
+ count = PJ_ARRAY_SIZE(ifs);
+ status = pj_enum_ip_interface(af, &count, ifs);
+ if (status != PJ_SUCCESS) {
+ pjsua_perror(THIS_FILE, "pj_enum_ip_interface() error", status);
+ } else {
+ for (i=0; i<count; ++i) {
+ char ipaddr[PJ_INET6_ADDRSTRLEN+2];
+ PJ_LOG(3,(THIS_FILE, "Interface: %s",
+ pj_sockaddr_print(&ifs[i], ipaddr, sizeof(ipaddr), 2)));
+ }
+ }
+
+ // Get default iinterface
+ status = pj_getdefaultipinterface(af, &ifs[0]);
+ if (status != PJ_SUCCESS) {
+ pjsua_perror(THIS_FILE, "pj_getdefaultipinterface() error", status);
+ } else {
+ char ipaddr[PJ_INET6_ADDRSTRLEN+2];
+ PJ_LOG(3,(THIS_FILE, "Default IP: %s",
+ pj_sockaddr_print(&ifs[0], ipaddr, sizeof(ipaddr), 2)));
+ }
+
+ // Get default IP address
+ status = pj_gethostip(af, &ifs[0]);
+ if (status != PJ_SUCCESS) {
+ pjsua_perror(THIS_FILE, "pj_gethostip() error", status);
+ } else {
+ char ipaddr[PJ_INET6_ADDRSTRLEN+2];
+ PJ_LOG(3,(THIS_FILE, "Host IP: %s",
+ pj_sockaddr_print(&ifs[0], ipaddr, sizeof(ipaddr), 2)));
+ }
+
+ status = -1;
+
+on_return:
+ pj_shutdown();
+ return status;
+}
+#endif
+
+
+#include <es_sock.h>
+
+#if 0
+// Force network connection to use the first IAP,
+// this is useful for debugging on emulator without GUI.
+// Include commdb.lib & apengine.lib in symbian_ua.mmp file
+// if this is enabled.
+
+#include <apdatahandler.h>
+
+inline void ForceUseFirstIAP()
+{
+ TUint32 rank = 1;
+ TUint32 bearers;
+ TUint32 prompt;
+ TUint32 iap;
+
+ CCommsDatabase* commDb = CCommsDatabase::NewL(EDatabaseTypeIAP);
+ CleanupStack::PushL(commDb);
+
+ CApDataHandler* apDataHandler = CApDataHandler::NewLC(*commDb);
+
+ TCommDbConnectionDirection direction = ECommDbConnectionDirectionOutgoing;
+ apDataHandler->GetPreferredIfDbIapTypeL(rank, direction, bearers, prompt, iap);
+ prompt = ECommDbDialogPrefDoNotPrompt;
+ apDataHandler->SetPreferredIfDbIapTypeL(rank, direction, bearers, (TCommDbDialogPref)prompt, iap, ETrue);
+ CleanupStack::PopAndDestroy(2); // apDataHandler, commDb
+}
+
+static void SelectIAP()
+{
+ ForceUseFirstIAP();
+}
+
+#else
+
+static void SelectIAP()
+{
+}
+
+#endif
+
+
+// Class CConnMon to monitor network connection (RConnection). Whenever
+// the connection is down, it will notify PJLIB and restart PJSUA-LIB.
+class CConnMon : public CActive {
+public:
+ static CConnMon* NewL(RConnection &conn, RSocketServ &sserver) {
+ CConnMon *self = new (ELeave) CConnMon(conn, sserver);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+ void Start() {
+ conn_.ProgressNotification(nif_progress_, iStatus);
+ SetActive();
+ }
+
+ void Stop() {
+ Cancel();
+ }
+
+ ~CConnMon() { Stop(); }
+
+private:
+ CConnMon(RConnection &conn, RSocketServ &sserver) :
+ CActive(EPriorityHigh),
+ conn_(conn),
+ sserver_(sserver)
+ {
+ CActiveScheduler::Add(this);
+ }
+
+ void ConstructL() {}
+
+ void DoCancel() {
+ conn_.CancelProgressNotification();
+ }
+
+ void RunL() {
+ int stage = nif_progress_().iStage;
+
+ if (stage == KLinkLayerClosed) {
+ pj_status_t status;
+ TInt err;
+
+ // Tell pjlib that connection is down.
+ pj_symbianos_set_connection_status(PJ_FALSE);
+
+ PJ_LOG(3, (THIS_FILE, "RConnection closed, restarting PJSUA.."));
+
+ // Destroy pjsua
+ pjsua_destroy();
+ PJ_LOG(3, (THIS_FILE, "PJSUA destroyed."));
+
+ // Reopen the connection
+ err = conn_.Open(sserver_);
+ if (err == KErrNone)
+ err = conn_.Start();
+ if (err != KErrNone) {
+ CActiveScheduler::Stop();
+ return;
+ }
+
+ // Reinit Symbian OS param before pj_init()
+ pj_symbianos_params sym_params;
+ pj_bzero(&sym_params, sizeof(sym_params));
+ sym_params.rsocketserv = &sserver_;
+ sym_params.rconnection = &conn_;
+ pj_symbianos_set_params(&sym_params);
+
+ // Reinit pjsua
+ status = app_startup();
+ if (status != PJ_SUCCESS) {
+ pjsua_perror(THIS_FILE, "app_startup() error", status);
+ CActiveScheduler::Stop();
+ return;
+ }
+
+ PJ_LOG(3, (THIS_FILE, "PJSUA restarted."));
+ PrintMainMenu();
+ }
+
+ Start();
+ }
+
+ RConnection& conn_;
+ RSocketServ& sserver_;
+ TNifProgressBuf nif_progress_;
+};
+
+////////////////////////////////////////////////////////////////////////////
+int ua_main()
+{
+ RSocketServ aSocketServer;
+ RConnection aConn;
+ TInt err;
+ pj_symbianos_params sym_params;
+ pj_status_t status;
+
+ SelectIAP();
+
+ // Initialize RSocketServ
+ if ((err=aSocketServer.Connect(32)) != KErrNone)
+ return PJ_STATUS_FROM_OS(err);
+
+ // Open up a connection
+ if ((err=aConn.Open(aSocketServer)) != KErrNone) {
+ aSocketServer.Close();
+ return PJ_STATUS_FROM_OS(err);
+ }
+
+ if ((err=aConn.Start()) != KErrNone) {
+ aSocketServer.Close();
+ return PJ_STATUS_FROM_OS(err);
+ }
+
+ // Set Symbian OS parameters in pjlib.
+ // This must be done before pj_init() is called.
+ pj_bzero(&sym_params, sizeof(sym_params));
+ sym_params.rsocketserv = &aSocketServer;
+ sym_params.rconnection = &aConn;
+ pj_symbianos_set_params(&sym_params);
+
+ // Initialize pjsua
+ status = app_startup();
+ //status = test_addr();
+ if (status != PJ_SUCCESS) {
+ aConn.Close();
+ aSocketServer.Close();
+ return status;
+ }
+
+
+ // Run the UI
+ ConsoleUI *con = new ConsoleUI(console);
+
+ con->Run();
+ PrintMainMenu();
+
+ // Init & start connection monitor
+ CConnMon *connmon = CConnMon::NewL(aConn, aSocketServer);
+ connmon->Start();
+
+ CActiveScheduler::Start();
+
+ delete connmon;
+ delete con;
+
+ // Dump memory statistics
+ PJ_LOG(3,(THIS_FILE, "Max heap usage: %u.%03uMB",
+ pjsua_var.cp.peak_used_size / 1000000,
+ (pjsua_var.cp.peak_used_size % 1000000)/1000));
+
+ // check max stack usage
+#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0
+ pj_thread_t* this_thread = pj_thread_this();
+ if (!this_thread)
+ return status;
+
+ const char* max_stack_file;
+ int max_stack_line;
+ status = pj_thread_get_stack_info(this_thread, &max_stack_file, &max_stack_line);
+
+ PJ_LOG(3,(THIS_FILE, "Max stack usage: %u at %s:%d",
+ pj_thread_get_stack_max_usage(this_thread),
+ max_stack_file, max_stack_line));
+#endif
+
+ // Shutdown pjsua
+ pjsua_destroy();
+
+ // Close connection and socket server
+ aConn.Close();
+ aSocketServer.Close();
+
+ return status;
+}
+
diff --git a/pjsip-apps/src/symbian_ua/ua.h b/pjsip-apps/src/symbian_ua/ua.h
new file mode 100644
index 0000000..51a4a63
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua/ua.h
@@ -0,0 +1,24 @@
+/* $Id: ua.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <e32cons.h>
+
+extern CConsoleBase* console;
+
+int ua_main();
diff --git a/pjsip-apps/src/symbian_ua_gui/application.uidesign b/pjsip-apps/src/symbian_ua_gui/application.uidesign
new file mode 100644
index 0000000..abe5c5a
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/application.uidesign
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<designerData version="1.1.0">
+ <componentManifest>
+ <manifestEntry id="com.nokia.sdt.series60.CAknApplication" version="1.1.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.NonLayoutBase" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.CAknDocument" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.CAknViewAppUi" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.CAknAppUi" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.CAknAppUiBase" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.DesignTimeContainer" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.StatusPane" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.ControlBase" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.StatusPaneCaption" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.StatusPaneTitleBase" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.CBA" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.CBABase" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.AvkonViewReference" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.DesignReference" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.WaitDialog" version="1.0.0"/>
+ </componentManifest>
+ <property id="com.nokia.sdt.symbian.dm.RESOURCE_DIRECTORY_ID">data</property>
+ <property id="com.nokia.sdt.component.symbian.vendor">com.nokia.series60</property>
+ <property id="com.nokia.sdt.component.symbian.version">3.0.1</property>
+ <property id="com.nokia.sdt.symbian.dm.COMPONENT_PROVIDER">com.nokia.sdt.component.symbian.Symbian-Provider</property>
+ <property id="com.nokia.sdt.symbian.dm.INCLUDE_DIRECTORY_ID">inc</property>
+ <property id="com.nokia.sdt.symbian.dm.ROOT_CONTAINER">symbian_ua_guiAppUi</property>
+ <property id="com.nokia.sdt.symbian.dm.SOURCE_DIRECTORY_ID">src</property>
+ <property id="com.nokia.sdt.symbian.dm.LOCALIZED_FILE_FORMAT">loc</property>
+ <property id="com.nokia.sdt.symbian.dm.ROOT_APPLICATION_NAME">symbian_ua_gui</property>
+ <property id="com.nokia.sdt.symbian.dm.SOURCEGEN_PROVIDER">com.nokia.sdt.sourcegen.Symbian-Provider</property>
+ <property id="com.nokia.sdt.symbian.dm.BUILD_DIRECTORY_ID">group</property>
+ <component id="com.nokia.sdt.series60.CAknApplication">
+ <property id="className">Csymbian_ua_guiApplication</property>
+ <property id="documentBase">symbian_ua_gui</property>
+ <property id="name">symbian_ua_guiApplication</property>
+ <property id="uid">0xEBD12EE4</property>
+ <component id="com.nokia.sdt.series60.CAknDocument">
+ <property id="className">Csymbian_ua_guiDocument</property>
+ <property id="name">symbian_ua_guiDocument</property>
+ <component id="com.nokia.sdt.series60.CAknViewAppUi">
+ <property id="initialDesign" type="componentRef">aknViewReference2</property>
+ <property id="className">Csymbian_ua_guiAppUi</property>
+ <compoundProperty id="location">
+ <property id="x">52</property>
+ <property id="y">45</property>
+ </compoundProperty>
+ <property id="name">symbian_ua_guiAppUi</property>
+ <compoundProperty id="size">
+ <property id="width">240</property>
+ <property id="height">320</property>
+ </compoundProperty>
+ <component id="com.nokia.sdt.series60.StatusPane">
+ <compoundProperty id="location">
+ <property id="x">20</property>
+ </compoundProperty>
+ <property id="name">statusPane</property>
+ <compoundProperty id="size">
+ <property id="width">204</property>
+ <property id="height">66</property>
+ </compoundProperty>
+ <component id="com.nokia.sdt.series60.StatusPaneCaption">
+ <property id="shortCaption" type="i18n">STR_symbian_ua_guiApplication_2</property>
+ <compoundProperty id="location">
+ <property id="x">56</property>
+ </compoundProperty>
+ <property id="longCaption" type="i18n">STR_symbian_ua_guiApplication_1</property>
+ <property id="name">caption</property>
+ <compoundProperty id="size">
+ <property id="width">148</property>
+ <property id="height">43</property>
+ </compoundProperty>
+ </component>
+ </component>
+ <component id="com.nokia.sdt.series60.CBA">
+ <compoundProperty id="location">
+ <property id="y">288</property>
+ </compoundProperty>
+ <compoundProperty id="info"/>
+ <property id="name">controlPane</property>
+ <compoundProperty id="size">
+ <property id="width">240</property>
+ <property id="height">32</property>
+ </compoundProperty>
+ </component>
+ <component id="com.nokia.sdt.series60.AvkonViewReference">
+ <property id="filePath">symbian_ua_guiContainer.uidesign</property>
+ <property id="baseName">symbian_ua_guiContainer</property>
+ <compoundProperty id="tabImage"/>
+ <property id="name">aknViewReference1</property>
+ </component>
+ <component id="com.nokia.sdt.series60.AvkonViewReference">
+ <property id="filePath">symbian_ua_guiSettingItemList.uidesign</property>
+ <property id="baseName">symbian_ua_guiSettingItemList</property>
+ <compoundProperty id="tabImage"/>
+ <property id="name">aknViewReference2</property>
+ </component>
+ <component id="com.nokia.sdt.series60.WaitDialog">
+ <compoundProperty id="location">
+ <property id="x">0</property>
+ <property id="y">171</property>
+ </compoundProperty>
+ <property id="name">dlg_wait_init</property>
+ <property id="text" type="i18n">STR_symbian_ua_guiApplication_3</property>
+ <compoundProperty id="size">
+ <property id="width">240</property>
+ <property id="height">149</property>
+ </compoundProperty>
+ <eventBinding id="canceled" handlerDisplay="HandleDlg_wait_initCanceledL" handlerSymbol="cpp@src//symbian_ua_guiAppUi.cpp/function(Csymbian_ua_guiAppUi::HandleDlg_wait_initCanceledL(CAknProgressDialog*))"/>
+ </component>
+ </component>
+ </component>
+ </component>
+ <stringBundle>
+ <stringTable language="LANG_English">
+ <string id="STR_symbian_ua_guiApplication_1">symbian_ua_gui</string>
+ <string id="STR_symbian_ua_guiApplication_2">symbian_ua_gui</string>
+ <string id="STR_symbian_ua_guiApplication_3">Please wait...</string>
+ </stringTable>
+ </stringBundle>
+ <macroTable/>
+ <sourceMappingState>
+ <resourceMappings>
+ <resourceMapping instanceName="symbian_ua_guiAppUi">r_application_symbian_ua_gui_app_ui</resourceMapping>
+ <resourceMapping instanceName="statusPane">r_application_status_pane</resourceMapping>
+ <resourceMapping instanceName="aknViewReference2" rsrcId="tabText">r_application_akn_view_reference2</resourceMapping>
+ <resourceMapping instanceName="dlg_wait_init">r_application_dlg_wait_init</resourceMapping>
+ <resourceMapping instanceName="symbian_ua_guiAppUi" rsrcId="localisable_app_info">r_localisable_app_info</resourceMapping>
+ <resourceMapping instanceName="aknViewReference1" rsrcId="tabText">r_application_akn_view_reference1</resourceMapping>
+ </resourceMappings>
+ <enumMappings>
+ <enumMapping instanceName="aknViewReference2" propertyId="" nameAlgorithm="com.nokia.sdt.component.symbian.NAME_ALG_VIEW_UID">ESymbian_ua_guiSettingItemListViewId</enumMapping>
+ <enumMapping instanceName="dlg_wait_init" propertyId="" nameAlgorithm="com.nokia.sdt.component.symbian.NAME_ALG_DIALOG_LINE_ID">ESymbian_ua_guiApplicationDlg_wait_init</enumMapping>
+ <enumMapping instanceName="aknViewReference1" propertyId="" nameAlgorithm="com.nokia.sdt.component.symbian.NAME_ALG_VIEW_UID">ESymbian_ua_guiContainerViewId</enumMapping>
+ </enumMappings>
+ <arrayMappings/>
+ </sourceMappingState>
+ <generatedFiles>
+ <file>src/symbian_ua_guiAppUi.cpp</file>
+ <file>src/symbian_ua_guiDocument.cpp</file>
+ <file>inc/symbian_ua_guiApplication.h</file>
+ <file>src/symbian_ua_guiApplication.cpp</file>
+ <file>inc/symbian_ua_guiAppUi.h</file>
+ <file>inc/symbian_ua_guiDocument.h</file>
+ <file>data/symbian_ua_gui.rss</file>
+ <file>data/symbian_ua_guiContainer.rssi</file>
+ <file>inc/symbian_ua_gui.hrh</file>
+ <file>inc/symbian_ua_guiContainer.hrh</file>
+ <file>data/symbian_ua_guiSettingItemList.rssi</file>
+ <file>inc/symbian_ua_guiSettingItemList.hrh</file>
+ <file>data/symbian_ua_gui.loc</file>
+ <file>data/symbian_ua_gui.l01</file>
+ <file>data/symbian_ua_guiContainer.loc</file>
+ <file>data/symbian_ua_guiContainer.l01</file>
+ <file>data/symbian_ua_guiSettingItemList.loc</file>
+ <file>data/symbian_ua_guiSettingItemList.l01</file>
+ </generatedFiles>
+</designerData>
diff --git a/pjsip-apps/src/symbian_ua_gui/data/symbian_ua_gui.l01 b/pjsip-apps/src/symbian_ua_gui/data/symbian_ua_gui.l01
new file mode 100644
index 0000000..c2a8140
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/data/symbian_ua_gui.l01
@@ -0,0 +1,12 @@
+/*
+========================================================================
+ Name : symbian_ua_gui.l01
+ Author : nanang
+ Copyright : (c) PJSIP 2008
+ Description :
+========================================================================
+*/
+// localized strings for language: UK English (01)
+#define STR_symbian_ua_guiApplication_1 "symbian_ua_gui"
+#define STR_symbian_ua_guiApplication_2 "symbian_ua_gui"
+#define STR_symbian_ua_guiApplication_3 "Please wait..."
diff --git a/pjsip-apps/src/symbian_ua_gui/data/symbian_ua_gui.loc b/pjsip-apps/src/symbian_ua_gui/data/symbian_ua_gui.loc
new file mode 100644
index 0000000..d13671e
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/data/symbian_ua_gui.loc
@@ -0,0 +1,11 @@
+/*
+========================================================================
+ Name : symbian_ua_gui.loc
+ Author : nanang
+ Copyright : (c) PJSIP 2008
+ Description :
+========================================================================
+*/
+#ifdef LANGUAGE_01
+#include "symbian_ua_gui.l01"
+#endif
diff --git a/pjsip-apps/src/symbian_ua_gui/data/symbian_ua_gui.rss b/pjsip-apps/src/symbian_ua_gui/data/symbian_ua_gui.rss
new file mode 100644
index 0000000..c502c33
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/data/symbian_ua_gui.rss
@@ -0,0 +1,71 @@
+/*
+========================================================================
+ Name : symbian_ua_gui.rss
+ Author : nanang
+ Copyright : (c) PJSIP 2008
+ Description :
+========================================================================
+*/
+NAME SYMB
+
+#include <avkon.rsg>
+#include <avkon.rh>
+#include <eikon.rh>
+#include <appinfo.rh>
+#include "symbian_ua_gui.hrh"
+#include "symbian_ua_gui.loc"
+
+RESOURCE RSS_SIGNATURE
+ {
+ }
+RESOURCE TBUF
+ {
+ buf = "symbian_ua_gui";
+ }
+RESOURCE EIK_APP_INFO r_application_symbian_ua_gui_app_ui
+ {
+ cba = R_AVKON_SOFTKEYS_OPTIONS_EXIT;
+ status_pane = r_application_status_pane;
+ }
+RESOURCE STATUS_PANE_APP_MODEL r_application_status_pane
+ {
+ }
+RESOURCE LOCALISABLE_APP_INFO r_localisable_app_info
+ {
+ short_caption = STR_symbian_ua_guiApplication_2;
+ caption_and_icon = CAPTION_AND_ICON_INFO
+ {
+ caption = STR_symbian_ua_guiApplication_1;
+ number_of_icons = 0;
+ };
+ }
+RESOURCE TBUF r_application_akn_view_reference1
+ {
+ }
+
+RESOURCE TBUF r_application_akn_view_reference2
+ {
+ }
+
+RESOURCE DIALOG r_application_dlg_wait_init
+ {
+ flags = EAknWaitNoteFlags;
+ buttons = R_AVKON_SOFTKEYS_CANCEL;
+ items =
+ {
+ DLG_LINE
+ {
+ type = EAknCtNote;
+ id = ESymbian_ua_guiApplicationDlg_wait_init;
+ control = AVKON_NOTE
+ {
+ layout = EWaitLayout;
+ singular_label = STR_symbian_ua_guiApplication_3;
+ animation = R_QGN_GRAF_WAIT_BAR_ANIM;
+ };
+ }
+ };
+ }
+
+#include "symbian_ua_guiContainer.rssi"
+#include "symbian_ua_guiSettingItemList.rssi"
diff --git a/pjsip-apps/src/symbian_ua_gui/data/symbian_ua_guiContainer.l01 b/pjsip-apps/src/symbian_ua_gui/data/symbian_ua_guiContainer.l01
new file mode 100644
index 0000000..ddf47ce
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/data/symbian_ua_guiContainer.l01
@@ -0,0 +1,21 @@
+/*
+========================================================================
+ Name : symbian_ua_guiContainer.l01
+ Author : nanang
+ Copyright : (c) PJSIP 2008
+ Description :
+========================================================================
+*/
+// localized strings for language: UK English (01)
+#define STR_symbian_ua_guiContainerView_1 "PJSUA for S60"
+#define STR_symbian_ua_guiContainerView_7 "Options"
+#define STR_symbian_ua_guiContainerView_8 "Call"
+#define STR_symbian_ua_guiContainerView_2 "URL"
+#define STR_symbian_ua_guiContainerView_4 "sip:"
+#define STR_symbian_ua_guiContainerView_9 "Setting"
+#define STR_symbian_ua_guiContainerView_10 "Exit"
+#define STR_symbian_ua_guiContainerView_3 ""
+#define STR_symbian_ua_guiContainerView_13 "Failed initializing PJSUA!"
+#define STR_symbian_ua_guiContainerView_16 "Register Success"
+#define STR_symbian_ua_guiContainerView_17 "Register Failed"
+#define STR_symbian_ua_guiContainerView_18 "Accept Call"
diff --git a/pjsip-apps/src/symbian_ua_gui/data/symbian_ua_guiContainer.loc b/pjsip-apps/src/symbian_ua_gui/data/symbian_ua_guiContainer.loc
new file mode 100644
index 0000000..7cf063f
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/data/symbian_ua_guiContainer.loc
@@ -0,0 +1,11 @@
+/*
+========================================================================
+ Name : symbian_ua_guiContainer.loc
+ Author : nanang
+ Copyright : (c) PJSIP 2008
+ Description :
+========================================================================
+*/
+#ifdef LANGUAGE_01
+#include "symbian_ua_guiContainer.l01"
+#endif
diff --git a/pjsip-apps/src/symbian_ua_gui/data/symbian_ua_guiContainer.rssi b/pjsip-apps/src/symbian_ua_gui/data/symbian_ua_guiContainer.rssi
new file mode 100644
index 0000000..5419289
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/data/symbian_ua_guiContainer.rssi
@@ -0,0 +1,141 @@
+/*
+========================================================================
+ Name : symbian_ua_guiContainer.rssi
+ Author : nanang
+ Copyright : (c) PJSIP 2008
+ Description :
+========================================================================
+*/
+#include "symbian_ua_guiContainer.hrh"
+#include "symbian_ua_guiContainer.loc"
+
+RESOURCE AVKON_VIEW r_symbian_ua_gui_container_symbian_ua_gui_container_view
+ {
+ cba = r_symbian_ua_gui_container_control_pane;
+ menubar = r_symbian_ua_gui_container_options_menu;
+ }
+RESOURCE MENU_BAR r_symbian_ua_gui_container_options_menu
+ {titles =
+ {
+ MENU_TITLE
+ {
+ menu_pane = r_symbian_ua_gui_container_menu_pane1_menu_pane;
+ }
+ };
+
+ }
+RESOURCE STATUS_PANE_APP_MODEL r_symbian_ua_gui_container_status_pane
+ {
+ panes =
+ {
+ SPANE_PANE
+ {
+ id = EEikStatusPaneUidTitle;
+ type = EAknCtTitlePane;
+ resource = r_symbian_ua_gui_container_title_resource;
+ }
+ };
+ }
+RESOURCE TITLE_PANE r_symbian_ua_gui_container_title_resource
+ {
+ txt = STR_symbian_ua_guiContainerView_1;
+ }
+RESOURCE CBA r_symbian_ua_gui_container_control_pane
+ {
+ buttons =
+ {
+ CBA_BUTTON
+ {
+ id = EAknSoftkeyOptions;
+ txt = STR_symbian_ua_guiContainerView_7;
+ },
+ CBA_BUTTON
+ {
+ id = ESymbian_ua_guiContainerViewControlPaneRightId;
+ txt = STR_symbian_ua_guiContainerView_8;
+ }
+ };
+ }
+RESOURCE LABEL r_symbian_ua_gui_container_label1
+ {
+ txt = STR_symbian_ua_guiContainerView_2;
+ horiz_align = EEikLabelAlignHCenter;
+ }
+RESOURCE EDWIN r_symbian_ua_gui_container_ed_url
+ {
+ maxlength = 255;
+ default_case = EAknEditorLowerCase;
+ allowed_case_modes = EAknEditorAllCaseModes;
+ numeric_keymap = EAknEditorStandardNumberModeKeymap;
+ default_input_mode = EAknEditorTextInputMode;
+ allowed_input_modes = EAknEditorTextInputMode | EAknEditorNumericInputMode | EAknEditorSecretAlphaInputMode | EAknEditorFullWidthTextInputMode | EAknEditorFullWidthNumericInputMode | EAknEditorHalfWidthTextInputMode;
+ special_character_table = R_AVKON_URL_SPECIAL_CHARACTER_TABLE_DIALOG;
+ avkon_flags = EAknEditorFlagNoT9 | EAknEditorFlagSupressShiftMenu;
+ }
+RESOURCE TBUF r_symbian_ua_gui_container_ed_url_2
+ {
+ buf = STR_symbian_ua_guiContainerView_4;
+ }
+RESOURCE MENU_PANE r_symbian_ua_gui_container_menu_pane1_menu_pane
+ {
+ items =
+ {
+ MENU_ITEM
+ {
+ command = ESymbian_ua_guiContainerViewSettingMenuItemCommand;
+ txt = STR_symbian_ua_guiContainerView_9;
+ },
+ MENU_ITEM
+ {
+ command = EAknCmdExit;
+ txt = STR_symbian_ua_guiContainerView_10;
+ }
+ };
+ }
+RESOURCE EDWIN r_symbian_ua_gui_container_ed_info
+ {
+ flags = EEikEdwinReadOnly;
+ lines = 10;
+ maxlength = 2000;
+ default_case = EAknEditorTextCase;
+ allowed_case_modes = EAknEditorAllCaseModes;
+ numeric_keymap = EAknEditorStandardNumberModeKeymap;
+ default_input_mode = EAknEditorTextInputMode;
+ allowed_input_modes = EAknEditorTextInputMode | EAknEditorNumericInputMode | EAknEditorSecretAlphaInputMode | EAknEditorKatakanaInputMode | EAknEditorFullWidthTextInputMode | EAknEditorFullWidthNumericInputMode | EAknEditorFullWidthKatakanaInputMode | EAknEditorHiraganaKanjiInputMode | EAknEditorHalfWidthTextInputMode;
+ avkon_flags = EAknEditorFlagNoEditIndicators | EAknEditorFlagEnableScrollBars;
+ special_character_table = 0;
+ }
+RESOURCE TBUF r_symbian_ua_gui_container_ed_info_2
+ {
+ buf = STR_symbian_ua_guiContainerView_3;
+ }
+RESOURCE TBUF r_symbian_ua_gui_container_note_error
+ {
+ buf = STR_symbian_ua_guiContainerView_13;
+ }
+RESOURCE TBUF r_symbian_ua_gui_container_note_info
+ {
+ buf = STR_symbian_ua_guiContainerView_16;
+ }
+RESOURCE TBUF r_symbian_ua_gui_container_note_warning
+ {
+ buf = STR_symbian_ua_guiContainerView_17;
+ }
+RESOURCE DIALOG r_symbian_ua_gui_container_qry_accept_call
+ {
+ flags = EAknGeneralQueryFlags;
+ buttons = R_AVKON_SOFTKEYS_YES_NO;
+ items =
+ {
+ DLG_LINE
+ {
+ type = EAknCtQuery;
+ id = ESymbian_ua_guiContainerViewQry_accept_call;
+ control = AVKON_CONFIRMATION_QUERY
+ {
+ layout = EConfirmationQueryLayout;
+ label = STR_symbian_ua_guiContainerView_18;
+ };
+ }
+ };
+ }
diff --git a/pjsip-apps/src/symbian_ua_gui/data/symbian_ua_guiSettingItemList.l01 b/pjsip-apps/src/symbian_ua_gui/data/symbian_ua_guiSettingItemList.l01
new file mode 100644
index 0000000..1f812f5
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/data/symbian_ua_guiSettingItemList.l01
@@ -0,0 +1,31 @@
+/*
+========================================================================
+ Name : symbian_ua_guiSettingItemList.l01
+ Author : nanang
+ Copyright : (c) PJSIP 2008
+ Description :
+========================================================================
+*/
+// localized strings for language: UK English (01)
+#define STR_symbian_ua_guiSettingItemListView_1 "Settings"
+#define STR_symbian_ua_guiSettingItemListView_2 "Account Settings"
+#define STR_symbian_ua_guiSettingItemListView_4 "Change"
+#define STR_symbian_ua_guiSettingItemListView_16 "Password"
+#define STR_symbian_ua_guiSettingItemListView_18 ""
+#define STR_symbian_ua_guiSettingItemListView_19 "STUN Server"
+#define STR_symbian_ua_guiSettingItemListView_24 "SRTP"
+#define STR_symbian_ua_guiSettingItemListView_25 "On"
+#define STR_symbian_ua_guiSettingItemListView_26 "Popup text for On"
+#define STR_symbian_ua_guiSettingItemListView_27 "Off"
+#define STR_symbian_ua_guiSettingItemListView_28 "Popup text for Off"
+#define STR_symbian_ua_guiSettingItemListView_3 ""
+#define STR_symbian_ua_guiSettingItemListView_5 "Registrar"
+#define STR_symbian_ua_guiSettingItemListView_7 ""
+#define STR_symbian_ua_guiSettingItemListView_8 "User"
+#define STR_symbian_ua_guiSettingItemListView_46 "ICE"
+#define STR_symbian_ua_guiSettingItemListView_47 "On"
+#define STR_symbian_ua_guiSettingItemListView_48 "Popup text for On"
+#define STR_symbian_ua_guiSettingItemListView_49 "Off"
+#define STR_symbian_ua_guiSettingItemListView_140 "Options"
+#define STR_symbian_ua_guiSettingItemListView_141 "Done"
+#define STR_symbian_ua_guiSettingItemListView_50 "Popup text for Off"
diff --git a/pjsip-apps/src/symbian_ua_gui/data/symbian_ua_guiSettingItemList.loc b/pjsip-apps/src/symbian_ua_gui/data/symbian_ua_guiSettingItemList.loc
new file mode 100644
index 0000000..c454d8f
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/data/symbian_ua_guiSettingItemList.loc
@@ -0,0 +1,11 @@
+/*
+========================================================================
+ Name : symbian_ua_guiSettingItemList.loc
+ Author : nanang
+ Copyright : (c) PJSIP 2008
+ Description :
+========================================================================
+*/
+#ifdef LANGUAGE_01
+#include "symbian_ua_guiSettingItemList.l01"
+#endif
diff --git a/pjsip-apps/src/symbian_ua_gui/data/symbian_ua_guiSettingItemList.rssi b/pjsip-apps/src/symbian_ua_gui/data/symbian_ua_guiSettingItemList.rssi
new file mode 100644
index 0000000..c8a4b30
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/data/symbian_ua_guiSettingItemList.rssi
@@ -0,0 +1,275 @@
+/*
+========================================================================
+ Name : symbian_ua_guiSettingItemList.rssi
+ Author : nanang
+ Copyright : (c) PJSIP 2008
+ Description :
+========================================================================
+*/
+#include "symbian_ua_guiSettingItemList.hrh"
+#include "symbian_ua_guiSettingItemList.loc"
+
+RESOURCE AVKON_VIEW r_symbian_ua_gui_setting_item_list_symbian_ua_gui_setting_item_list_view
+ {
+ cba = r_symbian_ua_gui_setting_item_list_control_pane;
+ menubar = r_symbian_ua_gui_setting_item_list_options_menu;
+ }
+RESOURCE MENU_BAR r_symbian_ua_gui_setting_item_list_options_menu
+ {
+ titles =
+ {
+ MENU_TITLE
+ {
+ menu_pane = r_symbian_ua_gui_setting_item_list_menu_pane1_menu_pane;
+ }
+ };
+ }
+RESOURCE MENU_PANE r_symbian_ua_gui_setting_item_list_menu_pane1_menu_pane
+ {
+ items =
+ {
+ MENU_ITEM
+ {
+ command = ESymbian_ua_guiSettingItemListViewMenuItem1Command;
+ txt = STR_symbian_ua_guiSettingItemListView_4;
+ }
+ };
+ }
+RESOURCE STATUS_PANE_APP_MODEL r_symbian_ua_gui_setting_item_list_status_pane
+ {
+ panes =
+ {
+ SPANE_PANE
+ {
+ id = EEikStatusPaneUidTitle;
+ type = EAknCtTitlePane;
+ resource = r_symbian_ua_gui_setting_item_list_title_resource;
+ }
+ };
+ }
+RESOURCE TITLE_PANE r_symbian_ua_gui_setting_item_list_title_resource
+ {
+ txt = STR_symbian_ua_guiSettingItemListView_2;
+ }
+RESOURCE AVKON_SETTING_ITEM_LIST r_symbian_ua_gui_setting_item_list_symbian_ua_gui_setting_item_list
+ {
+ items =
+ {
+ AVKON_SETTING_ITEM
+ {
+ name = STR_symbian_ua_guiSettingItemListView_5;
+ identifier = ESymbian_ua_guiSettingItemListViewEd_registrar;
+ setting_page_resource = r_symbian_ua_gui_setting_item_list_ed_registrar_setting_page_resource;
+ },
+ AVKON_SETTING_ITEM
+ {
+ name = STR_symbian_ua_guiSettingItemListView_8;
+ identifier = ESymbian_ua_guiSettingItemListViewEd_user;
+ setting_page_resource = r_symbian_ua_gui_setting_item_list_ed_user_setting_page_resource;
+ },
+ AVKON_SETTING_ITEM
+ {
+ name = STR_symbian_ua_guiSettingItemListView_16;
+ identifier = ESymbian_ua_guiSettingItemListViewEd_password;
+ setting_page_resource = r_symbian_ua_gui_setting_item_list_ed_password_setting_page_resource;
+ },
+ AVKON_SETTING_ITEM
+ {
+ name = STR_symbian_ua_guiSettingItemListView_24;
+ identifier = ESymbian_ua_guiSettingItemListViewB_srtp;
+ setting_page_resource = r_symbian_ua_gui_setting_item_list_b_srtp_setting_page_resource;
+ associated_resource = r_symbian_ua_gui_setting_item_list_b_srtp;
+ },
+ AVKON_SETTING_ITEM
+ {
+ name = STR_symbian_ua_guiSettingItemListView_46;
+ identifier = ESymbian_ua_guiSettingItemListViewB_ice;
+ setting_page_resource = r_symbian_ua_gui_setting_item_list_b_ice_setting_page_resource;
+ associated_resource = r_symbian_ua_gui_setting_item_list_b_ice;
+ },
+ AVKON_SETTING_ITEM
+ {
+ name = STR_symbian_ua_guiSettingItemListView_19;
+ identifier = ESymbian_ua_guiSettingItemListViewEd_stun_server;
+ setting_page_resource = r_symbian_ua_gui_setting_item_list_ed_stun_server_setting_page_resource;
+ }
+ };
+ }
+RESOURCE CBA r_symbian_ua_gui_setting_item_list_control_pane
+ {
+ buttons =
+ {
+ CBA_BUTTON
+ {
+ id = EAknSoftkeyOptions;
+ txt = STR_symbian_ua_guiSettingItemListView_140;
+ },
+ CBA_BUTTON
+ {
+ id = EAknSoftkeySave;
+ txt = STR_symbian_ua_guiSettingItemListView_141;
+ }
+ };
+ }
+RESOURCE AVKON_SETTING_PAGE r_symbian_ua_gui_setting_item_list_ed_registrar_setting_page_resource
+ {
+ number = -16380;
+ label = STR_symbian_ua_guiSettingItemListView_5;
+ type = EEikCtEdwin;
+ editor_resource_id = r_symbian_ua_gui_setting_item_list_ed_registrar_editor_resource_id;
+ }
+RESOURCE EDWIN r_symbian_ua_gui_setting_item_list_ed_registrar_editor_resource_id
+ {
+ maxlength = 255;
+ default_case = EAknEditorLowerCase;
+ allowed_case_modes = EAknEditorAllCaseModes;
+ numeric_keymap = EAknEditorStandardNumberModeKeymap;
+ default_input_mode = EAknEditorTextInputMode;
+ allowed_input_modes = EAknEditorTextInputMode | EAknEditorNumericInputMode | EAknEditorSecretAlphaInputMode | EAknEditorKatakanaInputMode | EAknEditorFullWidthTextInputMode | EAknEditorFullWidthNumericInputMode | EAknEditorFullWidthKatakanaInputMode | EAknEditorHiraganaKanjiInputMode | EAknEditorHalfWidthTextInputMode;
+ special_character_table = 0;
+ }
+RESOURCE AVKON_SETTING_PAGE r_symbian_ua_gui_setting_item_list_ed_user_setting_page_resource
+ {
+ number = -16380;
+ label = STR_symbian_ua_guiSettingItemListView_8;
+ type = EEikCtEdwin;
+ editor_resource_id = r_symbian_ua_gui_setting_item_list_ed_user_editor_resource_id;
+ }
+RESOURCE EDWIN r_symbian_ua_gui_setting_item_list_ed_user_editor_resource_id
+ {
+ maxlength = 255;
+ default_case = EAknEditorLowerCase;
+ allowed_case_modes = EAknEditorAllCaseModes;
+ numeric_keymap = EAknEditorStandardNumberModeKeymap;
+ default_input_mode = EAknEditorTextInputMode;
+ allowed_input_modes = EAknEditorTextInputMode | EAknEditorNumericInputMode | EAknEditorSecretAlphaInputMode | EAknEditorKatakanaInputMode | EAknEditorFullWidthTextInputMode | EAknEditorFullWidthNumericInputMode | EAknEditorFullWidthKatakanaInputMode | EAknEditorHiraganaKanjiInputMode | EAknEditorHalfWidthTextInputMode;
+ special_character_table = 0;
+ }
+RESOURCE AVKON_SETTING_PAGE r_symbian_ua_gui_setting_item_list_ed_password_setting_page_resource
+ {
+ number = -16380;
+ label = STR_symbian_ua_guiSettingItemListView_16;
+ type = EEikCtSecretEd;
+ editor_resource_id = r_symbian_ua_gui_setting_item_list_ed_password_editor_resource_id;
+ }
+RESOURCE SECRETED r_symbian_ua_gui_setting_item_list_ed_password_editor_resource_id
+ {num_letters = 32;
+
+ }
+RESOURCE AVKON_SETTING_PAGE r_symbian_ua_gui_setting_item_list_ed_stun_server_setting_page_resource
+ {
+ number = -16380;
+ label = STR_symbian_ua_guiSettingItemListView_19;
+ type = EEikCtEdwin;
+ editor_resource_id = r_symbian_ua_gui_setting_item_list_ed_stun_server_editor_resource_id;
+ }
+RESOURCE EDWIN r_symbian_ua_gui_setting_item_list_ed_stun_server_editor_resource_id
+ {
+ maxlength = 255;
+ default_case = EAknEditorTextCase;
+ allowed_case_modes = EAknEditorAllCaseModes;
+ numeric_keymap = EAknEditorStandardNumberModeKeymap;
+ default_input_mode = EAknEditorTextInputMode;
+ allowed_input_modes = EAknEditorTextInputMode | EAknEditorNumericInputMode | EAknEditorSecretAlphaInputMode | EAknEditorKatakanaInputMode | EAknEditorFullWidthTextInputMode | EAknEditorFullWidthNumericInputMode | EAknEditorFullWidthKatakanaInputMode | EAknEditorHiraganaKanjiInputMode | EAknEditorHalfWidthTextInputMode;
+ special_character_table = 0;
+ }
+RESOURCE AVKON_SETTING_PAGE r_symbian_ua_gui_setting_item_list_b_srtp_setting_page_resource
+ {
+ number = -16380;
+ label = STR_symbian_ua_guiSettingItemListView_24;
+ type = EAknCtPopupSettingList;
+ editor_resource_id = r_symbian_ua_gui_setting_item_list_b_srtp_editor_resource_id;
+ }
+RESOURCE POPUP_SETTING_LIST r_symbian_ua_gui_setting_item_list_b_srtp_editor_resource_id
+ {
+ }
+RESOURCE AVKON_POPUP_SETTING_TEXTS r_symbian_ua_gui_setting_item_list_b_srtp
+ {
+ setting_texts_resource = r_symbian_ua_gui_setting_item_list_b_srtp_setting_texts_resource;
+ popped_up_texts_resource = r_symbian_ua_gui_setting_item_list_b_srtp_popped_up_texts_resource;
+ }
+RESOURCE ARRAY r_symbian_ua_gui_setting_item_list_b_srtp_setting_texts_resource
+ {
+ items =
+ {
+ AVKON_ENUMERATED_TEXT
+ {
+ text = STR_symbian_ua_guiSettingItemListView_25;
+ value = 1;
+ },
+ AVKON_ENUMERATED_TEXT
+ {
+ text = STR_symbian_ua_guiSettingItemListView_27;
+ }
+ };
+ }
+RESOURCE ARRAY r_symbian_ua_gui_setting_item_list_b_srtp_popped_up_texts_resource
+ {
+ items =
+ {
+ LBUF
+ {
+ txt = STR_symbian_ua_guiSettingItemListView_26;
+ },
+ LBUF
+ {
+ txt = STR_symbian_ua_guiSettingItemListView_28;
+ }
+ };
+ }
+RESOURCE AVKON_SETTING_PAGE r_symbian_ua_gui_setting_item_list_b_ice_setting_page_resource
+ {
+ number = -16380;
+ label = STR_symbian_ua_guiSettingItemListView_46;
+ type = EAknCtPopupSettingList;
+ editor_resource_id = r_symbian_ua_gui_setting_item_list_b_ice_editor_resource_id;
+ }
+RESOURCE POPUP_SETTING_LIST r_symbian_ua_gui_setting_item_list_b_ice_editor_resource_id
+ {
+ }
+RESOURCE AVKON_POPUP_SETTING_TEXTS r_symbian_ua_gui_setting_item_list_b_ice
+ {
+ setting_texts_resource = r_symbian_ua_gui_setting_item_list_b_ice_setting_texts_resource;
+ popped_up_texts_resource = r_symbian_ua_gui_setting_item_list_b_ice_popped_up_texts_resource;
+ }
+RESOURCE ARRAY r_symbian_ua_gui_setting_item_list_b_ice_setting_texts_resource
+ {
+ items =
+ {
+ AVKON_ENUMERATED_TEXT
+ {
+ text = STR_symbian_ua_guiSettingItemListView_47;
+ value = 1;
+ },
+ AVKON_ENUMERATED_TEXT
+ {
+ text = STR_symbian_ua_guiSettingItemListView_49;
+ }
+ };
+ }
+RESOURCE ARRAY r_symbian_ua_gui_setting_item_list_b_ice_popped_up_texts_resource
+ {
+ items =
+ {
+ LBUF
+ {
+ txt = STR_symbian_ua_guiSettingItemListView_48;
+ },
+ LBUF
+ {
+ txt = STR_symbian_ua_guiSettingItemListView_50;
+ }
+ };
+ }
+RESOURCE TBUF r_symbian_ua_gui_setting_item_list_ed_registrar
+ {
+ buf = STR_symbian_ua_guiSettingItemListView_3;
+ }
+RESOURCE TBUF r_symbian_ua_gui_setting_item_list_ed_user
+ {
+ buf = STR_symbian_ua_guiSettingItemListView_7;
+ }
+RESOURCE TBUF r_symbian_ua_gui_setting_item_list_ed_stun_server
+ {
+ buf = STR_symbian_ua_guiSettingItemListView_18;
+ }
diff --git a/pjsip-apps/src/symbian_ua_gui/data/symbian_ua_gui_reg.loc b/pjsip-apps/src/symbian_ua_gui/data/symbian_ua_gui_reg.loc
new file mode 100644
index 0000000..876b4b5
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/data/symbian_ua_gui_reg.loc
@@ -0,0 +1,11 @@
+// LOCALISATION STRINGS
+
+// Caption string for app.
+#define qtn_caption_string "symbian_ua_gui"
+
+// Short caption string for app.
+#define qtn_short_caption_string "HW"
+
+#define qtn_loc_resource_file_1 "\\resource\\apps\\symbian_ua_gui"
+
+// End of File
diff --git a/pjsip-apps/src/symbian_ua_gui/data/symbian_ua_gui_reg.rss b/pjsip-apps/src/symbian_ua_gui/data/symbian_ua_gui_reg.rss
new file mode 100644
index 0000000..ad50c4f
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/data/symbian_ua_gui_reg.rss
@@ -0,0 +1,21 @@
+
+#include <eikon.rh>
+#include <avkon.rsg>
+#include <avkon.rh>
+#include <appinfo.rh>
+#include "symbian_ua_gui_reg.loc"
+#include <symbian_ua_gui.rsg>
+
+UID2 KUidAppRegistrationResourceFile
+UID3 0xEBD12EE4
+
+RESOURCE APP_REGISTRATION_INFO
+ {
+ app_file="symbian_ua_gui";
+ localisable_resource_file = qtn_loc_resource_file_1;
+ localisable_resource_id = R_LOCALISABLE_APP_INFO;
+
+ embeddability=KAppNotEmbeddable;
+ newfile=KAppDoesNotSupportNewFile;
+ }
+
diff --git a/pjsip-apps/src/symbian_ua_gui/gfx/list_icon.bmp b/pjsip-apps/src/symbian_ua_gui/gfx/list_icon.bmp
new file mode 100644
index 0000000..a874fea
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/gfx/list_icon.bmp
Binary files differ
diff --git a/pjsip-apps/src/symbian_ua_gui/gfx/list_icon_mask.bmp b/pjsip-apps/src/symbian_ua_gui/gfx/list_icon_mask.bmp
new file mode 100644
index 0000000..e320527
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/gfx/list_icon_mask.bmp
Binary files differ
diff --git a/pjsip-apps/src/symbian_ua_gui/gfx/mark_icon.bmp b/pjsip-apps/src/symbian_ua_gui/gfx/mark_icon.bmp
new file mode 100644
index 0000000..35571e2
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/gfx/mark_icon.bmp
Binary files differ
diff --git a/pjsip-apps/src/symbian_ua_gui/gfx/mark_icon_mask.bmp b/pjsip-apps/src/symbian_ua_gui/gfx/mark_icon_mask.bmp
new file mode 100644
index 0000000..dc8744b
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/gfx/mark_icon_mask.bmp
Binary files differ
diff --git a/pjsip-apps/src/symbian_ua_gui/gfx/qgn_menu_symbian_ua_gui.svg b/pjsip-apps/src/symbian_ua_gui/gfx/qgn_menu_symbian_ua_gui.svg
new file mode 100644
index 0000000..47da6d7
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/gfx/qgn_menu_symbian_ua_gui.svg
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg baseProfile="tiny" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="100%" viewBox="0 0 88 87.999">
+<g>
+<g>
+<g>
+<g>
+<rect fill="none" width="88" height="87.999"/>
+</g>
+</g>
+<g>
+<linearGradient id="XMLID_7_" gradientUnits="userSpaceOnUse" x1="12.3042" y1="18.3799" x2="63.4113" y2="79.287">
+<stop offset="0" style="stop-color:#B3DDFF"/>
+<stop offset="0.8146" style="stop-color:#084296"/>
+<stop offset="1" style="stop-color:#084296"/>
+</linearGradient>
+<path fill="url(#XMLID_7_)" d="M32.135,7.415L14.363,17.432v23.167c0,0,8.926,15.351,10.468,18.001 c-2.386,1.704-15.44,11.03-15.44,11.03l21.613,12.652c0,0,12.907-9.85,14.71-11.226c1.979,1.109,16.231,9.101,16.231,9.101 l16.664-15.132c0,0-14.066-6.929-16.888-8.318c1.467-3.01,10.531-21.604,10.531-21.604l-22.298-9.59 c0,0-1.486,3.173-2.093,4.467c-2.046-0.88-6.573-2.826-6.573-2.826s-3.713,2.463-5.696,3.778 c-0.327-0.744-0.542-1.233-0.657-1.495c0.007-0.824,0.213-23.72,0.213-23.72L32.135,7.415z"/>
+<linearGradient id="XMLID_8_" gradientUnits="userSpaceOnUse" x1="40.8276" y1="52.1914" x2="16.1997" y2="21.1353">
+<stop offset="0" style="stop-color:#5AA7E0"/>
+<stop offset="1" style="stop-color:#3366CC"/>
+</linearGradient>
+<polygon fill="url(#XMLID_8_)" points="59.051,57.621 69.536,36.111 50.944,28.115 48.852,32.581 41.493,29.418 34.719,33.911 32.932,29.849 33.117,9.157 16.363,18.601 16.363,40.06 27.476,59.169 13.064,69.463 30.856,79.879 45.546,68.669 61.667,77.708 75.089,65.521 "/>
+<linearGradient id="XMLID_9_" gradientUnits="userSpaceOnUse" x1="60.585" y1="31.876" x2="53.8582" y2="45.1125">
+<stop offset="0" style="stop-color:#5AA7E0"/>
+<stop offset="1" style="stop-color:#3366CC"/>
+</linearGradient>
+<polygon fill="url(#XMLID_9_)" points="41.26,48.783 50.944,28.115 69.536,36.111 59.051,57.621 "/>
+<polygon fill="#0046B7" points="16.363,40.06 27.476,59.169 41.26,48.783 32.932,29.849 "/>
+<polygon fill="#3366CC" points="16.363,40.06 16.363,18.601 33.117,9.157 32.932,29.849 "/>
+<polygon fill="#CFECFF" points="26.696,39.23 41.493,29.418 59.523,37.168 45.546,47.954 "/>
+<path fill="#5AA7E0" d="M41.954,55.286"/>
+<polygon fill="#3366CC" points="26.696,39.23 27.476,59.169 45.546,68.669 45.546,47.954 "/>
+<polygon fill="#5AA7E0" points="13.064,69.463 27.476,59.169 45.546,68.669 30.856,79.879 "/>
+<linearGradient id="XMLID_10_" gradientUnits="userSpaceOnUse" x1="29.2085" y1="63.6836" x2="48.7102" y2="56.1976">
+<stop offset="0" style="stop-color:#5AA7E0"/>
+<stop offset="0.0056" style="stop-color:#5AA7E0"/>
+<stop offset="0.85" style="stop-color:#3366CC"/>
+<stop offset="1" style="stop-color:#3366CC"/>
+</linearGradient>
+<polygon fill="url(#XMLID_10_)" points="43.423,46.971 27.476,59.169 45.546,68.669 45.546,47.954 "/>
+<polygon fill="#0046B7" points="45.546,47.954 45.546,68.669 59.051,57.621 59.523,37.168 "/>
+<linearGradient id="XMLID_11_" gradientUnits="userSpaceOnUse" x1="45.3936" y1="59.5186" x2="59.0508" y2="59.5186">
+<stop offset="0" style="stop-color:#0046B7"/>
+<stop offset="1" style="stop-color:#3366CC"/>
+</linearGradient>
+<polygon fill="url(#XMLID_11_)" points="45.394,50.368 45.546,68.669 59.051,57.621 "/>
+<linearGradient id="XMLID_12_" gradientUnits="userSpaceOnUse" x1="60.8945" y1="68.6807" x2="57.2953" y2="58.792">
+<stop offset="0" style="stop-color:#5AA7E0"/>
+<stop offset="0.4101" style="stop-color:#5AA7E0"/>
+<stop offset="1" style="stop-color:#3366CC"/>
+</linearGradient>
+<polygon fill="url(#XMLID_12_)" points="61.667,77.708 45.546,68.669 59.051,57.621 75.089,65.521 "/>
+</g>
+</g>
+</g>
+</svg>
diff --git a/pjsip-apps/src/symbian_ua_gui/group/ABLD.BAT b/pjsip-apps/src/symbian_ua_gui/group/ABLD.BAT
new file mode 100644
index 0000000..8ccf2ed
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/group/ABLD.BAT
@@ -0,0 +1,15 @@
+@ECHO OFF
+
+REM Bldmake-generated batch file - ABLD.BAT
+REM ** DO NOT EDIT **
+
+perl -S ABLD.PL "\project\pjproject-trunk\pjsip-apps\src\symbian_ua_gui\group\\" %1 %2 %3 %4 %5 %6 %7 %8 %9
+if errorlevel==1 goto CheckPerl
+goto End
+
+:CheckPerl
+perl -v >NUL
+if errorlevel==1 echo Is Perl, version 5.003_07 or later, installed?
+goto End
+
+:End
diff --git a/pjsip-apps/src/symbian_ua_gui/group/Icons_aif_scalable_dc.mk b/pjsip-apps/src/symbian_ua_gui/group/Icons_aif_scalable_dc.mk
new file mode 100644
index 0000000..8aa63c7
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/group/Icons_aif_scalable_dc.mk
@@ -0,0 +1,71 @@
+# ============================================================================
+# Name : Icons_aif_scalable_dc.mk
+# Part of : symbian_ua_gui
+#
+# Description:
+#
+# ============================================================================
+
+
+ifeq (WINS,$(findstring WINS, $(PLATFORM)))
+ZDIR=$(EPOCROOT)epoc32\release\$(PLATFORM)\$(CFG)\Z
+else
+ZDIR=$(EPOCROOT)epoc32\data\z
+endif
+
+
+# ----------------------------------------------------------------------------
+# TODO: Configure these
+# ----------------------------------------------------------------------------
+
+TARGETDIR=$(ZDIR)\resource\apps
+ICONTARGETFILENAME=$(TARGETDIR)\symbian_ua_gui_aif.mif
+HEADERDIR=$(EPOCROOT)epoc32\include
+HEADERFILENAME=$(HEADERDIR)\symbian_ua_gui_aif.mbg
+
+ICONDIR=..\gfx
+
+do_nothing :
+ @rem do_nothing
+
+MAKMAKE : do_nothing
+
+BLD : do_nothing
+
+CLEAN : do_nothing
+
+LIB : do_nothing
+
+CLEANLIB : do_nothing
+
+# ----------------------------------------------------------------------------
+# TODO: Configure these.
+#
+# NOTE 1: DO NOT DEFINE MASK FILE NAMES! They are included automatically by
+# MifConv if the mask detph is defined.
+#
+# NOTE 2: Usually, source paths should not be included in the bitmap
+# definitions. MifConv searches for the icons in all icon directories in a
+# predefined order, which is currently \s60\icons, \s60\bitmaps2.
+# The directory \s60\icons is included in the search only if the feature flag
+# __SCALABLE_ICONS is defined.
+# ----------------------------------------------------------------------------
+# NOTE: if you have JUSTINTIME enabled for your S60 3rd FP1 or newer SDK
+# and this command crashes, consider adding "/X" to the command line.
+# See <http://forum.nokia.com/document/Forum_Nokia_Technical_Library_v1_35/contents/FNTL/Build_process_fails_at_mif_file_creation_in_S60_3rd_Ed_FP1_SDK.htm>
+# ----------------------------------------------------------------------------
+
+RESOURCE :
+ mifconv $(ICONTARGETFILENAME) \
+ /H$(HEADERFILENAME) \
+ /c32,8 $(ICONDIR)\qgn_menu_symbian_ua_gui.svg
+
+FREEZE : do_nothing
+
+SAVESPACE : do_nothing
+
+RELEASABLES :
+ @echo $(ICONTARGETFILENAME)
+
+FINAL : do_nothing
+
diff --git a/pjsip-apps/src/symbian_ua_gui/group/bld.inf b/pjsip-apps/src/symbian_ua_gui/group/bld.inf
new file mode 100644
index 0000000..dcdef78
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/group/bld.inf
@@ -0,0 +1,12 @@
+
+PRJ_PLATFORMS
+WINSCW ARMV5 GCCE
+
+PRJ_EXPORTS
+
+PRJ_MMPFILES
+
+gnumakefile icons_aif_scalable_dc.mk
+
+
+symbian_ua_gui.mmp
diff --git a/pjsip-apps/src/symbian_ua_gui/group/symbian_ua_gui.mmp b/pjsip-apps/src/symbian_ua_gui/group/symbian_ua_gui.mmp
new file mode 100644
index 0000000..1d6b2e7
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/group/symbian_ua_gui.mmp
@@ -0,0 +1,102 @@
+// The part below will be overwritten by automated test
+// =BEGIN
+#define SND_HAS_APS 0
+#define SND_HAS_VAS 0
+#define SND_HAS_MDA 1
+// =END
+
+TARGET symbian_ua_gui.exe
+UID 0x100039CE 0xEBD12EE4
+VENDORID 0
+TARGETTYPE exe
+EPOCSTACKSIZE 0x8000
+
+MACRO PJ_M_I386=1
+MACRO PJ_SYMBIAN=1
+
+SYSTEMINCLUDE \epoc32\include
+SYSTEMINCLUDE \epoc32\include\variant
+SYSTEMINCLUDE \epoc32\include\ecom
+SYSTEMINCLUDE \epoc32\include\libc
+SYSTEMINCLUDE ..\..\..\..\pjlib\include
+SYSTEMINCLUDE ..\..\..\..\pjlib-util\include
+SYSTEMINCLUDE ..\..\..\..\pjnath\include
+SYSTEMINCLUDE ..\..\..\..\pjmedia\include
+SYSTEMINCLUDE ..\..\..\..\pjsip\include
+
+USERINCLUDE ..\inc
+USERINCLUDE ..\data
+
+SOURCEPATH ..\data
+
+START RESOURCE symbian_ua_gui.rss
+HEADER
+TARGETPATH resource\apps
+END //RESOURCE
+
+START RESOURCE symbian_ua_gui_reg.rss
+TARGETPATH \private\10003a3f\apps
+END //RESOURCE
+
+LIBRARY euser.lib apparc.lib cone.lib eikcore.lib avkon.lib
+LIBRARY commonengine.lib efsrv.lib estor.lib eikcoctl.lib eikdlg.lib
+LIBRARY eikctl.lib bafl.lib fbscli.lib aknnotify.lib aknicon.lib
+LIBRARY etext.lib gdi.lib egul.lib insock.lib
+LIBRARY ecom.lib inetprotutil.lib http.lib esock.lib
+LIBRARY charconv.lib estlib.lib
+LIBRARY securesocket.lib x509.lib crypto.lib x500.lib
+LIBRARY hal.lib
+
+// Ordering static libs based on dependencies, most to least dependent,
+// this could be necessary for some SDKs, e.g: S60 3rd MR
+STATICLIBRARY pjsua_lib.lib
+STATICLIBRARY pjsip_ua.lib pjsip_simple.lib pjsip.lib
+STATICLIBRARY libgsmcodec.lib libspeexcodec.lib
+STATICLIBRARY libg7221codec.lib libpassthroughcodec.lib
+STATICLIBRARY pjmedia.lib
+STATICLIBRARY pjmedia_audiodev.lib
+STATICLIBRARY pjsdp.lib
+STATICLIBRARY pjnath.lib
+STATICLIBRARY pjlib_util.lib pjlib.lib
+STATICLIBRARY libsrtp.lib
+STATICLIBRARY libresample.lib
+
+
+#if SND_HAS_APS
+ LIBRARY APSSession2.lib
+#endif
+
+#if SND_HAS_VAS
+ LIBRARY VoIPAudioIntfc.lib
+#endif
+
+#if SND_HAS_MDA
+ LIBRARY mediaclientaudiostream.lib
+ LIBRARY mediaclientaudioinputstream.lib
+#endif
+
+#if SND_HAS_APS || SND_HAS_VAS
+ CAPABILITY NetworkServices LocalServices ReadUserData WriteUserData UserEnvironment MultimediaDD
+#else
+ CAPABILITY NetworkServices LocalServices ReadUserData WriteUserData UserEnvironment
+#endif
+
+LANG 01
+
+START BITMAP symbian_ua_gui.mbm
+HEADER
+TARGETPATH \resource\apps
+SOURCEPATH ..\gfx
+SOURCE c12,1 list_icon.bmp list_icon_mask.bmp
+END
+
+SOURCEPATH ..\src
+SOURCE symbian_ua_guiContainerView.cpp
+SOURCE symbian_ua_guiContainer.cpp
+SOURCE symbian_ua_guiAppUi.cpp
+SOURCE symbian_ua_guiDocument.cpp
+SOURCE symbian_ua_guiApplication.cpp
+SOURCE symbian_ua_guiSettingItemList.cpp
+SOURCE Symbian_ua_guiSettingItemListSets.cpp
+SOURCE symbian_ua_guiSettingItemListView.cpp
+SOURCE symbian_ua.cpp
diff --git a/pjsip-apps/src/symbian_ua_gui/inc/Symbian_ua_guiSettingItemListSettings.h b/pjsip-apps/src/symbian_ua_gui/inc/Symbian_ua_guiSettingItemListSettings.h
new file mode 100644
index 0000000..aabe4aa
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/inc/Symbian_ua_guiSettingItemListSettings.h
@@ -0,0 +1,73 @@
+/* $Id: Symbian_ua_guiSettingItemListSettings.h 3550 2011-05-05 05:33:27Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef SYMBIAN_UA_GUISETTINGITEMLISTSETTINGS_H
+#define SYMBIAN_UA_GUISETTINGITEMLISTSETTINGS_H
+
+// [[[ begin generated region: do not modify [Generated Includes]
+#include <e32std.h>
+// ]]] end generated region [Generated Includes]
+
+// [[[ begin generated region: do not modify [Generated Constants]
+const int KEd_registrarMaxLength = 255;
+const int KEd_userMaxLength = 255;
+const int KEd_passwordMaxLength = 32;
+const int KEd_stun_serverMaxLength = 255;
+// ]]] end generated region [Generated Constants]
+
+/**
+ * @class TSymbian_ua_guiSettingItemListSettings Symbian_ua_guiSettingItemListSettings.h
+ */
+class TSymbian_ua_guiSettingItemListSettings
+ {
+public:
+ // construct and destroy
+ static TSymbian_ua_guiSettingItemListSettings* NewL();
+ void ConstructL();
+
+private:
+ // constructor
+ TSymbian_ua_guiSettingItemListSettings();
+ // [[[ begin generated region: do not modify [Generated Accessors]
+public:
+ TDes& Ed_registrar();
+ void SetEd_registrar(const TDesC& aValue);
+ TDes& Ed_user();
+ void SetEd_user(const TDesC& aValue);
+ TDes& Ed_password();
+ void SetEd_password(const TDesC& aValue);
+ TBool& B_srtp();
+ void SetB_srtp(const TBool& aValue);
+ TBool& B_ice();
+ void SetB_ice(const TBool& aValue);
+ TDes& Ed_stun_server();
+ void SetEd_stun_server(const TDesC& aValue);
+ // ]]] end generated region [Generated Accessors]
+
+ // [[[ begin generated region: do not modify [Generated Members]
+protected:
+ TBuf<KEd_registrarMaxLength> iEd_registrar;
+ TBuf<KEd_userMaxLength> iEd_user;
+ TBuf<KEd_passwordMaxLength> iEd_password;
+ TBool iB_srtp;
+ TBool iB_ice;
+ TBuf<KEd_stun_serverMaxLength> iEd_stun_server;
+ // ]]] end generated region [Generated Members]
+
+ };
+#endif // SYMBIAN_UA_GUISETTINGITEMLISTSETTINGS_H
diff --git a/pjsip-apps/src/symbian_ua_gui/inc/symbian_ua.h b/pjsip-apps/src/symbian_ua_gui/inc/symbian_ua.h
new file mode 100644
index 0000000..431b2e7
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/inc/symbian_ua.h
@@ -0,0 +1,50 @@
+/* $Id: ua.cpp 1793 2008-02-14 13:39:24Z bennylp $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __SYMBIAN_UA_H__
+#define __SYMBIAN_UA_H__
+
+#include <stddef.h>
+
+typedef struct
+{
+ void (*on_info)(const wchar_t* buf);
+ void (*on_incoming_call)(const wchar_t* caller_disp, const wchar_t* caller_uri);
+ void (*on_call_end)(const wchar_t* reason);
+ void (*on_reg_state)(bool success);
+ void (*on_unreg_state)(bool success);
+} symbian_ua_info_cb_t;
+
+int symbian_ua_init();
+int symbian_ua_destroy();
+
+void symbian_ua_set_info_callback(const symbian_ua_info_cb_t *cb);
+
+int symbian_ua_set_account(const char *domain, const char *username,
+ const char *password,
+ bool use_srtp, bool use_ice);
+
+bool symbian_ua_anycall();
+int symbian_ua_makecall(const char* dest_url);
+int symbian_ua_endcall();
+int symbian_ua_answercall();
+
+#endif
+
diff --git a/pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_gui.hrh b/pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_gui.hrh
new file mode 100644
index 0000000..72127e0
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_gui.hrh
@@ -0,0 +1,17 @@
+/*
+========================================================================
+ Name : symbian_ua_gui.hrh
+ Author : nanang
+ Copyright : (c) PJSIP 2008
+ Description :
+========================================================================
+*/
+enum Tsymbian_ua_guiViewUids
+ {
+ ESymbian_ua_guiContainerViewId = 1,
+ ESymbian_ua_guiSettingItemListViewId
+ };
+enum TSymbian_ua_guiApplicationControls
+ {
+ ESymbian_ua_guiApplicationDlg_wait_init = 1
+ };
diff --git a/pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_gui.pan b/pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_gui.pan
new file mode 100644
index 0000000..a06f56b
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_gui.pan
@@ -0,0 +1,18 @@
+
+#ifndef SYMBIAN_UA_GUI_PAN_H
+#define SYMBIAN_UA_GUI_PAN_H
+
+/** symbian_ua_gui application panic codes */
+enum Tsymbian_ua_guiPanics
+ {
+ Esymbian_ua_guiUi = 1
+ // add further panics here
+ };
+
+inline void Panic(Tsymbian_ua_guiPanics aReason)
+ {
+ _LIT(applicationName,"symbian_ua_gui");
+ User::Panic(applicationName, aReason);
+ }
+
+#endif // SYMBIAN_UA_GUI_PAN_H
diff --git a/pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_guiAppUi.h b/pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_guiAppUi.h
new file mode 100644
index 0000000..36fb720
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_guiAppUi.h
@@ -0,0 +1,129 @@
+/* $Id: symbian_ua_guiAppUi.h 3550 2011-05-05 05:33:27Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef SYMBIAN_UA_GUIAPPUI_H
+#define SYMBIAN_UA_GUIAPPUI_H
+
+// [[[ begin generated region: do not modify [Generated Includes]
+#include <aknviewappui.h>
+#include <aknwaitdialog.h>
+// ]]] end generated region [Generated Includes]
+
+// [[[ begin generated region: do not modify [Generated Forward Declarations]
+class Csymbian_ua_guiContainerView;
+class Csymbian_ua_guiSettingItemListView;
+// ]]] end generated region [Generated Forward Declarations]
+
+/**
+ * @class Csymbian_ua_guiAppUi symbian_ua_guiAppUi.h
+ * @brief The AppUi class handles application-wide aspects of the user interface, including
+ * view management and the default menu, control pane, and status pane.
+ */
+class Csymbian_ua_guiAppUi : public CAknViewAppUi, public CTimer
+ {
+public:
+ // constructor and destructor
+ Csymbian_ua_guiAppUi();
+ virtual ~Csymbian_ua_guiAppUi();
+ void ConstructL();
+
+public:
+ // from CCoeAppUi
+ TKeyResponse HandleKeyEventL(
+ const TKeyEvent& aKeyEvent,
+ TEventCode aType );
+
+ // from CEikAppUi
+ void HandleCommandL( TInt aCommand );
+ void HandleResourceChangeL( TInt aType );
+
+ // from CAknAppUi
+ void HandleViewDeactivation(
+ const TVwsViewId& aViewIdToBeDeactivated,
+ const TVwsViewId& aNewlyActivatedViewId );
+
+private:
+ void InitializeContainersL();
+ // [[[ begin generated region: do not modify [Generated Methods]
+public:
+ void ExecuteDlg_wait_initLD( const TDesC* aOverrideText = NULL );
+ void RemoveDlg_wait_initL();
+ // ]]] end generated region [Generated Methods]
+
+ // [[[ begin generated region: do not modify [Generated Instance Variables]
+private:
+ CAknWaitDialog* iDlg_wait_init;
+ class CProgressDialogCallback;
+ CProgressDialogCallback* iDlg_wait_initCallback;
+ Csymbian_ua_guiContainerView* iSymbian_ua_guiContainerView;
+ Csymbian_ua_guiSettingItemListView* iSymbian_ua_guiSettingItemListView;
+ // ]]] end generated region [Generated Instance Variables]
+
+
+ // [[[ begin [User Handlers]
+protected:
+ void HandleSymbian_ua_guiAppUiApplicationSpecificEventL(
+ TInt aType,
+ const TWsEvent& anEvent );
+ void HandleDlg_wait_initCanceledL( CAknProgressDialog* aDialog );
+ // ]]] end [User Handlers]
+
+
+ // [[[ begin [Overridden Methods]
+protected:
+ void HandleApplicationSpecificEventL(
+ TInt aType,
+ const TWsEvent& anEvent );
+ // ]]] end [Overridden Methods]
+
+ virtual void RunL();
+
+ // [[[ begin [MProgressDialogCallback support]
+private:
+ typedef void ( Csymbian_ua_guiAppUi::*ProgressDialogEventHandler )(
+ CAknProgressDialog* aProgressDialog );
+
+ /**
+ * This is a helper class for progress/wait dialog callbacks. It routes the dialog's
+ * cancel notification to the handler function for the cancel event.
+ */
+ class CProgressDialogCallback : public CBase, public MProgressDialogCallback
+ {
+ public:
+ CProgressDialogCallback(
+ Csymbian_ua_guiAppUi* aHandlerObj,
+ CAknProgressDialog* aDialog,
+ ProgressDialogEventHandler aHandler ) :
+ handlerObj( aHandlerObj ), dialog( aDialog ), handler( aHandler )
+ {}
+
+ void DialogDismissedL( TInt aButtonId )
+ {
+ ( handlerObj->*handler )( dialog );
+ }
+ private:
+ Csymbian_ua_guiAppUi* handlerObj;
+ CAknProgressDialog* dialog;
+ ProgressDialogEventHandler handler;
+ };
+
+ // ]]] end [MProgressDialogCallback support]
+
+ };
+
+#endif // SYMBIAN_UA_GUIAPPUI_H
diff --git a/pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_guiApplication.h b/pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_guiApplication.h
new file mode 100644
index 0000000..af53b73
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_guiApplication.h
@@ -0,0 +1,45 @@
+/* $Id: symbian_ua_guiApplication.h 3550 2011-05-05 05:33:27Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef SYMBIAN_UA_GUIAPPLICATION_H
+#define SYMBIAN_UA_GUIAPPLICATION_H
+
+// [[[ begin generated region: do not modify [Generated Includes]
+#include <aknapp.h>
+// ]]] end generated region [Generated Includes]
+
+// [[[ begin generated region: do not modify [Generated Constants]
+const TUid KUidsymbian_ua_guiApplication = { 0xEBD12EE4 };
+// ]]] end generated region [Generated Constants]
+
+/**
+ *
+ * @class Csymbian_ua_guiApplication symbian_ua_guiApplication.h
+ * @brief A CAknApplication-derived class is required by the S60 application
+ * framework. It is subclassed to create the application's document
+ * object.
+ */
+class Csymbian_ua_guiApplication : public CAknApplication
+ {
+private:
+ TUid AppDllUid() const;
+ CApaDocument* CreateDocumentL();
+
+ };
+
+#endif // SYMBIAN_UA_GUIAPPLICATION_H
diff --git a/pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_guiContainer.h b/pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_guiContainer.h
new file mode 100644
index 0000000..0b6a847
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_guiContainer.h
@@ -0,0 +1,123 @@
+/* $Id: symbian_ua_guiContainer.h 3550 2011-05-05 05:33:27Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef SYMBIAN_UA_GUICONTAINER_H
+#define SYMBIAN_UA_GUICONTAINER_H
+
+// [[[ begin generated region: do not modify [Generated Includes]
+#include <coecntrl.h>
+// ]]] end generated region [Generated Includes]
+
+
+// [[[ begin [Event Handler Includes]
+// ]]] end [Event Handler Includes]
+
+// [[[ begin generated region: do not modify [Generated Forward Declarations]
+class MEikCommandObserver;
+class CEikLabel;
+class CEikEdwin;
+// ]]] end generated region [Generated Forward Declarations]
+
+/**
+ * Container class for symbian_ua_guiContainer
+ *
+ * @class CSymbian_ua_guiContainer symbian_ua_guiContainer.h
+ */
+class CSymbian_ua_guiContainer : public CCoeControl
+ {
+public:
+ // constructors and destructor
+ CSymbian_ua_guiContainer();
+ static CSymbian_ua_guiContainer* NewL(
+ const TRect& aRect,
+ const CCoeControl* aParent,
+ MEikCommandObserver* aCommandObserver );
+ static CSymbian_ua_guiContainer* NewLC(
+ const TRect& aRect,
+ const CCoeControl* aParent,
+ MEikCommandObserver* aCommandObserver );
+ void ConstructL(
+ const TRect& aRect,
+ const CCoeControl* aParent,
+ MEikCommandObserver* aCommandObserver );
+ virtual ~CSymbian_ua_guiContainer();
+
+public:
+ // from base class CCoeControl
+ TInt CountComponentControls() const;
+ CCoeControl* ComponentControl( TInt aIndex ) const;
+ TKeyResponse OfferKeyEventL(
+ const TKeyEvent& aKeyEvent,
+ TEventCode aType );
+ void HandleResourceChange( TInt aType );
+
+protected:
+ // from base class CCoeControl
+ void SizeChanged();
+
+private:
+ // from base class CCoeControl
+ void Draw( const TRect& aRect ) const;
+
+private:
+ void InitializeControlsL();
+ void LayoutControls();
+ CCoeControl* iFocusControl;
+ MEikCommandObserver* iCommandObserver;
+ // [[[ begin generated region: do not modify [Generated Methods]
+public:
+ // ]]] end generated region [Generated Methods]
+
+ // [[[ begin generated region: do not modify [Generated Type Declarations]
+public:
+ // ]]] end generated region [Generated Type Declarations]
+
+ // [[[ begin generated region: do not modify [Generated Instance Variables]
+private:
+ CEikLabel* iLabel1;
+ CEikEdwin* iEd_url;
+ CEikEdwin* iEd_info;
+ // ]]] end generated region [Generated Instance Variables]
+
+
+ // [[[ begin [Overridden Methods]
+protected:
+ // ]]] end [Overridden Methods]
+
+
+ // [[[ begin [User Handlers]
+protected:
+ // ]]] end [User Handlers]
+
+public:
+ enum TControls
+ {
+ // [[[ begin generated region: do not modify [Generated Contents]
+ ELabel1,
+ EEd_url,
+ EEd_info,
+
+ // ]]] end generated region [Generated Contents]
+
+ // add any user-defined entries here...
+
+ ELastControl
+ };
+ };
+
+#endif // SYMBIAN_UA_GUICONTAINER_H
diff --git a/pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_guiContainer.hrh b/pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_guiContainer.hrh
new file mode 100644
index 0000000..1ad366f
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_guiContainer.hrh
@@ -0,0 +1,17 @@
+/*
+========================================================================
+ Name : symbian_ua_guiContainer.hrh
+ Author : nanang
+ Copyright : (c) PJSIP 2008
+ Description :
+========================================================================
+*/
+enum TSymbian_ua_guiContainerViewCommands
+ {
+ ESymbian_ua_guiContainerViewControlPaneRightId = 0x6000,
+ ESymbian_ua_guiContainerViewSettingMenuItemCommand
+ };
+enum TSymbian_ua_guiContainerViewControls
+ {
+ ESymbian_ua_guiContainerViewQry_accept_call = 1
+ };
diff --git a/pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_guiContainerView.h b/pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_guiContainerView.h
new file mode 100644
index 0000000..4e9e8a5
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_guiContainerView.h
@@ -0,0 +1,98 @@
+/* $Id: symbian_ua_guiContainerView.h 3550 2011-05-05 05:33:27Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef SYMBIAN_UA_GUICONTAINERVIEW_H
+#define SYMBIAN_UA_GUICONTAINERVIEW_H
+
+// [[[ begin generated region: do not modify [Generated Includes]
+#include <aknview.h>
+// ]]] end generated region [Generated Includes]
+
+
+// [[[ begin [Event Handler Includes]
+// ]]] end [Event Handler Includes]
+
+// [[[ begin generated region: do not modify [Generated Forward Declarations]
+class CSymbian_ua_guiContainer;
+// ]]] end generated region [Generated Forward Declarations]
+
+// [[[ begin generated region: do not modify [Generated Constants]
+// ]]] end generated region [Generated Constants]
+
+/**
+ * Avkon view class for symbian_ua_guiContainerView. It is register with the view server
+ * by the AppUi. It owns the container control.
+ * @class Csymbian_ua_guiContainerView symbian_ua_guiContainerView.h
+ */
+class Csymbian_ua_guiContainerView : public CAknView
+ {
+public:
+ // constructors and destructor
+ Csymbian_ua_guiContainerView();
+ static Csymbian_ua_guiContainerView* NewL();
+ static Csymbian_ua_guiContainerView* NewLC();
+ void ConstructL();
+ virtual ~Csymbian_ua_guiContainerView();
+
+public:
+ // from base class CAknView
+ TUid Id() const;
+ void HandleCommandL( TInt aCommand );
+
+ void PutMessage(const TDesC &msg);
+
+protected:
+ // from base class CAknView
+ void DoActivateL(
+ const TVwsViewId& aPrevViewId,
+ TUid aCustomMessageId,
+ const TDesC8& aCustomMessage );
+ void DoDeactivate();
+ void HandleStatusPaneSizeChange();
+
+private:
+ void SetupStatusPaneL();
+ void CleanupStatusPane();
+ // [[[ begin generated region: do not modify [Generated Methods]
+public:
+ static void RunNote_errorL( const TDesC* aOverrideText = NULL );
+ static void RunNote_infoL( const TDesC* aOverrideText = NULL );
+ static void RunNote_warningL( const TDesC* aOverrideText = NULL );
+ static TInt RunQry_accept_callL( const TDesC* aOverrideText = NULL );
+ // ]]] end generated region [Generated Methods]
+
+
+ // [[[ begin [Overridden Methods]
+protected:
+ // ]]] end [Overridden Methods]
+
+
+ // [[[ begin [User Handlers]
+protected:
+ TBool CallSoftKeyPressedL( TInt aCommand );
+ TBool HandleSettingMenuItemSelectedL( TInt aCommand );
+ // ]]] end [User Handlers]
+
+ // [[[ begin generated region: do not modify [Generated Instance Variables]
+private:
+ CSymbian_ua_guiContainer* iSymbian_ua_guiContainer;
+ // ]]] end generated region [Generated Instance Variables]
+
+ };
+
+#endif // SYMBIAN_UA_GUICONTAINERVIEW_H
diff --git a/pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_guiDocument.h b/pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_guiDocument.h
new file mode 100644
index 0000000..52fd529
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_guiDocument.h
@@ -0,0 +1,46 @@
+/* $Id: symbian_ua_guiDocument.h 3550 2011-05-05 05:33:27Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef SYMBIAN_UA_GUIDOCUMENT_H
+#define SYMBIAN_UA_GUIDOCUMENT_H
+
+#include <akndoc.h>
+
+class CEikAppUi;
+
+/**
+* @class Csymbian_ua_guiDocument symbian_ua_guiDocument.h
+* @brief A CAknDocument-derived class is required by the S60 application
+* framework. It is responsible for creating the AppUi object.
+*/
+class Csymbian_ua_guiDocument : public CAknDocument
+ {
+public:
+ // constructor
+ static Csymbian_ua_guiDocument* NewL( CEikApplication& aApp );
+
+private:
+ // constructors
+ Csymbian_ua_guiDocument( CEikApplication& aApp );
+ void ConstructL();
+
+public:
+ // from base class CEikDocument
+ CEikAppUi* CreateAppUiL();
+ };
+#endif // SYMBIAN_UA_GUIDOCUMENT_H
diff --git a/pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_guiSettingItemList.h b/pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_guiSettingItemList.h
new file mode 100644
index 0000000..880b033
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_guiSettingItemList.h
@@ -0,0 +1,97 @@
+/* $Id: symbian_ua_guiSettingItemList.h 3550 2011-05-05 05:33:27Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef SYMBIAN_UA_GUISETTINGITEMLIST_H
+#define SYMBIAN_UA_GUISETTINGITEMLIST_H
+
+// [[[ begin generated region: do not modify [Generated Includes]
+#include <aknsettingitemlist.h>
+// ]]] end generated region [Generated Includes]
+
+
+// [[[ begin [Event Handler Includes]
+// ]]] end [Event Handler Includes]
+
+// [[[ begin generated region: do not modify [Generated Forward Declarations]
+class MEikCommandObserver;
+class TSymbian_ua_guiSettingItemListSettings;
+// ]]] end generated region [Generated Forward Declarations]
+
+/**
+ * @class CSymbian_ua_guiSettingItemList symbian_ua_guiSettingItemList.h
+ */
+class CSymbian_ua_guiSettingItemList : public CAknSettingItemList
+ {
+public: // constructors and destructor
+
+ CSymbian_ua_guiSettingItemList(
+ TSymbian_ua_guiSettingItemListSettings& settings,
+ MEikCommandObserver* aCommandObserver );
+ virtual ~CSymbian_ua_guiSettingItemList();
+
+public:
+
+ // from CCoeControl
+ void HandleResourceChange( TInt aType );
+
+ // overrides of CAknSettingItemList
+ CAknSettingItem* CreateSettingItemL( TInt id );
+ void EditItemL( TInt aIndex, TBool aCalledFromMenu );
+ TKeyResponse OfferKeyEventL(
+ const TKeyEvent& aKeyEvent,
+ TEventCode aType );
+
+public:
+ // utility function for menu
+ void ChangeSelectedItemL();
+
+ void LoadSettingValuesL();
+ void SaveSettingValuesL();
+
+private:
+ // override of CAknSettingItemList
+ void SizeChanged();
+
+private:
+ // current settings values
+ TSymbian_ua_guiSettingItemListSettings& iSettings;
+ MEikCommandObserver* iCommandObserver;
+ // [[[ begin generated region: do not modify [Generated Methods]
+public:
+ // ]]] end generated region [Generated Methods]
+
+ // [[[ begin generated region: do not modify [Generated Type Declarations]
+public:
+ // ]]] end generated region [Generated Type Declarations]
+
+ // [[[ begin generated region: do not modify [Generated Instance Variables]
+private:
+ // ]]] end generated region [Generated Instance Variables]
+
+
+ // [[[ begin [Overridden Methods]
+protected:
+ // ]]] end [Overridden Methods]
+
+
+ // [[[ begin [User Handlers]
+protected:
+ // ]]] end [User Handlers]
+
+ };
+#endif // SYMBIAN_UA_GUISETTINGITEMLIST_H
diff --git a/pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_guiSettingItemList.hrh b/pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_guiSettingItemList.hrh
new file mode 100644
index 0000000..e9b4de4
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_guiSettingItemList.hrh
@@ -0,0 +1,22 @@
+/*
+========================================================================
+ Name : symbian_ua_guiSettingItemList.hrh
+ Author : nanang
+ Copyright : (c) PJSIP 2008
+ Description :
+========================================================================
+*/
+enum TSymbian_ua_guiSettingItemListViewCommands
+ {
+ ESymbian_ua_guiSettingItemListViewMenuItem1Command = 0x6000,
+ ESymbian_ua_guiSettingItemListViewSave_SettingsMenuItemCommand
+ };
+enum TSymbian_ua_guiSettingItemListViewSave_SettingsItems
+ {
+ ESymbian_ua_guiSettingItemListViewEd_registrar = 1,
+ ESymbian_ua_guiSettingItemListViewEd_user,
+ ESymbian_ua_guiSettingItemListViewEd_password,
+ ESymbian_ua_guiSettingItemListViewEd_stun_server,
+ ESymbian_ua_guiSettingItemListViewB_srtp,
+ ESymbian_ua_guiSettingItemListViewB_ice
+ };
diff --git a/pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_guiSettingItemListView.h b/pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_guiSettingItemListView.h
new file mode 100644
index 0000000..681e08c
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/inc/symbian_ua_guiSettingItemListView.h
@@ -0,0 +1,95 @@
+/* $Id: symbian_ua_guiSettingItemListView.h 3550 2011-05-05 05:33:27Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef SYMBIAN_UA_GUISETTINGITEMLISTVIEW_H
+#define SYMBIAN_UA_GUISETTINGITEMLISTVIEW_H
+
+// [[[ begin generated region: do not modify [Generated Includes]
+#include <aknview.h>
+#include "Symbian_ua_guiSettingItemListSettings.h"
+// ]]] end generated region [Generated Includes]
+
+
+// [[[ begin [Event Handler Includes]
+// ]]] end [Event Handler Includes]
+
+// [[[ begin generated region: do not modify [Generated Forward Declarations]
+class CSymbian_ua_guiSettingItemList;
+// ]]] end generated region [Generated Forward Declarations]
+
+// [[[ begin generated region: do not modify [Generated Constants]
+// ]]] end generated region [Generated Constants]
+
+/**
+ * Avkon view class for symbian_ua_guiSettingItemListView. It is register with the view server
+ * by the AppUi. It owns the container control.
+ * @class Csymbian_ua_guiSettingItemListView symbian_ua_guiSettingItemListView.h
+ */
+class Csymbian_ua_guiSettingItemListView : public CAknView
+ {
+public:
+ // constructors and destructor
+ Csymbian_ua_guiSettingItemListView();
+ static Csymbian_ua_guiSettingItemListView* NewL();
+ static Csymbian_ua_guiSettingItemListView* NewLC();
+ void ConstructL();
+ virtual ~Csymbian_ua_guiSettingItemListView();
+
+public:
+ // from base class CAknView
+ TUid Id() const;
+ void HandleCommandL( TInt aCommand );
+
+protected:
+ // from base class CAknView
+ void DoActivateL(
+ const TVwsViewId& aPrevViewId,
+ TUid aCustomMessageId,
+ const TDesC8& aCustomMessage );
+ void DoDeactivate();
+ void HandleStatusPaneSizeChange();
+
+private:
+ void SetupStatusPaneL();
+ void CleanupStatusPane();
+ // [[[ begin generated region: do not modify [Generated Methods]
+public:
+ // ]]] end generated region [Generated Methods]
+
+
+ // [[[ begin [Overridden Methods]
+protected:
+ // ]]] end [Overridden Methods]
+
+
+ // [[[ begin [User Handlers]
+protected:
+ TBool HandleChangeSelectedSettingItemL( TInt aCommand );
+ TBool HandleControlPaneRightSoftKeyPressedL( TInt aCommand );
+ TBool HandleCancelMenuItemSelectedL( TInt aCommand );
+ // ]]] end [User Handlers]
+
+ // [[[ begin generated region: do not modify [Generated Instance Variables]
+private:
+ CSymbian_ua_guiSettingItemList* iSymbian_ua_guiSettingItemList;
+ TSymbian_ua_guiSettingItemListSettings* iSettings;
+ // ]]] end generated region [Generated Instance Variables]
+
+ };
+
+#endif // SYMBIAN_UA_GUISETTINGITEMLISTVIEW_H
diff --git a/pjsip-apps/src/symbian_ua_gui/sis/symbian_ua_gui.pkg b/pjsip-apps/src/symbian_ua_gui/sis/symbian_ua_gui.pkg
new file mode 100644
index 0000000..b460505
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/sis/symbian_ua_gui.pkg
@@ -0,0 +1,36 @@
+; symbian_ua_gui.pkg
+; This is an auto-generated PKG file by Carbide.
+; This file uses variables specific to Carbide builds that will not work
+; on command-line builds. If you want to use this generated PKG file from the
+; command-line tools you will need to modify the variables with the appropriate
+; values: $(EPOCROOT), $(PLATFORM), $(TARGET)
+; Also, the resource file entries should be changed to match the language
+; used in the build. For example, if building for LANGUAGE_01, change the file
+; extensions .rsc to .r01.
+;
+;Language - standard language definitions
+&EN
+
+; standard SIS file header
+#{"symbian_ua_gui"},(0xEBD12EE4),1,0,0
+
+;Localised Vendor name
+%{"Vendor-EN"}
+
+;Unique Vendor name
+:"Vendor"
+
+;Supports Series 60 v 3.0
+[0x101F7961], 0, 0, 0, {"Series60ProductID"}
+
+;Files to install
+;You should change the source paths to match that of your environment
+;<source> <destination>
+"$(EPOCROOT)Epoc32\release\$(PLATFORM)\$(TARGET)\symbian_ua_gui.exe" -"!:\sys\bin\symbian_ua_gui.exe"
+"$(EPOCROOT)Epoc32\data\z\resource\apps\symbian_ua_gui.r01" -"!:\resource\apps\symbian_ua_gui.r01"
+"$(EPOCROOT)Epoc32\data\z\private\10003a3f\apps\symbian_ua_gui_reg.r01" -"!:\private\10003a3f\import\apps\symbian_ua_gui_reg.r01"
+"$(EPOCROOT)epoc32\data\z\resource\apps\symbian_ua_gui_aif.mif" -"!:\resource\apps\symbian_ua_gui_aif.mif"
+"$(EPOCROOT)epoc32\data\z\resource\apps\symbian_ua_gui.mbm" -"!:\resource\apps\symbian_ua_gui.mbm"
+; Add any installation notes if applicable
+;"symbian_ua_gui.txt" -"!:\private\0xEBD12EE4\symbian_ua_gui.txt"
+
diff --git a/pjsip-apps/src/symbian_ua_gui/sis/symbian_ua_gui.txt b/pjsip-apps/src/symbian_ua_gui/sis/symbian_ua_gui.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/sis/symbian_ua_gui.txt
diff --git a/pjsip-apps/src/symbian_ua_gui/src/Symbian_ua_guiSettingItemListSets.cpp b/pjsip-apps/src/symbian_ua_gui/src/Symbian_ua_guiSettingItemListSets.cpp
new file mode 100644
index 0000000..7e66d76
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/src/Symbian_ua_guiSettingItemListSets.cpp
@@ -0,0 +1,154 @@
+/* $Id: Symbian_ua_guiSettingItemListSets.cpp 3550 2011-05-05 05:33:27Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/**
+ * Generated helper class which manages the settings contained
+ * in 'symbian_ua_guiSettingItemList'. Each CAknSettingItem maintains
+ * a reference to data in this class so that changes in the setting
+ * item list can be synchronized with this storage.
+ */
+
+// [[[ begin generated region: do not modify [Generated Includes]
+#include <e32base.h>
+#include <stringloader.h>
+#include <barsread.h>
+#include <symbian_ua_gui.rsg>
+#include "Symbian_ua_guiSettingItemListSettings.h"
+// ]]] end generated region [Generated Includes]
+
+/**
+ * C/C++ constructor for settings data, cannot throw
+ */
+TSymbian_ua_guiSettingItemListSettings::TSymbian_ua_guiSettingItemListSettings()
+ {
+ }
+
+/**
+ * Two-phase constructor for settings data
+ */
+TSymbian_ua_guiSettingItemListSettings* TSymbian_ua_guiSettingItemListSettings::NewL()
+ {
+ TSymbian_ua_guiSettingItemListSettings* data = new( ELeave ) TSymbian_ua_guiSettingItemListSettings;
+ CleanupStack::PushL( data );
+ data->ConstructL();
+ CleanupStack::Pop( data );
+ return data;
+ }
+
+/**
+ * Second phase for initializing settings data
+ */
+void TSymbian_ua_guiSettingItemListSettings::ConstructL()
+ {
+ // [[[ begin generated region: do not modify [Generated Initializers]
+ {
+ HBufC* text = StringLoader::LoadLC( R_SYMBIAN_UA_GUI_SETTING_ITEM_LIST_ED_REGISTRAR );
+ SetEd_registrar( text->Des() );
+ CleanupStack::PopAndDestroy( text );
+ }
+ {
+ HBufC* text = StringLoader::LoadLC( R_SYMBIAN_UA_GUI_SETTING_ITEM_LIST_ED_USER );
+ SetEd_user( text->Des() );
+ CleanupStack::PopAndDestroy( text );
+ }
+ SetB_srtp( 0 );
+ SetB_ice( 0 );
+ {
+ HBufC* text = StringLoader::LoadLC( R_SYMBIAN_UA_GUI_SETTING_ITEM_LIST_ED_STUN_SERVER );
+ SetEd_stun_server( text->Des() );
+ CleanupStack::PopAndDestroy( text );
+ }
+ // ]]] end generated region [Generated Initializers]
+
+ }
+
+// [[[ begin generated region: do not modify [Generated Contents]
+TDes& TSymbian_ua_guiSettingItemListSettings::Ed_registrar()
+ {
+ return iEd_registrar;
+ }
+
+void TSymbian_ua_guiSettingItemListSettings::SetEd_registrar(const TDesC& aValue)
+ {
+ if ( aValue.Length() < KEd_registrarMaxLength)
+ iEd_registrar.Copy( aValue );
+ else
+ iEd_registrar.Copy( aValue.Ptr(), KEd_registrarMaxLength);
+ }
+
+TDes& TSymbian_ua_guiSettingItemListSettings::Ed_user()
+ {
+ return iEd_user;
+ }
+
+void TSymbian_ua_guiSettingItemListSettings::SetEd_user(const TDesC& aValue)
+ {
+ if ( aValue.Length() < KEd_userMaxLength)
+ iEd_user.Copy( aValue );
+ else
+ iEd_user.Copy( aValue.Ptr(), KEd_userMaxLength);
+ }
+
+TDes& TSymbian_ua_guiSettingItemListSettings::Ed_password()
+ {
+ return iEd_password;
+ }
+
+void TSymbian_ua_guiSettingItemListSettings::SetEd_password(const TDesC& aValue)
+ {
+ if ( aValue.Length() < KEd_passwordMaxLength)
+ iEd_password.Copy( aValue );
+ else
+ iEd_password.Copy( aValue.Ptr(), KEd_passwordMaxLength);
+ }
+
+TBool& TSymbian_ua_guiSettingItemListSettings::B_srtp()
+ {
+ return iB_srtp;
+ }
+
+void TSymbian_ua_guiSettingItemListSettings::SetB_srtp(const TBool& aValue)
+ {
+ iB_srtp = aValue;
+ }
+
+TBool& TSymbian_ua_guiSettingItemListSettings::B_ice()
+ {
+ return iB_ice;
+ }
+
+void TSymbian_ua_guiSettingItemListSettings::SetB_ice(const TBool& aValue)
+ {
+ iB_ice = aValue;
+ }
+
+TDes& TSymbian_ua_guiSettingItemListSettings::Ed_stun_server()
+ {
+ return iEd_stun_server;
+ }
+
+void TSymbian_ua_guiSettingItemListSettings::SetEd_stun_server(const TDesC& aValue)
+ {
+ if ( aValue.Length() < KEd_stun_serverMaxLength)
+ iEd_stun_server.Copy( aValue );
+ else
+ iEd_stun_server.Copy( aValue.Ptr(), KEd_stun_serverMaxLength);
+ }
+
+// ]]] end generated region [Generated Contents]
+
diff --git a/pjsip-apps/src/symbian_ua_gui/src/symbian_ua.cpp b/pjsip-apps/src/symbian_ua_gui/src/symbian_ua.cpp
new file mode 100644
index 0000000..79e81f2
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/src/symbian_ua.cpp
@@ -0,0 +1,514 @@
+/* $Id: ua.cpp 1793 2008-02-14 13:39:24Z bennylp $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <pjsua-lib/pjsua.h>
+#include <pjsua-lib/pjsua_internal.h>
+#include <es_sock.h>
+#include "symbian_ua.h"
+
+#define THIS_FILE "symbian_ua.cpp"
+#define LOG_LEVEL 3
+
+#define SIP_PORT 5060
+#define USE_ICE 0
+#define USE_SRTP PJSUA_DEFAULT_USE_SRTP
+
+static RSocketServ aSocketServer;
+static RConnection aConn;
+
+static pjsua_acc_id g_acc_id = PJSUA_INVALID_ID;
+static pjsua_call_id g_call_id = PJSUA_INVALID_ID;
+static pjsua_buddy_id g_buddy_id = PJSUA_INVALID_ID;
+
+static symbian_ua_info_cb_t g_cb = {NULL, NULL, NULL, NULL, NULL};
+
+static void log_writer(int level, const char *buf, int len)
+{
+ static wchar_t buf16[PJ_LOG_MAX_SIZE];
+
+ PJ_UNUSED_ARG(level);
+
+ if (!g_cb.on_info)
+ return;
+
+ pj_ansi_to_unicode(buf, len, buf16, PJ_ARRAY_SIZE(buf16));
+ g_cb.on_info(buf16);
+}
+
+static void on_reg_state(pjsua_acc_id acc_id)
+{
+ pjsua_acc_info acc_info;
+ pj_status_t status;
+
+ status = pjsua_acc_get_info(acc_id, &acc_info);
+ if (status != PJ_SUCCESS)
+ return;
+
+ if (acc_info.status == 200) {
+ if (acc_info.expires) {
+ PJ_LOG(3,(THIS_FILE, "Registration success!"));
+ if (g_cb.on_reg_state) g_cb.on_reg_state(true);
+ } else {
+ PJ_LOG(3,(THIS_FILE, "Unregistration success!"));
+ if (g_cb.on_unreg_state) g_cb.on_unreg_state(true);
+ }
+ } else {
+ if (acc_info.expires) {
+ PJ_LOG(3,(THIS_FILE, "Registration failed!"));
+ if (g_cb.on_reg_state) g_cb.on_reg_state(false);
+ } else {
+ PJ_LOG(3,(THIS_FILE, "Unregistration failed!"));
+ if (g_cb.on_unreg_state) g_cb.on_unreg_state(false);
+ }
+ }
+}
+
+/* Callback called by the library upon receiving incoming call */
+static void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id,
+ pjsip_rx_data *rdata)
+{
+ pjsua_call_info ci;
+
+ PJ_UNUSED_ARG(acc_id);
+ PJ_UNUSED_ARG(rdata);
+
+ if (g_call_id != PJSUA_INVALID_ID) {
+ pjsua_call_answer(call_id, PJSIP_SC_BUSY_HERE, NULL, NULL);
+ return;
+ }
+
+ pjsua_call_get_info(call_id, &ci);
+
+ PJ_LOG(3,(THIS_FILE, "Incoming call from %.*s!!",
+ (int)ci.remote_info.slen,
+ ci.remote_info.ptr));
+
+ g_call_id = call_id;
+
+ /* Automatically answer incoming calls with 180/Ringing */
+ pjsua_call_answer(call_id, 180, NULL, NULL);
+
+ if (g_cb.on_incoming_call) {
+ static wchar_t disp[256];
+ static wchar_t uri[PJSIP_MAX_URL_SIZE];
+
+ pj_ansi_to_unicode(ci.remote_info.ptr, ci.remote_info.slen,
+ disp, PJ_ARRAY_SIZE(disp));
+ pj_ansi_to_unicode(ci.remote_contact.ptr, ci.remote_contact.slen,
+ uri, PJ_ARRAY_SIZE(uri));
+
+ g_cb.on_incoming_call(disp, uri);
+ }
+}
+
+/* Callback called by the library when call's state has changed */
+static void on_call_state(pjsua_call_id call_id, pjsip_event *e)
+{
+ pjsua_call_info ci;
+
+ PJ_UNUSED_ARG(e);
+
+ pjsua_call_get_info(call_id, &ci);
+
+ if (ci.state == PJSIP_INV_STATE_DISCONNECTED) {
+ if (call_id == g_call_id)
+ g_call_id = PJSUA_INVALID_ID;
+ if (g_cb.on_call_end) {
+ static wchar_t reason[256];
+ pj_ansi_to_unicode(ci.last_status_text.ptr, ci.last_status_text.slen,
+ reason, PJ_ARRAY_SIZE(reason));
+ g_cb.on_call_end(reason);
+ }
+
+ } else if (ci.state != PJSIP_INV_STATE_INCOMING) {
+ if (g_call_id == PJSUA_INVALID_ID)
+ g_call_id = call_id;
+ }
+
+ PJ_LOG(3,(THIS_FILE, "Call %d state=%.*s", call_id,
+ (int)ci.state_text.slen,
+ ci.state_text.ptr));
+}
+
+/* Callback called by the library when call's media state has changed */
+static void on_call_media_state(pjsua_call_id call_id)
+{
+ pjsua_call_info ci;
+
+ pjsua_call_get_info(call_id, &ci);
+
+ if (ci.media_status == PJSUA_CALL_MEDIA_ACTIVE) {
+ // When media is active, connect call to sound device.
+ pjsua_conf_connect(ci.conf_slot, 0);
+ pjsua_conf_connect(0, ci.conf_slot);
+ }
+}
+
+
+/* Handler on buddy state changed. */
+static void on_buddy_state(pjsua_buddy_id buddy_id)
+{
+ pjsua_buddy_info info;
+ pjsua_buddy_get_info(buddy_id, &info);
+
+ PJ_LOG(3,(THIS_FILE, "%.*s status is %.*s",
+ (int)info.uri.slen,
+ info.uri.ptr,
+ (int)info.status_text.slen,
+ info.status_text.ptr));
+}
+
+
+/* Incoming IM message (i.e. MESSAGE request)! */
+static void on_pager(pjsua_call_id call_id, const pj_str_t *from,
+ const pj_str_t *to, const pj_str_t *contact,
+ const pj_str_t *mime_type, const pj_str_t *text)
+{
+ /* Note: call index may be -1 */
+ PJ_UNUSED_ARG(call_id);
+ PJ_UNUSED_ARG(to);
+ PJ_UNUSED_ARG(contact);
+ PJ_UNUSED_ARG(mime_type);
+
+ PJ_LOG(3,(THIS_FILE,"MESSAGE from %.*s: %.*s",
+ (int)from->slen, from->ptr,
+ (int)text->slen, text->ptr));
+}
+
+
+/* Received typing indication */
+static void on_typing(pjsua_call_id call_id, const pj_str_t *from,
+ const pj_str_t *to, const pj_str_t *contact,
+ pj_bool_t is_typing)
+{
+ PJ_UNUSED_ARG(call_id);
+ PJ_UNUSED_ARG(to);
+ PJ_UNUSED_ARG(contact);
+
+ PJ_LOG(3,(THIS_FILE, "IM indication: %.*s %s",
+ (int)from->slen, from->ptr,
+ (is_typing?"is typing..":"has stopped typing")));
+}
+
+
+/* Call transfer request status. */
+static void on_call_transfer_status(pjsua_call_id call_id,
+ int status_code,
+ const pj_str_t *status_text,
+ pj_bool_t final,
+ pj_bool_t *p_cont)
+{
+ PJ_LOG(3,(THIS_FILE, "Call %d: transfer status=%d (%.*s) %s",
+ call_id, status_code,
+ (int)status_text->slen, status_text->ptr,
+ (final ? "[final]" : "")));
+
+ if (status_code/100 == 2) {
+ PJ_LOG(3,(THIS_FILE,
+ "Call %d: call transfered successfully, disconnecting call",
+ call_id));
+ pjsua_call_hangup(call_id, PJSIP_SC_GONE, NULL, NULL);
+ *p_cont = PJ_FALSE;
+ }
+}
+
+
+/* NAT detection result */
+static void on_nat_detect(const pj_stun_nat_detect_result *res)
+{
+ if (res->status != PJ_SUCCESS) {
+ pjsua_perror(THIS_FILE, "NAT detection failed", res->status);
+ } else {
+ PJ_LOG(3, (THIS_FILE, "NAT detected as %s", res->nat_type_name));
+ }
+}
+
+/* Notification that call is being replaced. */
+static void on_call_replaced(pjsua_call_id old_call_id,
+ pjsua_call_id new_call_id)
+{
+ pjsua_call_info old_ci, new_ci;
+
+ pjsua_call_get_info(old_call_id, &old_ci);
+ pjsua_call_get_info(new_call_id, &new_ci);
+
+ PJ_LOG(3,(THIS_FILE, "Call %d with %.*s is being replaced by "
+ "call %d with %.*s",
+ old_call_id,
+ (int)old_ci.remote_info.slen, old_ci.remote_info.ptr,
+ new_call_id,
+ (int)new_ci.remote_info.slen, new_ci.remote_info.ptr));
+}
+
+int symbian_ua_init()
+{
+ TInt err;
+ pj_symbianos_params sym_params;
+ pj_status_t status;
+
+ // Initialize RSocketServ
+ if ((err=aSocketServer.Connect(32)) != KErrNone)
+ return PJ_STATUS_FROM_OS(err);
+
+ // Open up a connection
+ if ((err=aConn.Open(aSocketServer)) != KErrNone) {
+ aSocketServer.Close();
+ return PJ_STATUS_FROM_OS(err);
+ }
+
+ if ((err=aConn.Start()) != KErrNone) {
+ aConn.Close();
+ aSocketServer.Close();
+ return PJ_STATUS_FROM_OS(err);
+ }
+
+ // Set Symbian OS parameters in pjlib.
+ // This must be done before pj_init() is called.
+ pj_bzero(&sym_params, sizeof(sym_params));
+ sym_params.rsocketserv = &aSocketServer;
+ sym_params.rconnection = &aConn;
+ pj_symbianos_set_params(&sym_params);
+
+ /* Redirect log before pjsua_init() */
+ pj_log_set_log_func(&log_writer);
+
+ /* Set log level */
+ pj_log_set_level(LOG_LEVEL);
+
+ /* Create pjsua first! */
+ status = pjsua_create();
+ if (status != PJ_SUCCESS) {
+ pjsua_perror(THIS_FILE, "pjsua_create() error", status);
+ return status;
+ }
+
+ /* Init pjsua */
+ pjsua_config cfg;
+
+ pjsua_config_default(&cfg);
+ cfg.max_calls = 2;
+ cfg.thread_cnt = 0; // Disable threading on Symbian
+ cfg.use_srtp = USE_SRTP;
+ cfg.srtp_secure_signaling = 0;
+
+ cfg.cb.on_incoming_call = &on_incoming_call;
+ cfg.cb.on_call_media_state = &on_call_media_state;
+ cfg.cb.on_call_state = &on_call_state;
+ cfg.cb.on_buddy_state = &on_buddy_state;
+ cfg.cb.on_pager = &on_pager;
+ cfg.cb.on_typing = &on_typing;
+ cfg.cb.on_call_transfer_status = &on_call_transfer_status;
+ cfg.cb.on_call_replaced = &on_call_replaced;
+ cfg.cb.on_nat_detect = &on_nat_detect;
+ cfg.cb.on_reg_state = &on_reg_state;
+
+ pjsua_media_config med_cfg;
+
+ pjsua_media_config_default(&med_cfg);
+ med_cfg.thread_cnt = 0; // Disable threading on Symbian
+ med_cfg.has_ioqueue = PJ_FALSE;
+ med_cfg.clock_rate = 8000;
+#if defined(PJMEDIA_SYM_SND_USE_APS) && (PJMEDIA_SYM_SND_USE_APS==1)
+ med_cfg.audio_frame_ptime = 20;
+#else
+ med_cfg.audio_frame_ptime = 40;
+#endif
+ med_cfg.ec_tail_len = 0;
+ med_cfg.enable_ice = USE_ICE;
+ med_cfg.snd_auto_close_time = 5; // wait for 5 seconds idle before sound dev get auto-closed
+
+ pjsua_logging_config log_cfg;
+
+ pjsua_logging_config_default(&log_cfg);
+ log_cfg.console_level = LOG_LEVEL;
+ log_cfg.cb = &log_writer;
+ log_cfg.decor = 0;
+
+ status = pjsua_init(&cfg, &log_cfg, &med_cfg);
+ if (status != PJ_SUCCESS) {
+ pjsua_perror(THIS_FILE, "pjsua_init() error", status);
+ pjsua_destroy();
+ return status;
+ }
+
+ /* Add UDP transport. */
+ pjsua_transport_config tcfg;
+ pjsua_transport_id tid;
+
+ pjsua_transport_config_default(&tcfg);
+ tcfg.port = SIP_PORT;
+ status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, &tcfg, &tid);
+ if (status != PJ_SUCCESS) {
+ pjsua_perror(THIS_FILE, "Error creating transport", status);
+ pjsua_destroy();
+ return status;
+ }
+
+ /* Add account for the transport */
+ pjsua_acc_add_local(tid, PJ_TRUE, &g_acc_id);
+
+ /* Initialization is done, now start pjsua */
+ status = pjsua_start();
+ if (status != PJ_SUCCESS) {
+ pjsua_perror(THIS_FILE, "Error starting pjsua", status);
+ pjsua_destroy();
+ return status;
+ }
+
+ /* Adjust Speex priority and enable only the narrowband */
+ {
+ pj_str_t codec_id = pj_str("speex/8000");
+ pjmedia_codec_mgr_set_codec_priority(
+ pjmedia_endpt_get_codec_mgr(pjsua_var.med_endpt),
+ &codec_id, PJMEDIA_CODEC_PRIO_NORMAL+1);
+
+ codec_id = pj_str("speex/16000");
+ pjmedia_codec_mgr_set_codec_priority(
+ pjmedia_endpt_get_codec_mgr(pjsua_var.med_endpt),
+ &codec_id, PJMEDIA_CODEC_PRIO_DISABLED);
+
+ codec_id = pj_str("speex/32000");
+ pjmedia_codec_mgr_set_codec_priority(
+ pjmedia_endpt_get_codec_mgr(pjsua_var.med_endpt),
+ &codec_id, PJMEDIA_CODEC_PRIO_DISABLED);
+ }
+
+ return PJ_SUCCESS;
+}
+
+
+int symbian_ua_destroy()
+{
+ // Shutdown pjsua
+ pjsua_destroy();
+
+ // Close connection and socket server
+ aConn.Close();
+ aSocketServer.Close();
+
+ CloseSTDLIB();
+
+ return PJ_SUCCESS;
+}
+
+void symbian_ua_set_info_callback(const symbian_ua_info_cb_t *cb)
+{
+ if (cb)
+ g_cb = *cb;
+ else
+ pj_bzero(&g_cb, sizeof(g_cb));
+}
+
+int symbian_ua_set_account(const char *domain, const char *username,
+ const char *password,
+ bool use_srtp, bool use_ice)
+{
+ pj_status_t status;
+
+ PJ_ASSERT_RETURN(username && password && domain, PJ_EINVAL);
+ PJ_UNUSED_ARG(use_srtp);
+ PJ_UNUSED_ARG(use_ice);
+
+ if (domain[0] == 0) {
+ pjsua_acc_info acc_info;
+ pj_status_t status;
+
+ status = pjsua_acc_get_info(g_acc_id, &acc_info);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ if (acc_info.status == 200) {
+ PJ_LOG(3,(THIS_FILE, "Unregistering.."));
+ pjsua_acc_set_registration(g_acc_id, PJ_FALSE);
+ g_acc_id = 0;
+ }
+ return PJ_SUCCESS;
+ }
+
+ if (pjsua_acc_get_count() > 1) {
+ status = pjsua_acc_del(g_acc_id);
+ if (status != PJ_SUCCESS) {
+ pjsua_perror(THIS_FILE, "Error removing account", status);
+ return status;
+ }
+ g_acc_id = 0;
+ }
+
+ pjsua_acc_config cfg;
+ char tmp_id[PJSIP_MAX_URL_SIZE];
+ char tmp_reg_uri[PJSIP_MAX_URL_SIZE];
+
+ if (!pj_ansi_strnicmp(domain, "sip:", 4)) {
+ domain += 4;
+ }
+
+ pjsua_acc_config_default(&cfg);
+ pj_ansi_sprintf(tmp_id, "sip:%s@%s", username, domain);
+ cfg.id = pj_str(tmp_id);
+ pj_ansi_sprintf(tmp_reg_uri, "sip:%s", domain);
+ cfg.reg_uri = pj_str(tmp_reg_uri);
+ cfg.cred_count = 1;
+ cfg.cred_info[0].realm = pj_str("*");
+ cfg.cred_info[0].scheme = pj_str("digest");
+ cfg.cred_info[0].username = pj_str((char*)username);
+ cfg.cred_info[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
+ cfg.cred_info[0].data = pj_str((char*)password);
+
+ status = pjsua_acc_add(&cfg, PJ_TRUE, &g_acc_id);
+ if (status != PJ_SUCCESS) {
+ pjsua_perror(THIS_FILE, "Error setting account", status);
+ pjsua_destroy();
+ return status;
+ }
+
+ return PJ_SUCCESS;
+}
+
+int symbian_ua_makecall(const char* dest_url)
+{
+ if (pjsua_verify_url(dest_url) == PJ_SUCCESS) {
+ pj_str_t dst = pj_str((char*)dest_url);
+ pjsua_call_make_call(g_acc_id, &dst, 0, NULL,
+ NULL, &g_call_id);
+
+ return PJ_SUCCESS;
+ }
+
+ return PJ_EINVAL;
+}
+
+int symbian_ua_endcall()
+{
+ pjsua_call_hangup_all();
+
+ return PJ_SUCCESS;
+}
+
+bool symbian_ua_anycall()
+{
+ return (pjsua_call_get_count()>0);
+}
+
+int symbian_ua_answercall()
+{
+ PJ_ASSERT_RETURN (g_call_id != PJSUA_INVALID_ID, PJ_EINVAL);
+
+ return pjsua_call_answer(g_call_id, 200, NULL, NULL);
+}
+
diff --git a/pjsip-apps/src/symbian_ua_gui/src/symbian_ua_guiAppUi.cpp b/pjsip-apps/src/symbian_ua_gui/src/symbian_ua_guiAppUi.cpp
new file mode 100644
index 0000000..276ffa3
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/src/symbian_ua_guiAppUi.cpp
@@ -0,0 +1,257 @@
+/* $Id: symbian_ua_guiAppUi.cpp 3550 2011-05-05 05:33:27Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+// [[[ begin generated region: do not modify [Generated System Includes]
+#include <eikmenub.h>
+#include <akncontext.h>
+#include <akntitle.h>
+#include <symbian_ua_gui.rsg>
+// ]]] end generated region [Generated System Includes]
+
+// [[[ begin generated region: do not modify [Generated User Includes]
+#include "symbian_ua_guiAppUi.h"
+#include "symbian_ua_gui.hrh"
+#include "symbian_ua_guiContainer.hrh"
+#include "symbian_ua_guiSettingItemList.hrh"
+#include "symbian_ua_guiContainerView.h"
+#include "symbian_ua_guiSettingItemListView.h"
+// ]]] end generated region [Generated User Includes]
+
+// [[[ begin generated region: do not modify [Generated Constants]
+// ]]] end generated region [Generated Constants]
+
+#include "symbian_ua.h"
+
+/**
+ * Construct the Csymbian_ua_guiAppUi instance
+ */
+Csymbian_ua_guiAppUi::Csymbian_ua_guiAppUi() : CTimer(0)
+ {
+ // [[[ begin generated region: do not modify [Generated Contents]
+ // ]]] end generated region [Generated Contents]
+
+ }
+
+/**
+ * The appui's destructor removes the container from the control
+ * stack and destroys it.
+ */
+Csymbian_ua_guiAppUi::~Csymbian_ua_guiAppUi()
+ {
+ // [[[ begin generated region: do not modify [Generated Contents]
+ TRAPD( err_Dlg_wait_init, RemoveDlg_wait_initL() );
+ // ]]] end generated region [Generated Contents]
+ }
+
+// [[[ begin generated function: do not modify
+void Csymbian_ua_guiAppUi::InitializeContainersL()
+ {
+ iSymbian_ua_guiContainerView = Csymbian_ua_guiContainerView::NewL();
+ AddViewL( iSymbian_ua_guiContainerView );
+ iSymbian_ua_guiSettingItemListView = Csymbian_ua_guiSettingItemListView::NewL();
+ AddViewL( iSymbian_ua_guiSettingItemListView );
+ SetDefaultViewL( *iSymbian_ua_guiSettingItemListView );
+ }
+// ]]] end generated function
+
+/**
+ * Handle a command for this appui (override)
+ * @param aCommand command id to be handled
+ */
+void Csymbian_ua_guiAppUi::HandleCommandL( TInt aCommand )
+ {
+ // [[[ begin generated region: do not modify [Generated Code]
+ TBool commandHandled = EFalse;
+ switch ( aCommand )
+ { // code to dispatch to the AppUi's menu and CBA commands is generated here
+ default:
+ break;
+ }
+
+
+ if ( !commandHandled )
+ {
+ if ( aCommand == EAknSoftkeyExit || aCommand == EEikCmdExit )
+ {
+ symbian_ua_destroy();
+ Exit();
+ }
+ }
+ // ]]] end generated region [Generated Code]
+
+ }
+
+/**
+ * Override of the HandleResourceChangeL virtual function
+ */
+void Csymbian_ua_guiAppUi::HandleResourceChangeL( TInt aType )
+ {
+ CAknViewAppUi::HandleResourceChangeL( aType );
+ // [[[ begin generated region: do not modify [Generated Code]
+ // ]]] end generated region [Generated Code]
+
+ }
+
+/**
+ * Override of the HandleKeyEventL virtual function
+ * @return EKeyWasConsumed if event was handled, EKeyWasNotConsumed if not
+ * @param aKeyEvent
+ * @param aType
+ */
+TKeyResponse Csymbian_ua_guiAppUi::HandleKeyEventL(
+ const TKeyEvent& aKeyEvent,
+ TEventCode aType )
+ {
+ // The inherited HandleKeyEventL is private and cannot be called
+ // [[[ begin generated region: do not modify [Generated Contents]
+ // ]]] end generated region [Generated Contents]
+
+ return EKeyWasNotConsumed;
+ }
+
+/**
+ * Override of the HandleViewDeactivation virtual function
+ *
+ * @param aViewIdToBeDeactivated
+ * @param aNewlyActivatedViewId
+ */
+void Csymbian_ua_guiAppUi::HandleViewDeactivation(
+ const TVwsViewId& aViewIdToBeDeactivated,
+ const TVwsViewId& aNewlyActivatedViewId )
+ {
+ CAknViewAppUi::HandleViewDeactivation(
+ aViewIdToBeDeactivated,
+ aNewlyActivatedViewId );
+ // [[[ begin generated region: do not modify [Generated Contents]
+ // ]]] end generated region [Generated Contents]
+
+ }
+
+/**
+ * @brief Completes the second phase of Symbian object construction.
+ * Put initialization code that could leave here.
+ */
+void Csymbian_ua_guiAppUi::ConstructL()
+ {
+ // [[[ begin generated region: do not modify [Generated Contents]
+ BaseConstructL( EAknEnableSkin );
+ InitializeContainersL();
+ // ]]] end generated region [Generated Contents]
+
+ // Create private folder
+ RProcess process;
+ TFileName path;
+
+ path.Copy( process.FileName().Left(2) );
+
+ if(path.Compare(_L("c")) || path.Compare(_L("C")))
+ CEikonEnv::Static()->FsSession().CreatePrivatePath(EDriveC);
+ else if(path.Compare(_L("e")) || path.Compare(_L("E")))
+ CEikonEnv::Static()->FsSession().CreatePrivatePath(EDriveE);
+
+ // Init PJSUA
+ if (symbian_ua_init() != 0) {
+ symbian_ua_destroy();
+ Exit();
+ }
+
+ ExecuteDlg_wait_initLD();
+
+ CTimer::ConstructL();
+ CActiveScheduler::Add( this );
+ After(4000000);
+ }
+
+/**
+ * Override of the HandleApplicationSpecificEventL virtual function
+ */
+void Csymbian_ua_guiAppUi::HandleApplicationSpecificEventL(
+ TInt aType,
+ const TWsEvent& anEvent )
+ {
+ CAknViewAppUi::HandleApplicationSpecificEventL( aType, anEvent );
+ // [[[ begin generated region: do not modify [Generated Code]
+ // ]]] end generated region [Generated Code]
+
+ }
+
+/**
+ * Handle the applicationSpecificEvent event.
+ */
+void Csymbian_ua_guiAppUi::HandleSymbian_ua_guiAppUiApplicationSpecificEventL(
+ TInt /* aType */,
+ const TWsEvent& /* anEvent */ )
+ {
+ // TODO: implement applicationSpecificEvent event handler
+ }
+
+// [[[ begin generated function: do not modify
+/**
+ * Execute the wait dialog for dlg_wait_init. This routine returns
+ * while the dialog is showing. It will be closed and destroyed when
+ * RemoveDlg_wait_initL() or the user selects the Cancel soft key.
+ * @param aOverrideText optional override text. When null the text configured
+ * in the UI Designer is used.
+ */
+void Csymbian_ua_guiAppUi::ExecuteDlg_wait_initLD( const TDesC* aOverrideText )
+ {
+ iDlg_wait_init = new ( ELeave ) CAknWaitDialog(
+ reinterpret_cast< CEikDialog** >( &iDlg_wait_init ), EFalse );
+ if ( aOverrideText != NULL )
+ {
+ iDlg_wait_init->SetTextL( *aOverrideText );
+ }
+ iDlg_wait_init->ExecuteLD( R_APPLICATION_DLG_WAIT_INIT );
+ iDlg_wait_initCallback = new ( ELeave ) CProgressDialogCallback(
+ this, iDlg_wait_init, &Csymbian_ua_guiAppUi::HandleDlg_wait_initCanceledL );
+ iDlg_wait_init->SetCallback( iDlg_wait_initCallback );
+ }
+// ]]] end generated function
+
+// [[[ begin generated function: do not modify
+/**
+ * Close and dispose of the wait dialog for dlg_wait_init
+ */
+void Csymbian_ua_guiAppUi::RemoveDlg_wait_initL()
+ {
+ if ( iDlg_wait_init != NULL )
+ {
+ iDlg_wait_init->SetCallback( NULL );
+ iDlg_wait_init->ProcessFinishedL(); // deletes the dialog
+ iDlg_wait_init = NULL;
+ }
+ delete iDlg_wait_initCallback;
+ iDlg_wait_initCallback = NULL;
+
+ }
+// ]]] end generated function
+
+/**
+ * Handle the canceled event.
+ */
+void Csymbian_ua_guiAppUi::HandleDlg_wait_initCanceledL( CAknProgressDialog* /* aDialog */ )
+ {
+ // TODO: implement canceled event handler
+
+ }
+
+void Csymbian_ua_guiAppUi::RunL()
+ {
+ RemoveDlg_wait_initL();
+ iSymbian_ua_guiSettingItemListView->HandleCommandL(EAknSoftkeySave);
+ }
diff --git a/pjsip-apps/src/symbian_ua_gui/src/symbian_ua_guiApplication.cpp b/pjsip-apps/src/symbian_ua_gui/src/symbian_ua_guiApplication.cpp
new file mode 100644
index 0000000..2ccbbb2
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/src/symbian_ua_guiApplication.cpp
@@ -0,0 +1,96 @@
+/* $Id: symbian_ua_guiApplication.cpp 3550 2011-05-05 05:33:27Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+// [[[ begin generated region: do not modify [Generated System Includes]
+// ]]] end generated region [Generated System Includes]
+
+// [[[ begin generated region: do not modify [Generated Includes]
+#include "symbian_ua_guiApplication.h"
+#include "symbian_ua_guiDocument.h"
+#ifdef EKA2
+#include <eikstart.h>
+#endif
+// ]]] end generated region [Generated Includes]
+
+
+// Needed by APS
+TPtrC APP_UID = _L("EBD12EE4");
+
+/**
+ * @brief Returns the application's UID (override from CApaApplication::AppDllUid())
+ * @return UID for this application (KUidsymbian_ua_guiApplication)
+ */
+TUid Csymbian_ua_guiApplication::AppDllUid() const
+ {
+ return KUidsymbian_ua_guiApplication;
+ }
+
+/**
+ * @brief Creates the application's document (override from CApaApplication::CreateDocumentL())
+ * @return Pointer to the created document object (Csymbian_ua_guiDocument)
+ */
+CApaDocument* Csymbian_ua_guiApplication::CreateDocumentL()
+ {
+ return Csymbian_ua_guiDocument::NewL( *this );
+ }
+
+#ifdef EKA2
+
+/**
+ * @brief Called by the application framework to construct the application object
+ * @return The application (Csymbian_ua_guiApplication)
+ */
+LOCAL_C CApaApplication* NewApplication()
+ {
+ return new Csymbian_ua_guiApplication;
+ }
+
+/**
+* @brief This standard export is the entry point for all Series 60 applications
+* @return error code
+ */
+GLDEF_C TInt E32Main()
+ {
+ TInt err;
+
+ err = EikStart::RunApplication( NewApplication );
+
+ return err;
+ }
+
+#else // Series 60 2.x main DLL program code
+
+/**
+* @brief This standard export constructs the application object.
+* @return The application (Csymbian_ua_guiApplication)
+*/
+EXPORT_C CApaApplication* NewApplication()
+ {
+ return new Csymbian_ua_guiApplication;
+ }
+
+/**
+* @brief This standard export is the entry point for all Series 60 applications
+* @return error code
+*/
+GLDEF_C TInt E32Dll(TDllReason /*reason*/)
+ {
+ return KErrNone;
+ }
+
+#endif // EKA2
diff --git a/pjsip-apps/src/symbian_ua_gui/src/symbian_ua_guiContainer.cpp b/pjsip-apps/src/symbian_ua_gui/src/symbian_ua_guiContainer.cpp
new file mode 100644
index 0000000..94fc98a
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/src/symbian_ua_guiContainer.cpp
@@ -0,0 +1,295 @@
+/* $Id: symbian_ua_guiContainer.cpp 3550 2011-05-05 05:33:27Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+// [[[ begin generated region: do not modify [Generated System Includes]
+#include <barsread.h>
+#include <stringloader.h>
+#include <eiklabel.h>
+#include <eikenv.h>
+#include <gdi.h>
+#include <eikedwin.h>
+#include <aknviewappui.h>
+#include <eikappui.h>
+#include <symbian_ua_gui.rsg>
+// ]]] end generated region [Generated System Includes]
+
+// [[[ begin generated region: do not modify [Generated User Includes]
+#include "symbian_ua_guiContainer.h"
+#include "symbian_ua_guiContainerView.h"
+#include "symbian_ua_gui.hrh"
+#include "symbian_ua_guiContainer.hrh"
+#include "symbian_ua_guiSettingItemList.hrh"
+// ]]] end generated region [Generated User Includes]
+
+// [[[ begin generated region: do not modify [Generated Constants]
+// ]]] end generated region [Generated Constants]
+
+/**
+ * First phase of Symbian two-phase construction. Should not
+ * contain any code that could leave.
+ */
+CSymbian_ua_guiContainer::CSymbian_ua_guiContainer()
+ {
+ // [[[ begin generated region: do not modify [Generated Contents]
+ iLabel1 = NULL;
+ iEd_url = NULL;
+ iEd_info = NULL;
+ // ]]] end generated region [Generated Contents]
+
+ }
+/**
+ * Destroy child controls.
+ */
+CSymbian_ua_guiContainer::~CSymbian_ua_guiContainer()
+ {
+ // [[[ begin generated region: do not modify [Generated Contents]
+ delete iLabel1;
+ iLabel1 = NULL;
+ delete iEd_url;
+ iEd_url = NULL;
+ delete iEd_info;
+ iEd_info = NULL;
+ // ]]] end generated region [Generated Contents]
+
+ }
+
+/**
+ * Construct the control (first phase).
+ * Creates an instance and initializes it.
+ * Instance is not left on cleanup stack.
+ * @param aRect bounding rectangle
+ * @param aParent owning parent, or NULL
+ * @param aCommandObserver command observer
+ * @return initialized instance of CSymbian_ua_guiContainer
+ */
+CSymbian_ua_guiContainer* CSymbian_ua_guiContainer::NewL(
+ const TRect& aRect,
+ const CCoeControl* aParent,
+ MEikCommandObserver* aCommandObserver )
+ {
+ CSymbian_ua_guiContainer* self = CSymbian_ua_guiContainer::NewLC(
+ aRect,
+ aParent,
+ aCommandObserver );
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+/**
+ * Construct the control (first phase).
+ * Creates an instance and initializes it.
+ * Instance is left on cleanup stack.
+ * @param aRect The rectangle for this window
+ * @param aParent owning parent, or NULL
+ * @param aCommandObserver command observer
+ * @return new instance of CSymbian_ua_guiContainer
+ */
+CSymbian_ua_guiContainer* CSymbian_ua_guiContainer::NewLC(
+ const TRect& aRect,
+ const CCoeControl* aParent,
+ MEikCommandObserver* aCommandObserver )
+ {
+ CSymbian_ua_guiContainer* self = new ( ELeave ) CSymbian_ua_guiContainer();
+ CleanupStack::PushL( self );
+ self->ConstructL( aRect, aParent, aCommandObserver );
+ return self;
+ }
+
+/**
+ * Construct the control (second phase).
+ * Creates a window to contain the controls and activates it.
+ * @param aRect bounding rectangle
+ * @param aCommandObserver command observer
+ * @param aParent owning parent, or NULL
+ */
+void CSymbian_ua_guiContainer::ConstructL(
+ const TRect& aRect,
+ const CCoeControl* aParent,
+ MEikCommandObserver* aCommandObserver )
+ {
+ if ( aParent == NULL )
+ {
+ CreateWindowL();
+ }
+ else
+ {
+ SetContainerWindowL( *aParent );
+ }
+ iFocusControl = NULL;
+ iCommandObserver = aCommandObserver;
+ InitializeControlsL();
+ SetRect( aRect );
+ ActivateL();
+ // [[[ begin generated region: do not modify [Post-ActivateL initializations]
+ // ]]] end generated region [Post-ActivateL initializations]
+
+ }
+
+/**
+* Return the number of controls in the container (override)
+* @return count
+*/
+TInt CSymbian_ua_guiContainer::CountComponentControls() const
+ {
+ return ( int ) ELastControl;
+ }
+
+/**
+* Get the control with the given index (override)
+* @param aIndex Control index [0...n) (limited by #CountComponentControls)
+* @return Pointer to control
+*/
+CCoeControl* CSymbian_ua_guiContainer::ComponentControl( TInt aIndex ) const
+ {
+ // [[[ begin generated region: do not modify [Generated Contents]
+ switch ( aIndex )
+ {
+ case ELabel1:
+ return iLabel1;
+ case EEd_url:
+ return iEd_url;
+ case EEd_info:
+ return iEd_info;
+ }
+ // ]]] end generated region [Generated Contents]
+
+ // handle any user controls here...
+
+ return NULL;
+ }
+
+/**
+ * Handle resizing of the container. This implementation will lay out
+ * full-sized controls like list boxes for any screen size, and will layout
+ * labels, editors, etc. to the size they were given in the UI designer.
+ * This code will need to be modified to adjust arbitrary controls to
+ * any screen size.
+ */
+void CSymbian_ua_guiContainer::SizeChanged()
+ {
+ CCoeControl::SizeChanged();
+ LayoutControls();
+ // [[[ begin generated region: do not modify [Generated Contents]
+
+ // ]]] end generated region [Generated Contents]
+
+ }
+
+// [[[ begin generated function: do not modify
+/**
+ * Layout components as specified in the UI Designer
+ */
+void CSymbian_ua_guiContainer::LayoutControls()
+ {
+ iLabel1->SetExtent( TPoint( 2, 23 ), TSize( 32, 28 ) );
+ iEd_url->SetExtent( TPoint( 49, 25 ), TSize( 197, 28 ) );
+ iEd_info->SetExtent( TPoint( 3, 78 ), TSize( 235, 143 ) );
+ }
+// ]]] end generated function
+
+/**
+ * Handle key events.
+ */
+TKeyResponse CSymbian_ua_guiContainer::OfferKeyEventL(
+ const TKeyEvent& aKeyEvent,
+ TEventCode aType )
+ {
+ // [[[ begin generated region: do not modify [Generated Contents]
+
+ // ]]] end generated region [Generated Contents]
+
+ if ( iFocusControl != NULL
+ && iFocusControl->OfferKeyEventL( aKeyEvent, aType ) == EKeyWasConsumed )
+ {
+ return EKeyWasConsumed;
+ }
+ return CCoeControl::OfferKeyEventL( aKeyEvent, aType );
+ }
+
+// [[[ begin generated function: do not modify
+/**
+ * Initialize each control upon creation.
+ */
+void CSymbian_ua_guiContainer::InitializeControlsL()
+ {
+ iLabel1 = new ( ELeave ) CEikLabel;
+ iLabel1->SetContainerWindowL( *this );
+ {
+ TResourceReader reader;
+ iEikonEnv->CreateResourceReaderLC( reader, R_SYMBIAN_UA_GUI_CONTAINER_LABEL1 );
+ iLabel1->ConstructFromResourceL( reader );
+ CleanupStack::PopAndDestroy(); // reader internal state
+ }
+ iEd_url = new ( ELeave ) CEikEdwin;
+ iEd_url->SetContainerWindowL( *this );
+ {
+ TResourceReader reader;
+ iEikonEnv->CreateResourceReaderLC( reader, R_SYMBIAN_UA_GUI_CONTAINER_ED_URL );
+ iEd_url->ConstructFromResourceL( reader );
+ CleanupStack::PopAndDestroy(); // reader internal state
+ }
+ {
+ HBufC* text = StringLoader::LoadLC( R_SYMBIAN_UA_GUI_CONTAINER_ED_URL_2 );
+ iEd_url->SetTextL( text );
+ CleanupStack::PopAndDestroy( text );
+ }
+ iEd_info = new ( ELeave ) CEikEdwin;
+ iEd_info->SetContainerWindowL( *this );
+ {
+ TResourceReader reader;
+ iEikonEnv->CreateResourceReaderLC( reader, R_SYMBIAN_UA_GUI_CONTAINER_ED_INFO );
+ iEd_info->ConstructFromResourceL( reader );
+ CleanupStack::PopAndDestroy(); // reader internal state
+ }
+ {
+ HBufC* text = StringLoader::LoadLC( R_SYMBIAN_UA_GUI_CONTAINER_ED_INFO_2 );
+ iEd_info->SetTextL( text );
+ CleanupStack::PopAndDestroy( text );
+ }
+
+ iEd_url->SetFocus( ETrue );
+ iFocusControl = iEd_url;
+
+ }
+// ]]] end generated function
+
+/**
+ * Handle global resource changes, such as scalable UI or skin events (override)
+ */
+void CSymbian_ua_guiContainer::HandleResourceChange( TInt aType )
+ {
+ CCoeControl::HandleResourceChange( aType );
+ SetRect( iAvkonViewAppUi->View( TUid::Uid( ESymbian_ua_guiContainerViewId ) )->ClientRect() );
+ // [[[ begin generated region: do not modify [Generated Contents]
+ // ]]] end generated region [Generated Contents]
+
+ }
+
+/**
+ * Draw container contents.
+ */
+void CSymbian_ua_guiContainer::Draw( const TRect& aRect ) const
+ {
+ // [[[ begin generated region: do not modify [Generated Contents]
+ CWindowGc& gc = SystemGc();
+ gc.Clear( aRect );
+
+ // ]]] end generated region [Generated Contents]
+
+ }
+
diff --git a/pjsip-apps/src/symbian_ua_gui/src/symbian_ua_guiContainerView.cpp b/pjsip-apps/src/symbian_ua_gui/src/symbian_ua_guiContainerView.cpp
new file mode 100644
index 0000000..0fae4f6
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/src/symbian_ua_guiContainerView.cpp
@@ -0,0 +1,488 @@
+/* $Id: symbian_ua_guiContainerView.cpp 3550 2011-05-05 05:33:27Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+// [[[ begin generated region: do not modify [Generated System Includes]
+#include <aknviewappui.h>
+#include <eikmenub.h>
+#include <avkon.hrh>
+#include <barsread.h>
+#include <stringloader.h>
+#include <eiklabel.h>
+#include <eikenv.h>
+#include <gdi.h>
+#include <eikedwin.h>
+#include <akncontext.h>
+#include <akntitle.h>
+#include <eikbtgpc.h>
+#include <aknnotewrappers.h>
+#include <aknquerydialog.h>
+#include <symbian_ua_gui.rsg>
+// ]]] end generated region [Generated System Includes]
+
+// [[[ begin generated region: do not modify [Generated User Includes]
+#include "symbian_ua_gui.hrh"
+#include "symbian_ua_guiContainerView.h"
+#include "symbian_ua_guiContainer.hrh"
+#include "symbian_ua_guiSettingItemList.hrh"
+#include "symbian_ua_guiContainer.h"
+// ]]] end generated region [Generated User Includes]
+
+#include <utf.h>
+#include "symbian_ua.h"
+
+// [[[ begin generated region: do not modify [Generated Constants]
+// ]]] end generated region [Generated Constants]
+
+Csymbian_ua_guiContainerView *myinstance = NULL;
+_LIT(KStCall, "Call");
+_LIT(KStHangUp, "Hang Up");
+
+void on_info(const wchar_t* buf)
+{
+ TPtrC aBuf((const TUint16*)buf);
+
+ if (myinstance)
+ myinstance->PutMessage(aBuf);
+}
+
+void on_incoming_call(const wchar_t* caller_disp, const wchar_t* caller_uri)
+{
+ TBuf<512> buf;
+ TPtrC aDisp((const TUint16*)caller_disp);
+ TPtrC aUri((const TUint16*)caller_uri);
+ _LIT(KFormat, "Incoming call from %S, accept?");
+
+ buf.Format(KFormat, &aDisp);
+ if (Csymbian_ua_guiContainerView::RunQry_accept_callL(&buf) == EAknSoftkeyYes)
+ {
+ CEikButtonGroupContainer* cba = CEikButtonGroupContainer::Current();
+ if (cba != NULL) {
+ TRAPD(result, cba->SetCommandL(ESymbian_ua_guiContainerViewControlPaneRightId, KStHangUp));
+ cba->DrawDeferred();
+ }
+ symbian_ua_answercall();
+ } else {
+ symbian_ua_endcall();
+ }
+}
+
+void on_call_end(const wchar_t* reason)
+{
+ TPtrC aReason((const TUint16*)reason);
+
+ CEikButtonGroupContainer* cba = CEikButtonGroupContainer::Current();
+ if (cba != NULL) {
+ TRAPD(result, cba->SetCommandL(ESymbian_ua_guiContainerViewControlPaneRightId, KStCall));
+ cba->DrawDeferred();
+ }
+
+ Csymbian_ua_guiContainerView::RunNote_infoL(&aReason);
+}
+
+void on_reg_state(bool success)
+{
+ if (success)
+ Csymbian_ua_guiContainerView::RunNote_infoL();
+ else
+ Csymbian_ua_guiContainerView::RunNote_warningL();
+}
+
+void on_unreg_state(bool success)
+{
+ TPtrC st_success(_L("Unregistration Success!"));
+ TPtrC st_failed(_L("Unregistration Failed!"));
+
+ if (success)
+ Csymbian_ua_guiContainerView::RunNote_infoL(&st_success);
+ else
+ Csymbian_ua_guiContainerView::RunNote_warningL(&st_failed);
+}
+
+void Csymbian_ua_guiContainerView::PutMessage(const TDesC &msg)
+ {
+ if (!iSymbian_ua_guiContainer)
+ return;
+
+ CEikEdwin *obj_info = (CEikEdwin*) iSymbian_ua_guiContainer->ComponentControl(iSymbian_ua_guiContainer->EEd_info);
+
+ obj_info->SetTextL(&msg);
+ obj_info->DrawDeferred();
+ }
+
+/**
+ * First phase of Symbian two-phase construction. Should not contain any
+ * code that could leave.
+ */
+Csymbian_ua_guiContainerView::Csymbian_ua_guiContainerView()
+ {
+ // [[[ begin generated region: do not modify [Generated Contents]
+ iSymbian_ua_guiContainer = NULL;
+ // ]]] end generated region [Generated Contents]
+
+ }
+/**
+ * The view's destructor removes the container from the control
+ * stack and destroys it.
+ */
+Csymbian_ua_guiContainerView::~Csymbian_ua_guiContainerView()
+ {
+ // [[[ begin generated region: do not modify [Generated Contents]
+ delete iSymbian_ua_guiContainer;
+ iSymbian_ua_guiContainer = NULL;
+ // ]]] end generated region [Generated Contents]
+
+ symbian_ua_set_info_callback(NULL);
+ myinstance = NULL;
+ }
+
+/**
+ * Symbian two-phase constructor.
+ * This creates an instance then calls the second-phase constructor
+ * without leaving the instance on the cleanup stack.
+ * @return new instance of Csymbian_ua_guiContainerView
+ */
+Csymbian_ua_guiContainerView* Csymbian_ua_guiContainerView::NewL()
+ {
+ Csymbian_ua_guiContainerView* self = Csymbian_ua_guiContainerView::NewLC();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+/**
+ * Symbian two-phase constructor.
+ * This creates an instance, pushes it on the cleanup stack,
+ * then calls the second-phase constructor.
+ * @return new instance of Csymbian_ua_guiContainerView
+ */
+Csymbian_ua_guiContainerView* Csymbian_ua_guiContainerView::NewLC()
+ {
+ Csymbian_ua_guiContainerView* self = new ( ELeave ) Csymbian_ua_guiContainerView();
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ return self;
+ }
+
+
+/**
+ * Second-phase constructor for view.
+ * Initialize contents from resource.
+ */
+void Csymbian_ua_guiContainerView::ConstructL()
+ {
+ // [[[ begin generated region: do not modify [Generated Code]
+ BaseConstructL( R_SYMBIAN_UA_GUI_CONTAINER_SYMBIAN_UA_GUI_CONTAINER_VIEW );
+ // ]]] end generated region [Generated Code]
+
+ // add your own initialization code here
+ symbian_ua_info_cb_t cb;
+ Mem::FillZ(&cb, sizeof(cb));
+
+ cb.on_info = &on_info;
+ cb.on_incoming_call = &on_incoming_call;
+ cb.on_reg_state = &on_reg_state;
+ cb.on_unreg_state = &on_unreg_state;
+ cb.on_call_end = &on_call_end;
+
+ symbian_ua_set_info_callback(&cb);
+ myinstance = this;
+ }
+
+/**
+ * @return The UID for this view
+ */
+TUid Csymbian_ua_guiContainerView::Id() const
+ {
+ return TUid::Uid( ESymbian_ua_guiContainerViewId );
+ }
+
+/**
+ * Handle a command for this view (override)
+ * @param aCommand command id to be handled
+ */
+void Csymbian_ua_guiContainerView::HandleCommandL( TInt aCommand )
+ {
+ // [[[ begin generated region: do not modify [Generated Code]
+ TBool commandHandled = EFalse;
+ switch ( aCommand )
+ { // code to dispatch to the AknView's menu and CBA commands is generated here
+
+ case ESymbian_ua_guiContainerViewControlPaneRightId:
+ commandHandled = CallSoftKeyPressedL( aCommand );
+ break;
+ case ESymbian_ua_guiContainerViewSettingMenuItemCommand:
+ commandHandled = HandleSettingMenuItemSelectedL( aCommand );
+ break;
+ default:
+ break;
+ }
+
+
+ if ( !commandHandled )
+ {
+
+ if ( aCommand == ESymbian_ua_guiContainerViewControlPaneRightId )
+ {
+ AppUi()->HandleCommandL( EEikCmdExit );
+ }
+
+ }
+ // ]]] end generated region [Generated Code]
+
+ }
+
+/**
+ * Handles user actions during activation of the view,
+ * such as initializing the content.
+ */
+void Csymbian_ua_guiContainerView::DoActivateL(
+ const TVwsViewId& /*aPrevViewId*/,
+ TUid /*aCustomMessageId*/,
+ const TDesC8& /*aCustomMessage*/ )
+ {
+ // [[[ begin generated region: do not modify [Generated Contents]
+ SetupStatusPaneL();
+
+ CEikButtonGroupContainer* cba = AppUi()->Cba();
+ if ( cba != NULL )
+ {
+ cba->MakeVisible( EFalse );
+ }
+
+ if ( iSymbian_ua_guiContainer == NULL )
+ {
+ iSymbian_ua_guiContainer = CSymbian_ua_guiContainer::NewL( ClientRect(), NULL, this );
+ iSymbian_ua_guiContainer->SetMopParent( this );
+ AppUi()->AddToStackL( *this, iSymbian_ua_guiContainer );
+ }
+ // ]]] end generated region [Generated Contents]
+
+ cba = CEikButtonGroupContainer::Current();
+ if (cba != NULL) {
+ if (symbian_ua_anycall())
+ cba->SetCommandL(ESymbian_ua_guiContainerViewControlPaneRightId, KStHangUp);
+ else
+ cba->SetCommandL(ESymbian_ua_guiContainerViewControlPaneRightId, KStCall);
+ }
+
+ }
+
+/**
+ */
+void Csymbian_ua_guiContainerView::DoDeactivate()
+ {
+ // [[[ begin generated region: do not modify [Generated Contents]
+ CleanupStatusPane();
+
+ CEikButtonGroupContainer* cba = AppUi()->Cba();
+ if ( cba != NULL )
+ {
+ cba->MakeVisible( ETrue );
+ cba->DrawDeferred();
+ }
+
+ if ( iSymbian_ua_guiContainer != NULL )
+ {
+ AppUi()->RemoveFromViewStack( *this, iSymbian_ua_guiContainer );
+ delete iSymbian_ua_guiContainer;
+ iSymbian_ua_guiContainer = NULL;
+ }
+ // ]]] end generated region [Generated Contents]
+
+ }
+
+// [[[ begin generated function: do not modify
+void Csymbian_ua_guiContainerView::SetupStatusPaneL()
+ {
+ // reset the context pane
+ TUid contextPaneUid = TUid::Uid( EEikStatusPaneUidContext );
+ CEikStatusPaneBase::TPaneCapabilities subPaneContext =
+ StatusPane()->PaneCapabilities( contextPaneUid );
+ if ( subPaneContext.IsPresent() && subPaneContext.IsAppOwned() )
+ {
+ CAknContextPane* context = static_cast< CAknContextPane* > (
+ StatusPane()->ControlL( contextPaneUid ) );
+ context->SetPictureToDefaultL();
+ }
+
+ // setup the title pane
+ TUid titlePaneUid = TUid::Uid( EEikStatusPaneUidTitle );
+ CEikStatusPaneBase::TPaneCapabilities subPaneTitle =
+ StatusPane()->PaneCapabilities( titlePaneUid );
+ if ( subPaneTitle.IsPresent() && subPaneTitle.IsAppOwned() )
+ {
+ CAknTitlePane* title = static_cast< CAknTitlePane* >(
+ StatusPane()->ControlL( titlePaneUid ) );
+ TResourceReader reader;
+ iEikonEnv->CreateResourceReaderLC( reader, R_SYMBIAN_UA_GUI_CONTAINER_TITLE_RESOURCE );
+ title->SetFromResourceL( reader );
+ CleanupStack::PopAndDestroy(); // reader internal state
+ }
+
+ }
+// ]]] end generated function
+
+// [[[ begin generated function: do not modify
+void Csymbian_ua_guiContainerView::CleanupStatusPane()
+ {
+ }
+// ]]] end generated function
+
+/**
+ * Handle status pane size change for this view (override)
+ */
+void Csymbian_ua_guiContainerView::HandleStatusPaneSizeChange()
+ {
+ CAknView::HandleStatusPaneSizeChange();
+
+ // this may fail, but we're not able to propagate exceptions here
+ TInt result;
+ TRAP( result, SetupStatusPaneL() );
+ }
+
+/**
+ * Handle the rightSoftKeyPressed event.
+ * @return ETrue if the command was handled, EFalse if not
+ */
+TBool Csymbian_ua_guiContainerView::CallSoftKeyPressedL( TInt aCommand )
+ {
+ CEikEdwin *obj_url = (CEikEdwin*) iSymbian_ua_guiContainer->ComponentControl(iSymbian_ua_guiContainer->EEd_url);
+ CEikButtonGroupContainer* cba = CEikButtonGroupContainer::Current();
+
+ if (symbian_ua_anycall()) {
+ symbian_ua_endcall();
+ return ETrue;
+ }
+
+ PutMessage(_L("Making call..."));
+ if ( cba != NULL ) {
+ cba->SetCommandL(aCommand, KStHangUp);
+ cba->DrawDeferred();
+ }
+
+
+ TUint8 url[256];
+ TPtr8 aUrl(url, 256);
+
+ HBufC *buf = obj_url->GetTextInHBufL();
+ CnvUtfConverter::ConvertFromUnicodeToUtf8(aUrl, *buf);
+ delete buf;
+
+ if (symbian_ua_makecall((char *)aUrl.PtrZ()) != 0) {
+ PutMessage(_L("Making call failed!"));
+ if ( cba != NULL ) {
+ cba->SetCommandL(aCommand, KStCall);
+ cba->DrawDeferred();
+ }
+ }
+
+ return ETrue;
+ }
+
+/**
+ * Handle the selected event.
+ * @param aCommand the command id invoked
+ * @return ETrue if the command was handled, EFalse if not
+ */
+TBool Csymbian_ua_guiContainerView::HandleSettingMenuItemSelectedL( TInt aCommand )
+ {
+ AppUi()->ActivateLocalViewL(TUid::Uid(ESymbian_ua_guiSettingItemListViewId));
+ return ETrue;
+ }
+
+// [[[ begin generated function: do not modify
+/**
+ * Show the popup note for note_error
+ * @param aOverrideText optional override text
+ */
+void Csymbian_ua_guiContainerView::RunNote_errorL( const TDesC* aOverrideText )
+ {
+ CAknErrorNote* note = new ( ELeave ) CAknErrorNote();
+ if ( aOverrideText == NULL )
+ {
+ HBufC* noteText = StringLoader::LoadLC( R_SYMBIAN_UA_GUI_CONTAINER_NOTE_ERROR );
+ note->ExecuteLD( *noteText );
+ CleanupStack::PopAndDestroy( noteText );
+ }
+ else
+ {
+ note->ExecuteLD( *aOverrideText );
+ }
+ }
+// ]]] end generated function
+
+// [[[ begin generated function: do not modify
+/**
+ * Show the popup note for note_info
+ * @param aOverrideText optional override text
+ */
+void Csymbian_ua_guiContainerView::RunNote_infoL( const TDesC* aOverrideText )
+ {
+ CAknInformationNote* note = new ( ELeave ) CAknInformationNote();
+ if ( aOverrideText == NULL )
+ {
+ HBufC* noteText = StringLoader::LoadLC( R_SYMBIAN_UA_GUI_CONTAINER_NOTE_INFO );
+ note->ExecuteLD( *noteText );
+ CleanupStack::PopAndDestroy( noteText );
+ }
+ else
+ {
+ note->ExecuteLD( *aOverrideText );
+ }
+ }
+// ]]] end generated function
+
+// [[[ begin generated function: do not modify
+/**
+ * Show the popup note for note_warning
+ * @param aOverrideText optional override text
+ */
+void Csymbian_ua_guiContainerView::RunNote_warningL( const TDesC* aOverrideText )
+ {
+ CAknWarningNote* note = new ( ELeave ) CAknWarningNote();
+ if ( aOverrideText == NULL )
+ {
+ HBufC* noteText = StringLoader::LoadLC( R_SYMBIAN_UA_GUI_CONTAINER_NOTE_WARNING );
+ note->ExecuteLD( *noteText );
+ CleanupStack::PopAndDestroy( noteText );
+ }
+ else
+ {
+ note->ExecuteLD( *aOverrideText );
+ }
+ }
+// ]]] end generated function
+
+// [[[ begin generated function: do not modify
+/**
+ * Show the popup dialog for qry_accept_call
+ * @param aOverrideText optional override text
+ * @return EAknSoftkeyYes (left soft key id) or 0
+ */
+TInt Csymbian_ua_guiContainerView::RunQry_accept_callL( const TDesC* aOverrideText )
+ {
+
+ CAknQueryDialog* queryDialog = CAknQueryDialog::NewL();
+
+ if ( aOverrideText != NULL )
+ {
+ queryDialog->SetPromptL( *aOverrideText );
+ }
+ return queryDialog->ExecuteLD( R_SYMBIAN_UA_GUI_CONTAINER_QRY_ACCEPT_CALL );
+ }
+// ]]] end generated function
+
diff --git a/pjsip-apps/src/symbian_ua_gui/src/symbian_ua_guiDocument.cpp b/pjsip-apps/src/symbian_ua_gui/src/symbian_ua_guiDocument.cpp
new file mode 100644
index 0000000..906577c
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/src/symbian_ua_guiDocument.cpp
@@ -0,0 +1,67 @@
+/* $Id: symbian_ua_guiDocument.cpp 3550 2011-05-05 05:33:27Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+// [[[ begin generated region: do not modify [Generated User Includes]
+#include "symbian_ua_guiDocument.h"
+#include "symbian_ua_guiAppUi.h"
+// ]]] end generated region [Generated User Includes]
+
+/**
+ * @brief Constructs the document class for the application.
+ * @param anApplication the application instance
+ */
+Csymbian_ua_guiDocument::Csymbian_ua_guiDocument( CEikApplication& anApplication )
+ : CAknDocument( anApplication )
+ {
+ }
+
+/**
+ * @brief Completes the second phase of Symbian object construction.
+ * Put initialization code that could leave here.
+ */
+void Csymbian_ua_guiDocument::ConstructL()
+ {
+ }
+
+/**
+ * Symbian OS two-phase constructor.
+ *
+ * Creates an instance of Csymbian_ua_guiDocument, constructs it, and
+ * returns it.
+ *
+ * @param aApp the application instance
+ * @return the new Csymbian_ua_guiDocument
+ */
+Csymbian_ua_guiDocument* Csymbian_ua_guiDocument::NewL( CEikApplication& aApp )
+ {
+ Csymbian_ua_guiDocument* self = new ( ELeave ) Csymbian_ua_guiDocument( aApp );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+/**
+ * @brief Creates the application UI object for this document.
+ * @return the new instance
+ */
+CEikAppUi* Csymbian_ua_guiDocument::CreateAppUiL()
+ {
+ return new ( ELeave ) Csymbian_ua_guiAppUi;
+ }
+
diff --git a/pjsip-apps/src/symbian_ua_gui/src/symbian_ua_guiSettingItemList.cpp b/pjsip-apps/src/symbian_ua_gui/src/symbian_ua_guiSettingItemList.cpp
new file mode 100644
index 0000000..48f86d3
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/src/symbian_ua_guiSettingItemList.cpp
@@ -0,0 +1,433 @@
+/* $Id: symbian_ua_guiSettingItemList.cpp 3550 2011-05-05 05:33:27Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+// [[[ begin generated region: do not modify [Generated System Includes]
+#include <avkon.hrh>
+#include <avkon.rsg>
+#include <eikmenup.h>
+#include <aknappui.h>
+#include <eikcmobs.h>
+#include <barsread.h>
+#include <stringloader.h>
+#include <gdi.h>
+#include <eikedwin.h>
+#include <eikenv.h>
+#include <eikseced.h>
+#include <aknpopupfieldtext.h>
+#include <eikappui.h>
+#include <aknviewappui.h>
+#include <akntextsettingpage.h>
+#include <symbian_ua_gui.rsg>
+// ]]] end generated region [Generated System Includes]
+
+// [[[ begin generated region: do not modify [Generated User Includes]
+#include "symbian_ua_guiSettingItemList.h"
+#include "Symbian_ua_guiSettingItemListSettings.h"
+#include "symbian_ua_guiSettingItemList.hrh"
+#include "symbian_ua_gui.hrh"
+#include "symbian_ua_guiSettingItemListView.h"
+// ]]] end generated region [Generated User Includes]
+
+
+#include <s32stor.h>
+#include <s32file.h>
+
+
+// [[[ begin generated region: do not modify [Generated Constants]
+// ]]] end generated region [Generated Constants]
+
+
+_LIT(KtxDicFileName ,"settings.ini" );
+
+const TInt KRegistrar = 2;
+const TInt KUsername = 3;
+const TInt KPassword = 4;
+const TInt KStunServer = 5;
+const TInt KSrtp = 6;
+const TInt KIce = 7;
+
+/**
+ * Construct the CSymbian_ua_guiSettingItemList instance
+ * @param aCommandObserver command observer
+ */
+CSymbian_ua_guiSettingItemList::CSymbian_ua_guiSettingItemList(
+ TSymbian_ua_guiSettingItemListSettings& aSettings,
+ MEikCommandObserver* aCommandObserver )
+ : iSettings( aSettings ), iCommandObserver( aCommandObserver )
+ {
+ // [[[ begin generated region: do not modify [Generated Contents]
+ // ]]] end generated region [Generated Contents]
+
+ }
+/**
+ * Destroy any instance variables
+ */
+CSymbian_ua_guiSettingItemList::~CSymbian_ua_guiSettingItemList()
+ {
+ // [[[ begin generated region: do not modify [Generated Contents]
+ // ]]] end generated region [Generated Contents]
+
+ }
+
+/**
+ * Handle system notification that the container's size has changed.
+ */
+void CSymbian_ua_guiSettingItemList::SizeChanged()
+ {
+ if ( ListBox() )
+ {
+ ListBox()->SetRect( Rect() );
+ }
+ }
+
+/**
+ * Create one setting item at a time, identified by id.
+ * CAknSettingItemList calls this method and takes ownership
+ * of the returned value. The CAknSettingItem object owns
+ * a reference to the underlying data, which EditItemL() uses
+ * to edit and store the value.
+ */
+CAknSettingItem* CSymbian_ua_guiSettingItemList::CreateSettingItemL( TInt aId )
+ {
+ switch ( aId )
+ {
+ // [[[ begin generated region: do not modify [Initializers]
+ case ESymbian_ua_guiSettingItemListViewEd_registrar:
+ {
+ CAknTextSettingItem* item = new ( ELeave )
+ CAknTextSettingItem(
+ aId,
+ iSettings.Ed_registrar() );
+ item->SetSettingPageFlags(CAknTextSettingPage::EZeroLengthAllowed);
+ return item;
+ }
+ case ESymbian_ua_guiSettingItemListViewEd_user:
+ {
+ CAknTextSettingItem* item = new ( ELeave )
+ CAknTextSettingItem(
+ aId,
+ iSettings.Ed_user() );
+ item->SetSettingPageFlags(CAknTextSettingPage::EZeroLengthAllowed);
+ return item;
+ }
+ case ESymbian_ua_guiSettingItemListViewEd_password:
+ {
+ CAknPasswordSettingItem* item = new ( ELeave )
+ CAknPasswordSettingItem(
+ aId,
+ CAknPasswordSettingItem::EAlpha,
+ iSettings.Ed_password() );
+ item->SetSettingPageFlags(CAknTextSettingPage::EZeroLengthAllowed);
+ return item;
+ }
+ case ESymbian_ua_guiSettingItemListViewB_srtp:
+ {
+ CAknBinaryPopupSettingItem* item = new ( ELeave )
+ CAknBinaryPopupSettingItem(
+ aId,
+ iSettings.B_srtp() );
+ item->SetHidden( ETrue );
+ return item;
+ }
+ case ESymbian_ua_guiSettingItemListViewB_ice:
+ {
+ CAknBinaryPopupSettingItem* item = new ( ELeave )
+ CAknBinaryPopupSettingItem(
+ aId,
+ iSettings.B_ice() );
+ item->SetHidden( ETrue );
+ return item;
+ }
+ case ESymbian_ua_guiSettingItemListViewEd_stun_server:
+ {
+ CAknTextSettingItem* item = new ( ELeave )
+ CAknTextSettingItem(
+ aId,
+ iSettings.Ed_stun_server() );
+ item->SetHidden( ETrue );
+ return item;
+ }
+ // ]]] end generated region [Initializers]
+
+ }
+
+ return NULL;
+ }
+
+/**
+ * Edit the setting item identified by the given id and store
+ * the changes into the store.
+ * @param aIndex the index of the setting item in SettingItemArray()
+ * @param aCalledFromMenu true: a menu item invoked editing, thus
+ * always show the edit page and interactively edit the item;
+ * false: change the item in place if possible, else show the edit page
+ */
+void CSymbian_ua_guiSettingItemList::EditItemL ( TInt aIndex, TBool aCalledFromMenu )
+ {
+ CAknSettingItem* item = ( *SettingItemArray() )[aIndex];
+ switch ( item->Identifier() )
+ {
+ // [[[ begin generated region: do not modify [Editing Started Invoker]
+ // ]]] end generated region [Editing Started Invoker]
+
+ }
+
+ CAknSettingItemList::EditItemL( aIndex, aCalledFromMenu );
+
+ TBool storeValue = ETrue;
+ switch ( item->Identifier() )
+ {
+ // [[[ begin generated region: do not modify [Editing Stopped Invoker]
+ // ]]] end generated region [Editing Stopped Invoker]
+
+ }
+
+ if ( storeValue )
+ {
+ item->StoreL();
+ SaveSettingValuesL();
+ }
+ }
+/**
+ * Handle the "Change" option on the Options menu. This is an
+ * alternative to the Selection key that forces the settings page
+ * to come up rather than changing the value in place (if possible).
+ */
+void CSymbian_ua_guiSettingItemList::ChangeSelectedItemL()
+ {
+ if ( ListBox()->CurrentItemIndex() >= 0 )
+ {
+ EditItemL( ListBox()->CurrentItemIndex(), ETrue );
+ }
+ }
+
+/**
+ * Load the initial contents of the setting items. By default,
+ * the setting items are populated with the default values from
+ * the design. You can override those values here.
+ * <p>
+ * Note: this call alone does not update the UI.
+ * LoadSettingsL() must be called afterwards.
+ */
+void CSymbian_ua_guiSettingItemList::LoadSettingValuesL()
+ {
+ // load values into iSettings
+
+ TFileName path;
+ TFileName pathWithoutDrive;
+ CEikonEnv::Static()->FsSession().PrivatePath( pathWithoutDrive );
+
+ // Extract drive letter into appDrive:
+#ifdef __WINS__
+ path.Copy( _L("c:") );
+#else
+ RProcess process;
+ path.Copy( process.FileName().Left(2) );
+#endif
+
+ path.Append( pathWithoutDrive );
+ path.Append( KtxDicFileName );
+
+ TFindFile AufFolder(CCoeEnv::Static()->FsSession());
+ if(KErrNone == AufFolder.FindByDir(path, KNullDesC))
+ {
+ CDictionaryFileStore* MyDStore = CDictionaryFileStore::OpenLC(CCoeEnv::Static()->FsSession(),AufFolder.File(), TUid::Uid(1));
+ TUid FileUid;
+
+ FileUid.iUid = KRegistrar;
+ if(MyDStore->IsPresentL(FileUid))
+ {
+ RDictionaryReadStream in;
+ in.OpenLC(*MyDStore,FileUid);
+ in >> iSettings.Ed_registrar();
+ CleanupStack::PopAndDestroy(1);// in
+ }
+
+ FileUid.iUid = KUsername;
+ if(MyDStore->IsPresentL(FileUid))
+ {
+ RDictionaryReadStream in;
+ in.OpenLC(*MyDStore,FileUid);
+ in >> iSettings.Ed_user();
+ CleanupStack::PopAndDestroy(1);// in
+ }
+
+ FileUid.iUid = KPassword;
+ if(MyDStore->IsPresentL(FileUid))
+ {
+ RDictionaryReadStream in;
+ in.OpenLC(*MyDStore,FileUid);
+ in >> iSettings.Ed_password();
+ CleanupStack::PopAndDestroy(1);// in
+ }
+
+ FileUid.iUid = KStunServer;
+ if(MyDStore->IsPresentL(FileUid))
+ {
+ RDictionaryReadStream in;
+ in.OpenLC(*MyDStore,FileUid);
+ in >> iSettings.Ed_stun_server();
+ CleanupStack::PopAndDestroy(1);// in
+ }
+
+ FileUid.iUid = KSrtp;
+ if(MyDStore->IsPresentL(FileUid))
+ {
+ RDictionaryReadStream in;
+ in.OpenLC(*MyDStore,FileUid);
+ iSettings.SetB_srtp((TBool)in.ReadInt32L());
+ CleanupStack::PopAndDestroy(1);// in
+ }
+
+ FileUid.iUid = KIce;
+ if(MyDStore->IsPresentL(FileUid))
+ {
+ RDictionaryReadStream in;
+ in.OpenLC(*MyDStore,FileUid);
+ iSettings.SetB_ice((TBool)in.ReadInt32L());
+ CleanupStack::PopAndDestroy(1);// in
+ }
+
+ CleanupStack::PopAndDestroy(1);// Store
+ }
+
+ }
+
+/**
+ * Save the contents of the setting items. Note, this is called
+ * whenever an item is changed and stored to the model, so it
+ * may be called multiple times or not at all.
+ */
+void CSymbian_ua_guiSettingItemList::SaveSettingValuesL()
+ {
+ // store values from iSettings
+
+ TFileName path;
+ TFileName pathWithoutDrive;
+ CEikonEnv::Static()->FsSession().PrivatePath( pathWithoutDrive );
+
+ // Extract drive letter into appDrive:
+#ifdef __WINS__
+ path.Copy( _L("c:") );
+#else
+ RProcess process;
+ path.Copy( process.FileName().Left(2) );
+
+ if(path.Compare(_L("c")) || path.Compare(_L("C")))
+ CEikonEnv::Static()->FsSession().CreatePrivatePath(EDriveC);
+ else if(path.Compare(_L("e")) || path.Compare(_L("E")))
+ CEikonEnv::Static()->FsSession().CreatePrivatePath(EDriveE);
+#endif
+
+ path.Append( pathWithoutDrive );
+ path.Append( KtxDicFileName );
+
+ TFindFile AufFolder(CCoeEnv::Static()->FsSession());
+ if(KErrNone == AufFolder.FindByDir(path, KNullDesC))
+ {
+ User::LeaveIfError(CCoeEnv::Static()->FsSession().Delete(AufFolder.File()));
+ }
+
+ CDictionaryFileStore* MyDStore = CDictionaryFileStore::OpenLC(CCoeEnv::Static()->FsSession(),path, TUid::Uid(1));
+
+ TUid FileUid = {0x0};
+
+ FileUid.iUid = KRegistrar;
+ RDictionaryWriteStream out1;
+ out1.AssignLC(*MyDStore,FileUid);
+ out1 << iSettings.Ed_registrar();
+ out1.CommitL();
+ CleanupStack::PopAndDestroy(1);// out2
+
+ FileUid.iUid = KUsername;
+ RDictionaryWriteStream out2;
+ out2.AssignLC(*MyDStore,FileUid);
+ out2 << iSettings.Ed_user();
+ out2.CommitL();
+ CleanupStack::PopAndDestroy(1);// out2
+
+ FileUid.iUid = KPassword;
+ RDictionaryWriteStream out3;
+ out3.AssignLC(*MyDStore,FileUid);
+ out3 << iSettings.Ed_password();
+ out3.CommitL();
+ CleanupStack::PopAndDestroy(1);// out2
+
+ FileUid.iUid = KStunServer;
+ RDictionaryWriteStream out4;
+ out4.AssignLC(*MyDStore,FileUid);
+ out4 << iSettings.Ed_stun_server();
+ out4.CommitL();
+ CleanupStack::PopAndDestroy(1);// out2
+
+ FileUid.iUid = KSrtp;
+ RDictionaryWriteStream out5;
+ out5.AssignLC(*MyDStore,FileUid);
+ out5.WriteInt32L(iSettings.B_srtp());
+ out5.CommitL();
+ CleanupStack::PopAndDestroy(1);// out1
+
+ FileUid.iUid = KIce;
+ RDictionaryWriteStream out6;
+ out6.AssignLC(*MyDStore,FileUid);
+ out6.WriteInt32L(iSettings.B_ice());
+ out6.CommitL();
+ CleanupStack::PopAndDestroy(1);// out1
+
+ MyDStore->CommitL();
+ CleanupStack::PopAndDestroy(1);// Store
+
+ }
+
+
+/**
+ * Handle global resource changes, such as scalable UI or skin events (override)
+ */
+void CSymbian_ua_guiSettingItemList::HandleResourceChange( TInt aType )
+ {
+ CAknSettingItemList::HandleResourceChange( aType );
+ SetRect( iAvkonViewAppUi->View( TUid::Uid( ESymbian_ua_guiSettingItemListViewId ) )->ClientRect() );
+ // [[[ begin generated region: do not modify [Generated Contents]
+ // ]]] end generated region [Generated Contents]
+
+ }
+
+/**
+ * Handle key event (override)
+ * @param aKeyEvent key event
+ * @param aType event code
+ * @return EKeyWasConsumed if the event was handled, else EKeyWasNotConsumed
+ */
+TKeyResponse CSymbian_ua_guiSettingItemList::OfferKeyEventL(
+ const TKeyEvent& aKeyEvent,
+ TEventCode aType )
+ {
+ // [[[ begin generated region: do not modify [Generated Contents]
+ // ]]] end generated region [Generated Contents]
+
+ if ( aKeyEvent.iCode == EKeyLeftArrow
+ || aKeyEvent.iCode == EKeyRightArrow )
+ {
+ // allow the tab control to get the arrow keys
+ return EKeyWasNotConsumed;
+ }
+
+ return CAknSettingItemList::OfferKeyEventL( aKeyEvent, aType );
+ }
+
diff --git a/pjsip-apps/src/symbian_ua_gui/src/symbian_ua_guiSettingItemListView.cpp b/pjsip-apps/src/symbian_ua_gui/src/symbian_ua_guiSettingItemListView.cpp
new file mode 100644
index 0000000..aa8155d
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/src/symbian_ua_guiSettingItemListView.cpp
@@ -0,0 +1,295 @@
+/* $Id: symbian_ua_guiSettingItemListView.cpp 3550 2011-05-05 05:33:27Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+// [[[ begin generated region: do not modify [Generated System Includes]
+#include <aknviewappui.h>
+#include <eikmenub.h>
+#include <avkon.hrh>
+#include <akncontext.h>
+#include <akntitle.h>
+#include <stringloader.h>
+#include <barsread.h>
+#include <eikbtgpc.h>
+#include <symbian_ua_gui.rsg>
+// ]]] end generated region [Generated System Includes]
+
+// [[[ begin generated region: do not modify [Generated User Includes]
+#include "symbian_ua_gui.hrh"
+#include "symbian_ua_guiSettingItemListView.h"
+#include "symbian_ua_guiContainer.hrh"
+#include "symbian_ua_guiSettingItemList.hrh"
+#include "symbian_ua_guiSettingItemList.h"
+// ]]] end generated region [Generated User Includes]
+
+#include "symbian_ua.h"
+
+// [[[ begin generated region: do not modify [Generated Constants]
+// ]]] end generated region [Generated Constants]
+
+/**
+ * First phase of Symbian two-phase construction. Should not contain any
+ * code that could leave.
+ */
+Csymbian_ua_guiSettingItemListView::Csymbian_ua_guiSettingItemListView()
+ {
+ // [[[ begin generated region: do not modify [Generated Contents]
+ // ]]] end generated region [Generated Contents]
+
+ }
+/**
+ * The view's destructor removes the container from the control
+ * stack and destroys it.
+ */
+Csymbian_ua_guiSettingItemListView::~Csymbian_ua_guiSettingItemListView()
+ {
+ // [[[ begin generated region: do not modify [Generated Contents]
+ // ]]] end generated region [Generated Contents]
+
+ }
+
+/**
+ * Symbian two-phase constructor.
+ * This creates an instance then calls the second-phase constructor
+ * without leaving the instance on the cleanup stack.
+ * @return new instance of Csymbian_ua_guiSettingItemListView
+ */
+Csymbian_ua_guiSettingItemListView* Csymbian_ua_guiSettingItemListView::NewL()
+ {
+ Csymbian_ua_guiSettingItemListView* self = Csymbian_ua_guiSettingItemListView::NewLC();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+/**
+ * Symbian two-phase constructor.
+ * This creates an instance, pushes it on the cleanup stack,
+ * then calls the second-phase constructor.
+ * @return new instance of Csymbian_ua_guiSettingItemListView
+ */
+Csymbian_ua_guiSettingItemListView* Csymbian_ua_guiSettingItemListView::NewLC()
+ {
+ Csymbian_ua_guiSettingItemListView* self = new ( ELeave ) Csymbian_ua_guiSettingItemListView();
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ return self;
+ }
+
+
+/**
+ * Second-phase constructor for view.
+ * Initialize contents from resource.
+ */
+void Csymbian_ua_guiSettingItemListView::ConstructL()
+ {
+ // [[[ begin generated region: do not modify [Generated Code]
+ BaseConstructL( R_SYMBIAN_UA_GUI_SETTING_ITEM_LIST_SYMBIAN_UA_GUI_SETTING_ITEM_LIST_VIEW );
+ // ]]] end generated region [Generated Code]
+
+ // add your own initialization code here
+ }
+
+/**
+ * @return The UID for this view
+ */
+TUid Csymbian_ua_guiSettingItemListView::Id() const
+ {
+ return TUid::Uid( ESymbian_ua_guiSettingItemListViewId );
+ }
+
+/**
+ * Handle a command for this view (override)
+ * @param aCommand command id to be handled
+ */
+void Csymbian_ua_guiSettingItemListView::HandleCommandL( TInt aCommand )
+ {
+ // [[[ begin generated region: do not modify [Generated Code]
+ TBool commandHandled = EFalse;
+ switch ( aCommand )
+ { // code to dispatch to the AknView's menu and CBA commands is generated here
+
+ case EAknSoftkeySave:
+ commandHandled = HandleControlPaneRightSoftKeyPressedL( aCommand );
+ break;
+ case ESymbian_ua_guiSettingItemListViewMenuItem1Command:
+ commandHandled = HandleChangeSelectedSettingItemL( aCommand );
+ break;
+ default:
+ break;
+ }
+
+
+ if ( !commandHandled )
+ {
+
+ }
+ // ]]] end generated region [Generated Code]
+
+ }
+
+/**
+ * Handles user actions during activation of the view,
+ * such as initializing the content.
+ */
+void Csymbian_ua_guiSettingItemListView::DoActivateL(
+ const TVwsViewId& /*aPrevViewId*/,
+ TUid /*aCustomMessageId*/,
+ const TDesC8& /*aCustomMessage*/ )
+ {
+ // [[[ begin generated region: do not modify [Generated Contents]
+ SetupStatusPaneL();
+
+ CEikButtonGroupContainer* cba = AppUi()->Cba();
+ if ( cba != NULL )
+ {
+ cba->MakeVisible( EFalse );
+ }
+
+ if ( iSymbian_ua_guiSettingItemList == NULL )
+ {
+ iSettings = TSymbian_ua_guiSettingItemListSettings::NewL();
+ iSymbian_ua_guiSettingItemList = new ( ELeave ) CSymbian_ua_guiSettingItemList( *iSettings, this );
+ iSymbian_ua_guiSettingItemList->SetMopParent( this );
+ iSymbian_ua_guiSettingItemList->ConstructFromResourceL( R_SYMBIAN_UA_GUI_SETTING_ITEM_LIST_SYMBIAN_UA_GUI_SETTING_ITEM_LIST );
+ iSymbian_ua_guiSettingItemList->ActivateL();
+ iSymbian_ua_guiSettingItemList->LoadSettingValuesL();
+ iSymbian_ua_guiSettingItemList->LoadSettingsL();
+ AppUi()->AddToStackL( *this, iSymbian_ua_guiSettingItemList );
+ }
+ // ]]] end generated region [Generated Contents]
+
+ }
+
+/**
+ */
+void Csymbian_ua_guiSettingItemListView::DoDeactivate()
+ {
+ // [[[ begin generated region: do not modify [Generated Contents]
+ CleanupStatusPane();
+
+ CEikButtonGroupContainer* cba = AppUi()->Cba();
+ if ( cba != NULL )
+ {
+ cba->MakeVisible( ETrue );
+ cba->DrawDeferred();
+ }
+
+ if ( iSymbian_ua_guiSettingItemList != NULL )
+ {
+ AppUi()->RemoveFromStack( iSymbian_ua_guiSettingItemList );
+ delete iSymbian_ua_guiSettingItemList;
+ iSymbian_ua_guiSettingItemList = NULL;
+ delete iSettings;
+ iSettings = NULL;
+ }
+ // ]]] end generated region [Generated Contents]
+
+ }
+
+// [[[ begin generated function: do not modify
+void Csymbian_ua_guiSettingItemListView::SetupStatusPaneL()
+ {
+ // reset the context pane
+ TUid contextPaneUid = TUid::Uid( EEikStatusPaneUidContext );
+ CEikStatusPaneBase::TPaneCapabilities subPaneContext =
+ StatusPane()->PaneCapabilities( contextPaneUid );
+ if ( subPaneContext.IsPresent() && subPaneContext.IsAppOwned() )
+ {
+ CAknContextPane* context = static_cast< CAknContextPane* > (
+ StatusPane()->ControlL( contextPaneUid ) );
+ context->SetPictureToDefaultL();
+ }
+
+ // setup the title pane
+ TUid titlePaneUid = TUid::Uid( EEikStatusPaneUidTitle );
+ CEikStatusPaneBase::TPaneCapabilities subPaneTitle =
+ StatusPane()->PaneCapabilities( titlePaneUid );
+ if ( subPaneTitle.IsPresent() && subPaneTitle.IsAppOwned() )
+ {
+ CAknTitlePane* title = static_cast< CAknTitlePane* >(
+ StatusPane()->ControlL( titlePaneUid ) );
+ TResourceReader reader;
+ iEikonEnv->CreateResourceReaderLC( reader, R_SYMBIAN_UA_GUI_SETTING_ITEM_LIST_TITLE_RESOURCE );
+ title->SetFromResourceL( reader );
+ CleanupStack::PopAndDestroy(); // reader internal state
+ }
+
+ }
+// ]]] end generated function
+
+// [[[ begin generated function: do not modify
+void Csymbian_ua_guiSettingItemListView::CleanupStatusPane()
+ {
+ }
+// ]]] end generated function
+
+/**
+ * Handle status pane size change for this view (override)
+ */
+void Csymbian_ua_guiSettingItemListView::HandleStatusPaneSizeChange()
+ {
+ CAknView::HandleStatusPaneSizeChange();
+
+ // this may fail, but we're not able to propagate exceptions here
+ TInt result;
+ TRAP( result, SetupStatusPaneL() );
+ }
+
+/**
+ * Handle the selected event.
+ * @param aCommand the command id invoked
+ * @return ETrue if the command was handled, EFalse if not
+ */
+TBool Csymbian_ua_guiSettingItemListView::HandleChangeSelectedSettingItemL( TInt aCommand )
+ {
+ iSymbian_ua_guiSettingItemList->ChangeSelectedItemL();
+ return ETrue;
+ }
+
+/**
+ * Handle the rightSoftKeyPressed event.
+ * @return ETrue if the command was handled, EFalse if not
+ */
+TBool Csymbian_ua_guiSettingItemListView::HandleControlPaneRightSoftKeyPressedL( TInt aCommand )
+ {
+ TUint8 domain[256] = {0};
+ TPtr8 cDomain(domain, sizeof(domain));
+ TUint8 user[64] = {0};
+ TPtr8 cUser(user, sizeof(user));
+ TUint8 pass[64] = {0};
+ TPtr8 cPass(pass, sizeof(pass));
+
+ cDomain.Copy(iSettings->Ed_registrar());
+ cUser.Copy(iSettings->Ed_user());
+ cPass.Copy(iSettings->Ed_password());
+ symbian_ua_set_account((char*)domain, (char*)user, (char*)pass, false, false);
+
+ AppUi()->ActivateLocalViewL(TUid::Uid(ESymbian_ua_guiContainerViewId));
+ return ETrue;
+ }
+
+/**
+ * Handle the selected event.
+ * @param aCommand the command id invoked
+ * @return ETrue if the command was handled, EFalse if not
+ */
+TBool Csymbian_ua_guiSettingItemListView::HandleCancelMenuItemSelectedL( TInt aCommand )
+ {
+ AppUi()->ActivateLocalViewL(TUid::Uid(ESymbian_ua_guiContainerViewId));
+ return ETrue;
+ }
+
diff --git a/pjsip-apps/src/symbian_ua_gui/symbian_ua_guiContainer.uidesign b/pjsip-apps/src/symbian_ua_gui/symbian_ua_guiContainer.uidesign
new file mode 100644
index 0000000..3867c1b
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/symbian_ua_guiContainer.uidesign
@@ -0,0 +1,382 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<designerData version="1.1.0">
+ <componentManifest>
+ <manifestEntry id="com.nokia.sdt.series60.CAknView" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.DesignTimeContainer" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.StatusPane" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.ControlBase" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.StatusPaneTitle" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.StatusPaneTitleBase" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.CBA" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.CBABase" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.CCoeControl" version="1.1.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.ContainerBase" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.CEikLabel" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.CCoeControlBase" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.CEikEdwin" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.CEikEdwinBase" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.EditorBase" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.MenuBar" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.MenuBase" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.MenuPane" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.MenuItem" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.MenuItemBase" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.StandardNote" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.NonLayoutBase" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.ConfirmationQuery" version="1.0.0"/>
+ </componentManifest>
+ <property id="com.nokia.sdt.symbian.dm.RESOURCE_DIRECTORY_ID">data</property>
+ <property id="com.nokia.sdt.component.symbian.vendor">com.nokia.series60</property>
+ <property id="com.nokia.sdt.component.symbian.version">3.0.1</property>
+ <property id="com.nokia.sdt.symbian.dm.COMPONENT_PROVIDER">com.nokia.sdt.component.symbian.Symbian-Provider</property>
+ <property id="com.nokia.sdt.symbian.dm.INCLUDE_DIRECTORY_ID">inc</property>
+ <property id="com.nokia.sdt.symbian.dm.SOURCE_DIRECTORY_ID">src</property>
+ <property id="com.nokia.sdt.symbian.dm.SOURCEGEN_PROVIDER">com.nokia.sdt.sourcegen.Symbian-Provider</property>
+ <property id="com.nokia.sdt.symbian.dm.BUILD_DIRECTORY_ID">group</property>
+ <component id="com.nokia.sdt.series60.CAknView">
+ <property id="className">Csymbian_ua_guiContainerView</property>
+ <compoundProperty id="location">
+ <property id="x">52</property>
+ <property id="y">45</property>
+ </compoundProperty>
+ <property id="optionsMenu" type="componentRef">optionsMenu</property>
+ <property id="name">symbian_ua_guiContainerView</property>
+ <compoundProperty id="size">
+ <property id="width">240</property>
+ <property id="height">320</property>
+ </compoundProperty>
+ <component id="com.nokia.sdt.series60.StatusPane">
+ <compoundProperty id="location">
+ <property id="x">20</property>
+ </compoundProperty>
+ <property id="name">statusPane</property>
+ <compoundProperty id="size">
+ <property id="width">204</property>
+ <property id="height">66</property>
+ </compoundProperty>
+ <component id="com.nokia.sdt.series60.StatusPaneTitle">
+ <compoundProperty id="location">
+ <property id="x">56</property>
+ </compoundProperty>
+ <property id="name">title</property>
+ <property id="titleText" type="i18n">STR_symbian_ua_guiContainerView_1</property>
+ <compoundProperty id="size">
+ <property id="width">148</property>
+ <property id="height">43</property>
+ </compoundProperty>
+ <compoundProperty id="image"/>
+ </component>
+ </component>
+ <component id="com.nokia.sdt.series60.CBA">
+ <compoundProperty id="location">
+ <property id="y">288</property>
+ </compoundProperty>
+ <compoundProperty id="info">
+ <property id="rightId">UNIQUE</property>
+ <property id="leftText" type="i18n">STR_symbian_ua_guiContainerView_7</property>
+ <property id="rightText" type="i18n">STR_symbian_ua_guiContainerView_8</property>
+ </compoundProperty>
+ <property id="name">controlPane</property>
+ <compoundProperty id="size">
+ <property id="width">240</property>
+ <property id="height">32</property>
+ </compoundProperty>
+ <eventBinding id="rightSoftKeyPressed" handlerDisplay="CallSoftKeyPressedL" handlerSymbol="cpp@src//symbian_ua_guiContainerView.cpp/function(Csymbian_ua_guiContainerView::CallSoftKeyPressedL(TInt))"/>
+ </component>
+ <component id="com.nokia.sdt.series60.CCoeControl">
+ <property id="initialFocus" type="componentRef">ed_url</property>
+ <compoundProperty id="location">
+ <property id="y">66</property>
+ </compoundProperty>
+ <property id="className">CSymbian_ua_guiContainer</property>
+ <property id="name">symbian_ua_guiContainer</property>
+ <compoundProperty id="size">
+ <property id="width">240</property>
+ <property id="height">222</property>
+ </compoundProperty>
+ <component id="com.nokia.sdt.series60.CEikLabel">
+ <compoundProperty id="location">
+ <property id="x">2</property>
+ <property id="y">23</property>
+ </compoundProperty>
+ <property id="name">label1</property>
+ <property id="text" type="i18n">STR_symbian_ua_guiContainerView_2</property>
+ <compoundProperty id="size">
+ <property id="width">32</property>
+ <property id="height">28</property>
+ </compoundProperty>
+ </component>
+ <component id="com.nokia.sdt.series60.CEikEdwin">
+ <property id="defaultCase">EAknEditorLowerCase</property>
+ <compoundProperty id="size">
+ <property id="width">197</property>
+ <property id="height">28</property>
+ </compoundProperty>
+ <compoundProperty id="avkonFlags">
+ <property id="EAknEditorFlagNoT9">true</property>
+ <property id="EAknEditorFlagFixedCase">false</property>
+ <property id="EAknEditorFlagNoEditIndicators">false</property>
+ <property id="EAknEditorFlagNoLRNavigation">false</property>
+ <property id="EAknEditorFlagSupressShiftMenu">true</property>
+ <property id="EAknEditorFlagEnableScrollBars">false</property>
+ <property id="EAknEditorFlagMTAutoOverwrite">false</property>
+ <property id="EAknEditorFlagUseSCTNumericCharmap">false</property>
+ <property id="EAknEditorFlagLatinInputModesOnly">false</property>
+ <property id="EAknEditorFlagForceTransparentFepModes">false</property>
+ <property id="EAknEditorFlagAllowEntersWithScrollDown">false</property>
+ <property id="EAknEditorFlagEnablePictographInput">false</property>
+ <property id="EAknEditorFlagFindPane">false</property>
+ </compoundProperty>
+ <compoundProperty id="location">
+ <property id="x">49</property>
+ <property id="y">25</property>
+ </compoundProperty>
+ <compoundProperty id="flags"/>
+ <compoundProperty id="allowedCaseModes"/>
+ <property id="name">ed_url</property>
+ <property id="text" type="i18n">STR_symbian_ua_guiContainerView_4</property>
+ <compoundProperty id="allowedInputModes">
+ <property id="EAknEditorFullWidthTextInputMode">true</property>
+ <property id="EAknEditorFullWidthNumericInputMode">true</property>
+ <property id="EAknEditorHalfWidthTextInputMode">true</property>
+ <property id="EAknEditorTextInputMode">true</property>
+ <property id="EAknEditorNumericInputMode">true</property>
+ <property id="EAknEditorSecretAlphaInputMode">true</property>
+ <property id="EAknEditorFullWidthKatakanaInputMode">false</property>
+ <property id="EAknEditorHiraganaInputMode">false</property>
+ <property id="EAknEditorHiraganaKanjiInputMode">false</property>
+ <property id="EAknEditorKatakanaInputMode">false</property>
+ </compoundProperty>
+ <property id="specialCharacterTable">R_AVKON_URL_SPECIAL_CHARACTER_TABLE_DIALOG</property>
+ </component>
+ <component id="com.nokia.sdt.series60.CEikEdwin">
+ <compoundProperty id="size">
+ <property id="width">235</property>
+ <property id="height">143</property>
+ </compoundProperty>
+ <compoundProperty id="avkonFlags">
+ <property id="EAknEditorFlagNoEditIndicators">true</property>
+ <property id="EAknEditorFlagFixedCase">false</property>
+ <property id="EAknEditorFlagNoT9">false</property>
+ <property id="EAknEditorFlagNoLRNavigation">false</property>
+ <property id="EAknEditorFlagSupressShiftMenu">false</property>
+ <property id="EAknEditorFlagEnableScrollBars">true</property>
+ <property id="EAknEditorFlagMTAutoOverwrite">false</property>
+ <property id="EAknEditorFlagUseSCTNumericCharmap">false</property>
+ <property id="EAknEditorFlagLatinInputModesOnly">false</property>
+ <property id="EAknEditorFlagForceTransparentFepModes">false</property>
+ <property id="EAknEditorFlagAllowEntersWithScrollDown">false</property>
+ <property id="EAknEditorFlagEnablePictographInput">false</property>
+ <property id="EAknEditorFlagFindPane">false</property>
+ </compoundProperty>
+ <compoundProperty id="location">
+ <property id="x">3</property>
+ <property id="y">78</property>
+ </compoundProperty>
+ <compoundProperty id="flags">
+ <property id="EEikEdwinReadOnly">true</property>
+ <property id="EEikEdwinKeepDocument">false</property>
+ <property id="EEikEdwinSegmentedStorage">false</property>
+ <property id="EEikEdwinNoAutoSelection">false</property>
+ <property id="EEikEdwinJustAutoCurEnd">false</property>
+ <property id="EEikEdwinNoWrap">false</property>
+ <property id="EEikEdwinLineCursor">false</property>
+ <property id="EEikEdwinNoHorizScrolling">false</property>
+ <property id="EEikEdwinInclusiveSizeFixed">false</property>
+ <property id="EEikEdwinDisplayOnly">false</property>
+ <property id="EEikEdwinAlwaysShowSelection">false</property>
+ <property id="EEikEdwinAllowPictures">false</property>
+ <property id="EEikEdwinAllowUndo">false</property>
+ <property id="EEikEdwinNoLineOrParaBreaks">false</property>
+ <property id="EEikEdwinOnlyASCIIChars">false</property>
+ <property id="EEikEdwinIgnoreVirtualCursor">false</property>
+ <property id="EEikEdwinAvkonDisableCursor">false</property>
+ <property id="EEikEdwinAlternativeWrapping">false</property>
+ <property id="EEikEdwinResizable">false</property>
+ </compoundProperty>
+ <compoundProperty id="allowedCaseModes"/>
+ <property id="maxLength">2000</property>
+ <property id="name">ed_info</property>
+ <property id="text" type="i18n">STR_symbian_ua_guiContainerView_3</property>
+ <compoundProperty id="allowedInputModes">
+ <property id="EAknEditorKatakanaInputMode">true</property>
+ <property id="EAknEditorFullWidthTextInputMode">true</property>
+ <property id="EAknEditorFullWidthNumericInputMode">true</property>
+ <property id="EAknEditorFullWidthKatakanaInputMode">true</property>
+ <property id="EAknEditorHiraganaKanjiInputMode">true</property>
+ <property id="EAknEditorHalfWidthTextInputMode">true</property>
+ </compoundProperty>
+ <property id="lines">10</property>
+ </component>
+ </component>
+ <component id="com.nokia.sdt.series60.MenuBar">
+ <compoundProperty id="location">
+ <property id="x">3</property>
+ <property id="y">215</property>
+ </compoundProperty>
+ <property id="name">optionsMenu</property>
+ <compoundProperty id="size">
+ <property id="height">73</property>
+ <property id="width">237</property>
+ </compoundProperty>
+ <component id="com.nokia.sdt.series60.MenuPane">
+ <compoundProperty id="location"/>
+ <property id="name">menuPane1</property>
+ <compoundProperty id="size">
+ <property id="height">73</property>
+ <property id="width">237</property>
+ </compoundProperty>
+ <component id="com.nokia.sdt.series60.MenuItem">
+ <compoundProperty id="location">
+ <property id="x">5</property>
+ <property id="y">2</property>
+ </compoundProperty>
+ <property id="name">settingMenuItem</property>
+ <property id="text" type="i18n">STR_symbian_ua_guiContainerView_9</property>
+ <compoundProperty id="size">
+ <property id="width">222</property>
+ <property id="height">33</property>
+ </compoundProperty>
+ <eventBinding id="selected" handlerDisplay="HandleSettingMenuItemSelectedL" handlerSymbol="cpp@src//symbian_ua_guiContainerView.cpp/function(Csymbian_ua_guiContainerView::HandleSettingMenuItemSelectedL(TInt))"/>
+ </component>
+ <component id="com.nokia.sdt.series60.MenuItem">
+ <compoundProperty id="location">
+ <property id="x">5</property>
+ <property id="y">35</property>
+ </compoundProperty>
+ <property id="name">exitMenuItem</property>
+ <property id="text" type="i18n">STR_symbian_ua_guiContainerView_10</property>
+ <property id="command">EAknCmdExit</property>
+ <compoundProperty id="size">
+ <property id="width">222</property>
+ <property id="height">33</property>
+ </compoundProperty>
+ </component>
+ </component>
+ </component>
+ <component id="com.nokia.sdt.series60.StandardNote">
+ <property id="type">CAknErrorNote</property>
+ <compoundProperty id="location">
+ <property id="x">8</property>
+ <property id="y">171</property>
+ </compoundProperty>
+ <property id="name">note_error</property>
+ <property id="text" type="i18n">STR_symbian_ua_guiContainerView_13</property>
+ <compoundProperty id="size">
+ <property id="width">227</property>
+ <property id="height">114</property>
+ </compoundProperty>
+ </component>
+ <component id="com.nokia.sdt.series60.StandardNote">
+ <property id="type">CAknInformationNote</property>
+ <compoundProperty id="location">
+ <property id="x">8</property>
+ <property id="y">171</property>
+ </compoundProperty>
+ <property id="name">note_info</property>
+ <property id="text" type="i18n">STR_symbian_ua_guiContainerView_16</property>
+ <compoundProperty id="size">
+ <property id="width">227</property>
+ <property id="height">114</property>
+ </compoundProperty>
+ </component>
+ <component id="com.nokia.sdt.series60.StandardNote">
+ <property id="type">CAknWarningNote</property>
+ <compoundProperty id="location">
+ <property id="x">8</property>
+ <property id="y">171</property>
+ </compoundProperty>
+ <property id="name">note_warning</property>
+ <property id="text" type="i18n">STR_symbian_ua_guiContainerView_17</property>
+ <compoundProperty id="size">
+ <property id="width">227</property>
+ <property id="height">114</property>
+ </compoundProperty>
+ </component>
+ <component id="com.nokia.sdt.series60.ConfirmationQuery">
+ <compoundProperty id="location">
+ <property id="x">0</property>
+ <property id="y">171</property>
+ </compoundProperty>
+ <property id="name">qry_accept_call</property>
+ <property id="text" type="i18n">STR_symbian_ua_guiContainerView_18</property>
+ <compoundProperty id="size">
+ <property id="width">240</property>
+ <property id="height">149</property>
+ </compoundProperty>
+ </component>
+ </component>
+ <stringBundle>
+ <stringTable language="LANG_English">
+ <string id="STR_symbian_ua_guiContainerView_1">PJSUA for S60</string>
+ <string id="STR_symbian_ua_guiContainerView_2">URL</string>
+ <string id="STR_symbian_ua_guiContainerView_4">sip:</string>
+ <string id="STR_symbian_ua_guiContainerView_7">Options</string>
+ <string id="STR_symbian_ua_guiContainerView_8">Call</string>
+ <string id="STR_symbian_ua_guiContainerView_9">Setting</string>
+ <string id="STR_symbian_ua_guiContainerView_10">Exit</string>
+ <string id="STR_symbian_ua_guiContainerView_3"/>
+ <string id="STR_symbian_ua_guiContainerView_13">Failed initializing PJSUA!</string>
+ <string id="STR_symbian_ua_guiContainerView_16">Register Success</string>
+ <string id="STR_symbian_ua_guiContainerView_17">Register Failed</string>
+ <string id="STR_symbian_ua_guiContainerView_18">Accept Call</string>
+ </stringTable>
+ </stringBundle>
+ <macroTable/>
+ <sourceMappingState>
+ <resourceMappings>
+ <resourceMapping instanceName="qry_accept_call">r_symbian_ua_gui_container_qry_accept_call</resourceMapping>
+ <resourceMapping instanceName="note_warning">r_symbian_ua_gui_container_note_warning</resourceMapping>
+ <resourceMapping instanceName="ed_info" rsrcId="text">r_symbian_ua_gui_container_ed_info_2</resourceMapping>
+ <resourceMapping instanceName="optionsMenu">r_symbian_ua_gui_container_options_menu</resourceMapping>
+ <resourceMapping instanceName="menuPane1">r_symbian_ua_gui_container_menu_pane1_menu_pane</resourceMapping>
+ <resourceMapping instanceName="title">r_symbian_ua_gui_container_title_resource</resourceMapping>
+ <resourceMapping instanceName="statusPane">r_symbian_ua_gui_container_status_pane</resourceMapping>
+ <resourceMapping instanceName="ed_url">r_symbian_ua_gui_container_ed_url</resourceMapping>
+ <resourceMapping instanceName="symbian_ua_guiContainerView">r_symbian_ua_gui_container_symbian_ua_gui_container_view</resourceMapping>
+ <resourceMapping instanceName="label1">r_symbian_ua_gui_container_label1</resourceMapping>
+ <resourceMapping instanceName="controlPane">r_symbian_ua_gui_container_control_pane</resourceMapping>
+ <resourceMapping instanceName="ed_url" rsrcId="text">r_symbian_ua_gui_container_ed_url_2</resourceMapping>
+ <resourceMapping instanceName="note_info">r_symbian_ua_gui_container_note_info</resourceMapping>
+ <resourceMapping instanceName="note_error">r_symbian_ua_gui_container_note_error</resourceMapping>
+ <resourceMapping instanceName="ed_info">r_symbian_ua_gui_container_ed_info</resourceMapping>
+ </resourceMappings>
+ <enumMappings>
+ <enumMapping instanceName="title" propertyId="" nameAlgorithm="com.nokia.sdt.component.symbian.NAME_ALG_CONTROL_TYPE">EAknCtTitlePane</enumMapping>
+ <enumMapping instanceName="settingMenuItem" propertyId="command" nameAlgorithm="com.nokia.sdt.component.symbian.NAME_ALG_COMMANDS">ESymbian_ua_guiContainerViewSettingMenuItemCommand</enumMapping>
+ <enumMapping instanceName="ed_info" propertyId="numericKeymap">EAknEditorStandardNumberModeKeymap</enumMapping>
+ <enumMapping instanceName="label1" propertyId="font">EEikLabelFontNormal</enumMapping>
+ <enumMapping instanceName="ed_url" propertyId="defaultCase">EAknEditorLowerCase</enumMapping>
+ <enumMapping instanceName="symbian_ua_guiContainerView" propertyId="" nameAlgorithm="com.nokia.sdt.component.symbian.NAME_ALG_VIEW_UID">ESymbian_ua_guiContainerViewId</enumMapping>
+ <enumMapping instanceName="label1" propertyId="alignment">EEikLabelAlignHCenter</enumMapping>
+ <enumMapping instanceName="controlPane" propertyId="leftId" nameAlgorithm="com.nokia.sdt.component.symbian.NAME_ALG_COMMANDS">EAknSoftkeyOptions</enumMapping>
+ <enumMapping instanceName="qry_accept_call" propertyId="" nameAlgorithm="com.nokia.sdt.component.symbian.NAME_ALG_DIALOG_LINE_ID">ESymbian_ua_guiContainerViewQry_accept_call</enumMapping>
+ <enumMapping instanceName="controlPane" propertyId="rightId" nameAlgorithm="com.nokia.sdt.component.symbian.NAME_ALG_COMMANDS">ESymbian_ua_guiContainerViewControlPaneRightId</enumMapping>
+ <enumMapping instanceName="exitMenuItem" propertyId="command" nameAlgorithm="com.nokia.sdt.component.symbian.NAME_ALG_COMMANDS">EAknCmdExit</enumMapping>
+ <enumMapping instanceName="title" propertyId="" nameAlgorithm="com.nokia.sdt.component.symbian.NAME_ALG_STATUS_PANE_ID">EEikStatusPaneUidTitle</enumMapping>
+ <enumMapping instanceName="ed_url" propertyId="numericKeymap">EAknEditorStandardNumberModeKeymap</enumMapping>
+ <enumMapping instanceName="ed_info" propertyId="defaultInputMode">EAknEditorTextInputMode</enumMapping>
+ <enumMapping instanceName="ed_url" propertyId="defaultInputMode">EAknEditorTextInputMode</enumMapping>
+ <enumMapping instanceName="ed_info" propertyId="defaultCase">EAknEditorTextCase</enumMapping>
+ </enumMappings>
+ <arrayMappings/>
+ </sourceMappingState>
+ <generatedFiles>
+ <file>inc/symbian_ua_guiContainer.h</file>
+ <file>inc/symbian_ua_guiContainerView.h</file>
+ <file>src/symbian_ua_guiContainerView.cpp</file>
+ <file>src/symbian_ua_guiContainer.cpp</file>
+ <file>data/symbian_ua_gui.rss</file>
+ <file>data/symbian_ua_guiContainer.rssi</file>
+ <file>inc/symbian_ua_gui.hrh</file>
+ <file>inc/symbian_ua_guiContainer.hrh</file>
+ <file>data/symbian_ua_guiSettingItemList.rssi</file>
+ <file>inc/symbian_ua_guiSettingItemList.hrh</file>
+ <file>data/symbian_ua_gui.loc</file>
+ <file>data/symbian_ua_gui.l01</file>
+ <file>data/symbian_ua_guiContainer.loc</file>
+ <file>data/symbian_ua_guiContainer.l01</file>
+ <file>data/symbian_ua_guiSettingItemList.loc</file>
+ <file>data/symbian_ua_guiSettingItemList.l01</file>
+ </generatedFiles>
+</designerData>
diff --git a/pjsip-apps/src/symbian_ua_gui/symbian_ua_guiSettingItemList.uidesign b/pjsip-apps/src/symbian_ua_gui/symbian_ua_guiSettingItemList.uidesign
new file mode 100644
index 0000000..95962b6
--- /dev/null
+++ b/pjsip-apps/src/symbian_ua_gui/symbian_ua_guiSettingItemList.uidesign
@@ -0,0 +1,380 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<designerData version="1.1.0">
+ <componentManifest>
+ <manifestEntry id="com.nokia.sdt.series60.CAknView" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.DesignTimeContainer" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.StatusPane" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.ControlBase" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.StatusPaneTitle" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.StatusPaneTitleBase" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.CBA" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.CBABase" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.CAknSettingItemList" version="1.1.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.ContainerBase" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.CEikEdwin" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.CEikEdwinBase" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.EditorBase" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.CCoeControlBase" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.SecretEditor" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.CAknBinaryPopupSettingItem" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.EnumeratedTextPopupBase" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.MenuBar" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.MenuBase" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.MenuPane" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.MenuItem" version="1.0.0"/>
+ <manifestEntry id="com.nokia.sdt.series60.MenuItemBase" version="1.0.0"/>
+ </componentManifest>
+ <property id="com.nokia.sdt.symbian.dm.RESOURCE_DIRECTORY_ID">data</property>
+ <property id="com.nokia.sdt.component.symbian.vendor">com.nokia.series60</property>
+ <property id="com.nokia.sdt.component.symbian.version">3.0.1</property>
+ <property id="com.nokia.sdt.symbian.dm.COMPONENT_PROVIDER">com.nokia.sdt.component.symbian.Symbian-Provider</property>
+ <property id="com.nokia.sdt.symbian.dm.INCLUDE_DIRECTORY_ID">inc</property>
+ <property id="com.nokia.sdt.symbian.dm.SOURCE_DIRECTORY_ID">src</property>
+ <property id="com.nokia.sdt.symbian.dm.SOURCEGEN_PROVIDER">com.nokia.sdt.sourcegen.Symbian-Provider</property>
+ <property id="com.nokia.sdt.symbian.dm.BUILD_DIRECTORY_ID">group</property>
+ <component id="com.nokia.sdt.series60.CAknView">
+ <property id="className">Csymbian_ua_guiSettingItemListView</property>
+ <compoundProperty id="location">
+ <property id="x">52</property>
+ <property id="y">45</property>
+ </compoundProperty>
+ <property id="optionsMenu" type="componentRef">optionsMenu</property>
+ <property id="name">symbian_ua_guiSettingItemListView</property>
+ <compoundProperty id="size">
+ <property id="width">240</property>
+ <property id="height">320</property>
+ </compoundProperty>
+ <component id="com.nokia.sdt.series60.StatusPane">
+ <compoundProperty id="location">
+ <property id="x">20</property>
+ </compoundProperty>
+ <property id="name">statusPane</property>
+ <compoundProperty id="size">
+ <property id="width">204</property>
+ <property id="height">66</property>
+ </compoundProperty>
+ <component id="com.nokia.sdt.series60.StatusPaneTitle">
+ <compoundProperty id="location">
+ <property id="x">56</property>
+ </compoundProperty>
+ <property id="name">title</property>
+ <property id="titleText" type="i18n">STR_symbian_ua_guiSettingItemListView_2</property>
+ <compoundProperty id="size">
+ <property id="width">148</property>
+ <property id="height">43</property>
+ </compoundProperty>
+ <compoundProperty id="image"/>
+ </component>
+ </component>
+ <component id="com.nokia.sdt.series60.CBA">
+ <compoundProperty id="location">
+ <property id="y">288</property>
+ </compoundProperty>
+ <compoundProperty id="info">
+ <property id="leftText" type="i18n">STR_symbian_ua_guiSettingItemListView_140</property>
+ <property id="rightText" type="i18n">STR_symbian_ua_guiSettingItemListView_141</property>
+ <property id="rightId">EAknSoftkeySave</property>
+ </compoundProperty>
+ <property id="name">controlPane</property>
+ <compoundProperty id="size">
+ <property id="width">240</property>
+ <property id="height">32</property>
+ </compoundProperty>
+ <eventBinding id="rightSoftKeyPressed" handlerDisplay="HandleControlPaneRightSoftKeyPressedL" handlerSymbol="cpp@src//symbian_ua_guiSettingItemListView.cpp/function(Csymbian_ua_guiSettingItemListView::HandleControlPaneRightSoftKeyPressedL(TInt))"/>
+ </component>
+ <component id="com.nokia.sdt.series60.CAknSettingItemList">
+ <compoundProperty id="size">
+ <property id="width">240</property>
+ <property id="height">222</property>
+ </compoundProperty>
+ <property id="className">CSymbian_ua_guiSettingItemList</property>
+ <compoundProperty id="location">
+ <property id="y">66</property>
+ </compoundProperty>
+ <property id="EAknSettingItemNumberedStyle">false</property>
+ <property id="title" type="i18n">STR_symbian_ua_guiSettingItemListView_1</property>
+ <property id="name">symbian_ua_guiSettingItemList</property>
+ <property id="exitsApp">false</property>
+ <component id="com.nokia.sdt.series60.CEikEdwin">
+ <compoundProperty id="size">
+ <property id="height">58</property>
+ <property id="width">240</property>
+ </compoundProperty>
+ <property id="defaultCase">EAknEditorLowerCase</property>
+ <compoundProperty id="avkonFlags"/>
+ <compoundProperty id="location">
+ <property id="x">0</property>
+ <property id="y">0</property>
+ </compoundProperty>
+ <property id="itemTitle" type="i18n">STR_symbian_ua_guiSettingItemListView_5</property>
+ <compoundProperty id="flags"/>
+ <compoundProperty id="allowedCaseModes"/>
+ <property id="name">ed_registrar</property>
+ <property id="text" type="i18n">STR_symbian_ua_guiSettingItemListView_3</property>
+ <compoundProperty id="allowedInputModes">
+ <property id="EAknEditorKatakanaInputMode">true</property>
+ <property id="EAknEditorFullWidthTextInputMode">true</property>
+ <property id="EAknEditorFullWidthNumericInputMode">true</property>
+ <property id="EAknEditorFullWidthKatakanaInputMode">true</property>
+ <property id="EAknEditorHiraganaKanjiInputMode">true</property>
+ <property id="EAknEditorHalfWidthTextInputMode">true</property>
+ </compoundProperty>
+ </component>
+ <component id="com.nokia.sdt.series60.CEikEdwin">
+ <compoundProperty id="size">
+ <property id="height">58</property>
+ <property id="width">240</property>
+ </compoundProperty>
+ <property id="defaultCase">EAknEditorLowerCase</property>
+ <compoundProperty id="avkonFlags"/>
+ <compoundProperty id="location">
+ <property id="x">0</property>
+ <property id="y">58</property>
+ </compoundProperty>
+ <property id="itemTitle" type="i18n">STR_symbian_ua_guiSettingItemListView_8</property>
+ <compoundProperty id="flags"/>
+ <compoundProperty id="allowedCaseModes"/>
+ <property id="name">ed_user</property>
+ <property id="text" type="i18n">STR_symbian_ua_guiSettingItemListView_7</property>
+ <compoundProperty id="allowedInputModes">
+ <property id="EAknEditorKatakanaInputMode">true</property>
+ <property id="EAknEditorFullWidthTextInputMode">true</property>
+ <property id="EAknEditorFullWidthNumericInputMode">true</property>
+ <property id="EAknEditorFullWidthKatakanaInputMode">true</property>
+ <property id="EAknEditorHiraganaKanjiInputMode">true</property>
+ <property id="EAknEditorHalfWidthTextInputMode">true</property>
+ </compoundProperty>
+ </component>
+ <component id="com.nokia.sdt.series60.SecretEditor">
+ <property id="maxLength">32</property>
+ <compoundProperty id="location">
+ <property id="x">0</property>
+ <property id="y">116</property>
+ </compoundProperty>
+ <property id="name">ed_password</property>
+ <property id="itemTitle" type="i18n">STR_symbian_ua_guiSettingItemListView_16</property>
+ <compoundProperty id="size">
+ <property id="height">58</property>
+ <property id="width">240</property>
+ </compoundProperty>
+ </component>
+ <component id="com.nokia.sdt.series60.CAknBinaryPopupSettingItem">
+ <sequenceProperty id="items">
+ <compoundElement>
+ <property id="settingText" type="i18n">STR_symbian_ua_guiSettingItemListView_25</property>
+ <property id="popupText" type="i18n">STR_symbian_ua_guiSettingItemListView_26</property>
+ <property id="value">1</property>
+ </compoundElement>
+ <compoundElement>
+ <property id="settingText" type="i18n">STR_symbian_ua_guiSettingItemListView_27</property>
+ <property id="popupText" type="i18n">STR_symbian_ua_guiSettingItemListView_28</property>
+ </compoundElement>
+ </sequenceProperty>
+ <compoundProperty id="size">
+ <property id="height">0</property>
+ <property id="width">240</property>
+ </compoundProperty>
+ <compoundProperty id="location">
+ <property id="x">0</property>
+ <property id="y">174</property>
+ </compoundProperty>
+ <property id="itemTitle" type="i18n">STR_symbian_ua_guiSettingItemListView_24</property>
+ <property id="active">1</property>
+ <property id="name">b_srtp</property>
+ <property id="itemHidden">true</property>
+ </component>
+ <component id="com.nokia.sdt.series60.CAknBinaryPopupSettingItem">
+ <sequenceProperty id="items">
+ <compoundElement>
+ <property id="settingText" type="i18n">STR_symbian_ua_guiSettingItemListView_47</property>
+ <property id="popupText" type="i18n">STR_symbian_ua_guiSettingItemListView_48</property>
+ <property id="value">1</property>
+ </compoundElement>
+ <compoundElement>
+ <property id="settingText" type="i18n">STR_symbian_ua_guiSettingItemListView_49</property>
+ <property id="popupText" type="i18n">STR_symbian_ua_guiSettingItemListView_50</property>
+ </compoundElement>
+ </sequenceProperty>
+ <compoundProperty id="size">
+ <property id="height">0</property>
+ <property id="width">240</property>
+ </compoundProperty>
+ <compoundProperty id="location">
+ <property id="x">0</property>
+ <property id="y">174</property>
+ </compoundProperty>
+ <property id="itemTitle" type="i18n">STR_symbian_ua_guiSettingItemListView_46</property>
+ <property id="active">1</property>
+ <property id="name">b_ice</property>
+ <property id="itemHidden">true</property>
+ </component>
+ <component id="com.nokia.sdt.series60.CEikEdwin">
+ <compoundProperty id="size">
+ <property id="height">0</property>
+ <property id="width">240</property>
+ </compoundProperty>
+ <compoundProperty id="avkonFlags"/>
+ <compoundProperty id="location">
+ <property id="x">0</property>
+ <property id="y">174</property>
+ </compoundProperty>
+ <property id="itemTitle" type="i18n">STR_symbian_ua_guiSettingItemListView_19</property>
+ <compoundProperty id="flags"/>
+ <compoundProperty id="allowedCaseModes"/>
+ <property id="name">ed_stun_server</property>
+ <property id="text" type="i18n">STR_symbian_ua_guiSettingItemListView_18</property>
+ <property id="itemHidden">true</property>
+ <compoundProperty id="allowedInputModes">
+ <property id="EAknEditorKatakanaInputMode">true</property>
+ <property id="EAknEditorFullWidthTextInputMode">true</property>
+ <property id="EAknEditorFullWidthNumericInputMode">true</property>
+ <property id="EAknEditorFullWidthKatakanaInputMode">true</property>
+ <property id="EAknEditorHiraganaKanjiInputMode">true</property>
+ <property id="EAknEditorHalfWidthTextInputMode">true</property>
+ </compoundProperty>
+ </component>
+ </component>
+ <component id="com.nokia.sdt.series60.MenuBar">
+ <compoundProperty id="location">
+ <property id="x">3</property>
+ <property id="y">248</property>
+ </compoundProperty>
+ <property id="name">optionsMenu</property>
+ <compoundProperty id="size">
+ <property id="height">40</property>
+ <property id="width">237</property>
+ </compoundProperty>
+ <component id="com.nokia.sdt.series60.MenuPane">
+ <compoundProperty id="location"/>
+ <property id="name">menuPane1</property>
+ <compoundProperty id="size">
+ <property id="height">40</property>
+ <property id="width">237</property>
+ </compoundProperty>
+ <component id="com.nokia.sdt.series60.MenuItem">
+ <compoundProperty id="location">
+ <property id="x">5</property>
+ <property id="y">2</property>
+ </compoundProperty>
+ <property id="name">menuItem1</property>
+ <property id="text" type="i18n">STR_symbian_ua_guiSettingItemListView_4</property>
+ <compoundProperty id="size">
+ <property id="width">222</property>
+ <property id="height">33</property>
+ </compoundProperty>
+ <eventBinding id="selected" handlerDisplay="HandleChangeSelectedSettingItemL" handlerSymbol="cpp@src//symbian_ua_guiSettingItemListView.cpp/function(Csymbian_ua_guiSettingItemListView::HandleChangeSelectedSettingItemL(TInt))"/>
+ </component>
+ </component>
+ </component>
+ </component>
+ <stringBundle>
+ <stringTable language="LANG_English">
+ <string id="STR_symbian_ua_guiSettingItemListView_1">Settings</string>
+ <string id="STR_symbian_ua_guiSettingItemListView_2">Account Settings</string>
+ <string id="STR_symbian_ua_guiSettingItemListView_4">Change</string>
+ <string id="STR_symbian_ua_guiSettingItemListView_3"/>
+ <string id="STR_symbian_ua_guiSettingItemListView_5">Registrar</string>
+ <string id="STR_symbian_ua_guiSettingItemListView_7"/>
+ <string id="STR_symbian_ua_guiSettingItemListView_8">User</string>
+ <string id="STR_symbian_ua_guiSettingItemListView_16">Password</string>
+ <string id="STR_symbian_ua_guiSettingItemListView_18"/>
+ <string id="STR_symbian_ua_guiSettingItemListView_19">STUN Server</string>
+ <string id="STR_symbian_ua_guiSettingItemListView_24">SRTP</string>
+ <string id="STR_symbian_ua_guiSettingItemListView_25">On</string>
+ <string id="STR_symbian_ua_guiSettingItemListView_26">Popup text for On</string>
+ <string id="STR_symbian_ua_guiSettingItemListView_27">Off</string>
+ <string id="STR_symbian_ua_guiSettingItemListView_28">Popup text for Off</string>
+ <string id="STR_symbian_ua_guiSettingItemListView_46">ICE</string>
+ <string id="STR_symbian_ua_guiSettingItemListView_47">On</string>
+ <string id="STR_symbian_ua_guiSettingItemListView_48">Popup text for On</string>
+ <string id="STR_symbian_ua_guiSettingItemListView_49">Off</string>
+ <string id="STR_symbian_ua_guiSettingItemListView_50">Popup text for Off</string>
+ <string id="STR_symbian_ua_guiSettingItemListView_140">Options</string>
+ <string id="STR_symbian_ua_guiSettingItemListView_141">Done</string>
+ </stringTable>
+ </stringBundle>
+ <macroTable/>
+ <sourceMappingState>
+ <resourceMappings>
+ <resourceMapping instanceName="b_srtp" rsrcId="member$setting_page_resource">r_symbian_ua_gui_setting_item_list_b_srtp_setting_page_resource</resourceMapping>
+ <resourceMapping instanceName="ed_stun_server">r_symbian_ua_gui_setting_item_list_ed_stun_server_editor_resource_id</resourceMapping>
+ <resourceMapping instanceName="b_ice" rsrcId="setting">r_symbian_ua_gui_setting_item_list_b_ice_setting_texts_resource</resourceMapping>
+ <resourceMapping instanceName="ed_registrar">r_symbian_ua_gui_setting_item_list_ed_registrar_editor_resource_id</resourceMapping>
+ <resourceMapping instanceName="ed_user" rsrcId="text">r_symbian_ua_gui_setting_item_list_ed_user</resourceMapping>
+ <resourceMapping instanceName="b_srtp" rsrcId="popup">r_symbian_ua_gui_setting_item_list_b_srtp_popped_up_texts_resource</resourceMapping>
+ <resourceMapping instanceName="ed_stun_server" rsrcId="text">r_symbian_ua_gui_setting_item_list_ed_stun_server</resourceMapping>
+ <resourceMapping instanceName="optionsMenu">r_symbian_ua_gui_setting_item_list_options_menu</resourceMapping>
+ <resourceMapping instanceName="ed_password" rsrcId="member$setting_page_resource">r_symbian_ua_gui_setting_item_list_ed_password_setting_page_resource</resourceMapping>
+ <resourceMapping instanceName="b_ice" rsrcId="popup">r_symbian_ua_gui_setting_item_list_b_ice_popped_up_texts_resource</resourceMapping>
+ <resourceMapping instanceName="symbian_ua_guiSettingItemListView">r_symbian_ua_gui_setting_item_list_symbian_ua_gui_setting_item_list_view</resourceMapping>
+ <resourceMapping instanceName="ed_password">r_symbian_ua_gui_setting_item_list_ed_password_editor_resource_id</resourceMapping>
+ <resourceMapping instanceName="symbian_ua_guiSettingItemList">r_symbian_ua_gui_setting_item_list_symbian_ua_gui_setting_item_list</resourceMapping>
+ <resourceMapping instanceName="b_ice" rsrcId="member$setting_page_resource">r_symbian_ua_gui_setting_item_list_b_ice_setting_page_resource</resourceMapping>
+ <resourceMapping instanceName="statusPane">r_symbian_ua_gui_setting_item_list_status_pane</resourceMapping>
+ <resourceMapping instanceName="b_ice">r_symbian_ua_gui_setting_item_list_b_ice_editor_resource_id</resourceMapping>
+ <resourceMapping instanceName="ed_user">r_symbian_ua_gui_setting_item_list_ed_user_editor_resource_id</resourceMapping>
+ <resourceMapping instanceName="b_srtp" rsrcId="associated">r_symbian_ua_gui_setting_item_list_b_srtp</resourceMapping>
+ <resourceMapping instanceName="ed_registrar" rsrcId="text">r_symbian_ua_gui_setting_item_list_ed_registrar</resourceMapping>
+ <resourceMapping instanceName="b_srtp">r_symbian_ua_gui_setting_item_list_b_srtp_editor_resource_id</resourceMapping>
+ <resourceMapping instanceName="b_srtp" rsrcId="setting">r_symbian_ua_gui_setting_item_list_b_srtp_setting_texts_resource</resourceMapping>
+ <resourceMapping instanceName="ed_registrar" rsrcId="member$setting_page_resource">r_symbian_ua_gui_setting_item_list_ed_registrar_setting_page_resource</resourceMapping>
+ <resourceMapping instanceName="menuPane1">r_symbian_ua_gui_setting_item_list_menu_pane1_menu_pane</resourceMapping>
+ <resourceMapping instanceName="ed_user" rsrcId="member$setting_page_resource">r_symbian_ua_gui_setting_item_list_ed_user_setting_page_resource</resourceMapping>
+ <resourceMapping instanceName="controlPane">r_symbian_ua_gui_setting_item_list_control_pane</resourceMapping>
+ <resourceMapping instanceName="title">r_symbian_ua_gui_setting_item_list_title_resource</resourceMapping>
+ <resourceMapping instanceName="ed_stun_server" rsrcId="member$setting_page_resource">r_symbian_ua_gui_setting_item_list_ed_stun_server_setting_page_resource</resourceMapping>
+ <resourceMapping instanceName="b_ice" rsrcId="associated">r_symbian_ua_gui_setting_item_list_b_ice</resourceMapping>
+ </resourceMappings>
+ <enumMappings>
+ <enumMapping instanceName="menuItem1" propertyId="command" nameAlgorithm="com.nokia.sdt.component.symbian.NAME_ALG_COMMANDS">ESymbian_ua_guiSettingItemListViewMenuItem1Command</enumMapping>
+ <enumMapping instanceName="ed_password" propertyId="" nameAlgorithm="com.nokia.sdt.component.symbian.NAME_ALG_SETTING_ITEM_ID">ESymbian_ua_guiSettingItemListViewEd_password</enumMapping>
+ <enumMapping instanceName="ed_user" propertyId="" nameAlgorithm="com.nokia.sdt.component.symbian.NAME_ALG_CONTROL_TYPE">EEikCtEdwin</enumMapping>
+ <enumMapping instanceName="ed_stun_server" propertyId="" nameAlgorithm="com.nokia.sdt.component.symbian.NAME_ALG_SETTING_ITEM_ID">ESymbian_ua_guiSettingItemListViewEd_stun_server</enumMapping>
+ <enumMapping instanceName="title" propertyId="" nameAlgorithm="com.nokia.sdt.component.symbian.NAME_ALG_STATUS_PANE_ID">EEikStatusPaneUidTitle</enumMapping>
+ <enumMapping instanceName="ed_user" propertyId="defaultCase">EAknEditorLowerCase</enumMapping>
+ <enumMapping instanceName="b_ice" propertyId="" nameAlgorithm="com.nokia.sdt.component.symbian.NAME_ALG_SETTING_ITEM_ID">ESymbian_ua_guiSettingItemListViewB_ice</enumMapping>
+ <enumMapping instanceName="ed_user" propertyId="numericKeymap">EAknEditorStandardNumberModeKeymap</enumMapping>
+ <enumMapping instanceName="ed_stun_server" propertyId="" nameAlgorithm="com.nokia.sdt.component.symbian.NAME_ALG_CONTROL_TYPE">EEikCtEdwin</enumMapping>
+ <enumMapping instanceName="b_srtp" propertyId="" nameAlgorithm="com.nokia.sdt.component.symbian.NAME_ALG_SETTING_ITEM_ID">ESymbian_ua_guiSettingItemListViewB_srtp</enumMapping>
+ <enumMapping instanceName="ed_user" propertyId="defaultInputMode">EAknEditorTextInputMode</enumMapping>
+ <enumMapping instanceName="ed_registrar" propertyId="numericKeymap">EAknEditorStandardNumberModeKeymap</enumMapping>
+ <enumMapping instanceName="b_srtp" propertyId="" nameAlgorithm="com.nokia.sdt.component.symbian.NAME_ALG_CONTROL_TYPE">EAknCtPopupSettingList</enumMapping>
+ <enumMapping instanceName="ed_registrar" propertyId="defaultInputMode">EAknEditorTextInputMode</enumMapping>
+ <enumMapping instanceName="title" propertyId="" nameAlgorithm="com.nokia.sdt.component.symbian.NAME_ALG_CONTROL_TYPE">EAknCtTitlePane</enumMapping>
+ <enumMapping instanceName="symbian_ua_guiSettingItemListView" propertyId="" nameAlgorithm="com.nokia.sdt.component.symbian.NAME_ALG_VIEW_UID">ESymbian_ua_guiSettingItemListViewId</enumMapping>
+ <enumMapping instanceName="ed_registrar" propertyId="defaultCase">EAknEditorLowerCase</enumMapping>
+ <enumMapping instanceName="ed_password" propertyId="" nameAlgorithm="com.nokia.sdt.component.symbian.NAME_ALG_CONTROL_TYPE">EEikCtSecretEd</enumMapping>
+ <enumMapping instanceName="controlPane" propertyId="leftId" nameAlgorithm="com.nokia.sdt.component.symbian.NAME_ALG_COMMANDS">EAknSoftkeyOptions</enumMapping>
+ <enumMapping instanceName="ed_user" propertyId="" nameAlgorithm="com.nokia.sdt.component.symbian.NAME_ALG_SETTING_ITEM_ID">ESymbian_ua_guiSettingItemListViewEd_user</enumMapping>
+ <enumMapping instanceName="controlPane" propertyId="rightId" nameAlgorithm="com.nokia.sdt.component.symbian.NAME_ALG_COMMANDS">EAknSoftkeySave</enumMapping>
+ <enumMapping instanceName="ed_stun_server" propertyId="numericKeymap">EAknEditorStandardNumberModeKeymap</enumMapping>
+ <enumMapping instanceName="save_SettingsMenuItem" propertyId="command" nameAlgorithm="com.nokia.sdt.component.symbian.NAME_ALG_COMMANDS">ESymbian_ua_guiSettingItemListViewSave_SettingsMenuItemCommand</enumMapping>
+ <enumMapping instanceName="ed_registrar" propertyId="" nameAlgorithm="com.nokia.sdt.component.symbian.NAME_ALG_SETTING_ITEM_ID">ESymbian_ua_guiSettingItemListViewEd_registrar</enumMapping>
+ <enumMapping instanceName="ed_stun_server" propertyId="defaultInputMode">EAknEditorTextInputMode</enumMapping>
+ <enumMapping instanceName="b_ice" propertyId="" nameAlgorithm="com.nokia.sdt.component.symbian.NAME_ALG_CONTROL_TYPE">EAknCtPopupSettingList</enumMapping>
+ <enumMapping instanceName="ed_registrar" propertyId="" nameAlgorithm="com.nokia.sdt.component.symbian.NAME_ALG_CONTROL_TYPE">EEikCtEdwin</enumMapping>
+ <enumMapping instanceName="ed_stun_server" propertyId="defaultCase">EAknEditorTextCase</enumMapping>
+ </enumMappings>
+ <arrayMappings/>
+ </sourceMappingState>
+ <generatedFiles>
+ <file>src/symbian_ua_guiSettingItemList.cpp</file>
+ <file>src/Symbian_ua_guiSettingItemListSets.cpp</file>
+ <file>src/symbian_ua_guiSettingItemListView.cpp</file>
+ <file>inc/Symbian_ua_guiSettingItemListSettings.h</file>
+ <file>inc/symbian_ua_guiSettingItemList.h</file>
+ <file>inc/symbian_ua_guiSettingItemListView.h</file>
+ <file>data/symbian_ua_gui.rss</file>
+ <file>data/symbian_ua_guiContainer.rssi</file>
+ <file>inc/symbian_ua_gui.hrh</file>
+ <file>inc/symbian_ua_guiContainer.hrh</file>
+ <file>data/symbian_ua_guiSettingItemList.rssi</file>
+ <file>inc/symbian_ua_guiSettingItemList.hrh</file>
+ <file>data/symbian_ua_gui.loc</file>
+ <file>data/symbian_ua_gui.l01</file>
+ <file>data/symbian_ua_guiContainer.loc</file>
+ <file>data/symbian_ua_guiContainer.l01</file>
+ <file>data/symbian_ua_guiSettingItemList.loc</file>
+ <file>data/symbian_ua_guiSettingItemList.l01</file>
+ </generatedFiles>
+</designerData>
diff --git a/pjsip-apps/src/symsndtest/app_main.cpp b/pjsip-apps/src/symsndtest/app_main.cpp
new file mode 100644
index 0000000..d4f5523
--- /dev/null
+++ b/pjsip-apps/src/symsndtest/app_main.cpp
@@ -0,0 +1,434 @@
+/* $Id: app_main.cpp 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <pjmedia-audiodev/audiodev.h>
+#include <pjmedia/delaybuf.h>
+#include <pj/assert.h>
+#include <pj/errno.h>
+#include <pj/os.h>
+#include <pj/log.h>
+#include <pj/string.h>
+#include <pj/unicode.h>
+#include <e32cons.h>
+
+#define THIS_FILE "app_main.cpp"
+#define CLOCK_RATE 8000
+#define CHANNEL_COUNT 1
+#define PTIME 20
+#define SAMPLES_PER_FRAME (CLOCK_RATE*PTIME/1000)
+#define BITS_PER_SAMPLE 16
+
+extern CConsoleBase* console;
+
+static pj_caching_pool cp;
+static pjmedia_aud_stream *strm;
+static unsigned rec_cnt, play_cnt;
+static pj_time_val t_start;
+static pjmedia_aud_param param;
+static pj_pool_t *pool;
+static pjmedia_delay_buf *delaybuf;
+static char frame_buf[256];
+
+static void copy_frame_ext(pjmedia_frame_ext *f_dst,
+ const pjmedia_frame_ext *f_src)
+{
+ pj_bzero(f_dst, sizeof(*f_dst));
+ if (f_src->subframe_cnt) {
+ f_dst->base.type = PJMEDIA_FRAME_TYPE_EXTENDED;
+ for (unsigned i = 0; i < f_src->subframe_cnt; ++i) {
+ pjmedia_frame_ext_subframe *sf;
+ sf = pjmedia_frame_ext_get_subframe(f_src, i);
+ pjmedia_frame_ext_append_subframe(f_dst, sf->data, sf->bitlen,
+ param.samples_per_frame);
+ }
+ } else {
+ f_dst->base.type = PJMEDIA_FRAME_TYPE_NONE;
+ }
+}
+
+/* Logging callback */
+static void log_writer(int level, const char *buf, unsigned len)
+{
+ static wchar_t buf16[PJ_LOG_MAX_SIZE];
+
+ PJ_UNUSED_ARG(level);
+
+ pj_ansi_to_unicode(buf, len, buf16, PJ_ARRAY_SIZE(buf16));
+
+ TPtrC16 aBuf((const TUint16*)buf16, (TInt)len);
+ console->Write(aBuf);
+}
+
+/* perror util */
+static void app_perror(const char *title, pj_status_t status)
+{
+ char errmsg[PJ_ERR_MSG_SIZE];
+ pj_strerror(status, errmsg, sizeof(errmsg));
+ PJ_LOG(1,(THIS_FILE, "Error: %s: %s", title, errmsg));
+}
+
+/* Application init */
+static pj_status_t app_init()
+{
+ unsigned i, count;
+ pj_status_t status;
+
+ /* Redirect log */
+ pj_log_set_log_func((void (*)(int,const char*,int)) &log_writer);
+ pj_log_set_decor(PJ_LOG_HAS_NEWLINE);
+ pj_log_set_level(3);
+
+ /* Init pjlib */
+ status = pj_init();
+ if (status != PJ_SUCCESS) {
+ app_perror("pj_init()", status);
+ return status;
+ }
+
+ pj_caching_pool_init(&cp, NULL, 0);
+
+ /* Init sound subsystem */
+ status = pjmedia_aud_subsys_init(&cp.factory);
+ if (status != PJ_SUCCESS) {
+ app_perror("pjmedia_snd_init()", status);
+ pj_caching_pool_destroy(&cp);
+ pj_shutdown();
+ return status;
+ }
+
+ count = pjmedia_aud_dev_count();
+ PJ_LOG(3,(THIS_FILE, "Device count: %d", count));
+ for (i=0; i<count; ++i) {
+ pjmedia_aud_dev_info info;
+ pj_status_t status;
+
+ status = pjmedia_aud_dev_get_info(i, &info);
+ pj_assert(status == PJ_SUCCESS);
+ PJ_LOG(3, (THIS_FILE, "%d: %s %d/%d %dHz",
+ i, info.name, info.input_count, info.output_count,
+ info.default_samples_per_sec));
+
+ unsigned j;
+
+ /* Print extended formats supported by this audio device */
+ PJ_LOG(3, (THIS_FILE, " Extended formats supported:"));
+ for (j = 0; j < info.ext_fmt_cnt; ++j) {
+ const char *fmt_name = NULL;
+
+ switch (info.ext_fmt[j].id) {
+ case PJMEDIA_FORMAT_PCMA:
+ fmt_name = "PCMA";
+ break;
+ case PJMEDIA_FORMAT_PCMU:
+ fmt_name = "PCMU";
+ break;
+ case PJMEDIA_FORMAT_AMR:
+ fmt_name = "AMR-NB";
+ break;
+ case PJMEDIA_FORMAT_G729:
+ fmt_name = "G729";
+ break;
+ case PJMEDIA_FORMAT_ILBC:
+ fmt_name = "ILBC";
+ break;
+ case PJMEDIA_FORMAT_PCM:
+ fmt_name = "PCM";
+ break;
+ default:
+ fmt_name = "Unknown";
+ break;
+ }
+ PJ_LOG(3, (THIS_FILE, " - %s", fmt_name));
+ }
+ }
+
+ /* Create pool */
+ pool = pj_pool_create(&cp.factory, THIS_FILE, 512, 512, NULL);
+ if (pool == NULL) {
+ app_perror("pj_pool_create()", status);
+ pj_caching_pool_destroy(&cp);
+ pj_shutdown();
+ return status;
+ }
+
+ /* Init delay buffer */
+ status = pjmedia_delay_buf_create(pool, THIS_FILE, CLOCK_RATE,
+ SAMPLES_PER_FRAME, CHANNEL_COUNT,
+ 0, 0, &delaybuf);
+ if (status != PJ_SUCCESS) {
+ app_perror("pjmedia_delay_buf_create()", status);
+ //pj_caching_pool_destroy(&cp);
+ //pj_shutdown();
+ //return status;
+ }
+
+ return PJ_SUCCESS;
+}
+
+
+/* Sound capture callback */
+static pj_status_t rec_cb(void *user_data,
+ pjmedia_frame *frame)
+{
+ PJ_UNUSED_ARG(user_data);
+
+ if (param.ext_fmt.id == PJMEDIA_FORMAT_PCM) {
+ pjmedia_delay_buf_put(delaybuf, (pj_int16_t*)frame->buf);
+
+ if (frame->size != SAMPLES_PER_FRAME*2) {
+ PJ_LOG(3, (THIS_FILE, "Size captured = %u",
+ frame->size));
+ }
+ } else {
+ pjmedia_frame_ext *f_src = (pjmedia_frame_ext*)frame;
+ pjmedia_frame_ext *f_dst = (pjmedia_frame_ext*)frame_buf;
+
+ copy_frame_ext(f_dst, f_src);
+ }
+
+ ++rec_cnt;
+ return PJ_SUCCESS;
+}
+
+/* Play cb */
+static pj_status_t play_cb(void *user_data,
+ pjmedia_frame *frame)
+{
+ PJ_UNUSED_ARG(user_data);
+
+ if (param.ext_fmt.id == PJMEDIA_FORMAT_PCM) {
+ pjmedia_delay_buf_get(delaybuf, (pj_int16_t*)frame->buf);
+ frame->size = SAMPLES_PER_FRAME*2;
+ frame->type = PJMEDIA_FRAME_TYPE_AUDIO;
+ } else {
+ pjmedia_frame_ext *f_src = (pjmedia_frame_ext*)frame_buf;
+ pjmedia_frame_ext *f_dst = (pjmedia_frame_ext*)frame;
+
+ copy_frame_ext(f_dst, f_src);
+ }
+
+ ++play_cnt;
+ return PJ_SUCCESS;
+}
+
+/* Start sound */
+static pj_status_t snd_start(unsigned flag)
+{
+ pj_status_t status;
+
+ if (strm != NULL) {
+ app_perror("snd already open", PJ_EINVALIDOP);
+ return PJ_EINVALIDOP;
+ }
+
+ pjmedia_aud_dev_default_param(0, &param);
+ param.channel_count = CHANNEL_COUNT;
+ param.clock_rate = CLOCK_RATE;
+ param.samples_per_frame = SAMPLES_PER_FRAME;
+ param.dir = (pjmedia_dir) flag;
+ param.ext_fmt.id = PJMEDIA_FORMAT_AMR;
+ param.ext_fmt.bitrate = 12200;
+ param.output_route = PJMEDIA_AUD_DEV_ROUTE_LOUDSPEAKER;
+
+ status = pjmedia_aud_stream_create(&param, &rec_cb, &play_cb, NULL, &strm);
+ if (status != PJ_SUCCESS) {
+ app_perror("snd open", status);
+ return status;
+ }
+
+ rec_cnt = play_cnt = 0;
+ pj_gettimeofday(&t_start);
+
+ pjmedia_delay_buf_reset(delaybuf);
+
+ status = pjmedia_aud_stream_start(strm);
+ if (status != PJ_SUCCESS) {
+ app_perror("snd start", status);
+ pjmedia_aud_stream_destroy(strm);
+ strm = NULL;
+ return status;
+ }
+
+ return PJ_SUCCESS;
+}
+
+/* Stop sound */
+static pj_status_t snd_stop()
+{
+ pj_time_val now;
+ pj_status_t status;
+
+ if (strm == NULL) {
+ app_perror("snd not open", PJ_EINVALIDOP);
+ return PJ_EINVALIDOP;
+ }
+
+ status = pjmedia_aud_stream_stop(strm);
+ if (status != PJ_SUCCESS) {
+ app_perror("snd failed to stop", status);
+ }
+ status = pjmedia_aud_stream_destroy(strm);
+ strm = NULL;
+
+ pj_gettimeofday(&now);
+ PJ_TIME_VAL_SUB(now, t_start);
+
+ PJ_LOG(3,(THIS_FILE, "Duration: %d.%03d", now.sec, now.msec));
+ PJ_LOG(3,(THIS_FILE, "Captured: %d", rec_cnt));
+ PJ_LOG(3,(THIS_FILE, "Played: %d", play_cnt));
+
+ return status;
+}
+
+/* Shutdown application */
+static void app_fini()
+{
+ if (strm)
+ snd_stop();
+
+ pjmedia_aud_subsys_shutdown();
+ pjmedia_delay_buf_destroy(delaybuf);
+ pj_pool_release(pool);
+ pj_caching_pool_destroy(&cp);
+ pj_shutdown();
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+/*
+ * The interractive console UI
+ */
+#include <e32base.h>
+
+class ConsoleUI : public CActive
+{
+public:
+ ConsoleUI(CConsoleBase *con);
+
+ // Run console UI
+ void Run();
+
+ // Stop
+ void Stop();
+
+protected:
+ // Cancel asynchronous read.
+ void DoCancel();
+
+ // Implementation: called when read has completed.
+ void RunL();
+
+private:
+ CConsoleBase *con_;
+};
+
+
+ConsoleUI::ConsoleUI(CConsoleBase *con)
+: CActive(EPriorityUserInput), con_(con)
+{
+ CActiveScheduler::Add(this);
+}
+
+// Run console UI
+void ConsoleUI::Run()
+{
+ con_->Read(iStatus);
+ SetActive();
+}
+
+// Stop console UI
+void ConsoleUI::Stop()
+{
+ DoCancel();
+}
+
+// Cancel asynchronous read.
+void ConsoleUI::DoCancel()
+{
+ con_->ReadCancel();
+}
+
+static void PrintMenu()
+{
+ PJ_LOG(3, (THIS_FILE, "\n\n"
+ "Menu:\n"
+ " a Start bidir sound\n"
+ " t Start recorder\n"
+ " p Start player\n"
+ " d Stop & close sound\n"
+ " w Quit\n"));
+}
+
+// Implementation: called when read has completed.
+void ConsoleUI::RunL()
+{
+ TKeyCode kc = con_->KeyCode();
+ pj_bool_t reschedule = PJ_TRUE;
+
+ switch (kc) {
+ case 'w':
+ snd_stop();
+ CActiveScheduler::Stop();
+ reschedule = PJ_FALSE;
+ break;
+ case 'a':
+ snd_start(PJMEDIA_DIR_CAPTURE_PLAYBACK);
+ break;
+ case 't':
+ snd_start(PJMEDIA_DIR_CAPTURE);
+ break;
+ case 'p':
+ snd_start(PJMEDIA_DIR_PLAYBACK);
+ break;
+ case 'd':
+ snd_stop();
+ break;
+ default:
+ PJ_LOG(3,(THIS_FILE, "Keycode '%c' (%d) is pressed",
+ kc, kc));
+ break;
+ }
+
+ PrintMenu();
+
+ if (reschedule)
+ Run();
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+int app_main()
+{
+ if (app_init() != PJ_SUCCESS)
+ return -1;
+
+ // Run the UI
+ ConsoleUI *con = new ConsoleUI(console);
+
+ con->Run();
+
+ PrintMenu();
+ CActiveScheduler::Start();
+
+ delete con;
+
+ app_fini();
+ return 0;
+}
+
diff --git a/pjsip-apps/src/symsndtest/main_symbian.cpp b/pjsip-apps/src/symsndtest/main_symbian.cpp
new file mode 100644
index 0000000..d160a6c
--- /dev/null
+++ b/pjsip-apps/src/symsndtest/main_symbian.cpp
@@ -0,0 +1,83 @@
+/* $Id: main_symbian.cpp 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <e32std.h>
+#include <e32base.h>
+#include <e32std.h>
+#include <e32cons.h>
+#include <stdlib.h>
+
+
+// Global Variables
+CConsoleBase* console;
+
+// Needed by APS
+TPtrC APP_UID = _L("A000000E");
+
+int app_main();
+
+
+////////////////////////////////////////////////////////////////////////////
+
+LOCAL_C void DoStartL()
+{
+ CActiveScheduler *scheduler = new (ELeave) CActiveScheduler;
+ CleanupStack::PushL(scheduler);
+ CActiveScheduler::Install(scheduler);
+
+ app_main();
+
+ CActiveScheduler::Install(NULL);
+ CleanupStack::Pop(scheduler);
+ delete scheduler;
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+
+// E32Main()
+GLDEF_C TInt E32Main()
+{
+ // Mark heap usage
+ __UHEAP_MARK;
+
+ // Create cleanup stack
+ CTrapCleanup* cleanup = CTrapCleanup::New();
+
+ // Create output console
+ TRAPD(createError, console = Console::NewL(_L("Console"), TSize(KConsFullScreen,KConsFullScreen)));
+ if (createError)
+ return createError;
+
+ TRAPD(startError, DoStartL());
+
+ //console->Printf(_L("[press any key to close]\n"));
+ //console->Getch();
+
+ delete console;
+ delete cleanup;
+
+ CloseSTDLIB();
+
+ // Mark end of heap usage, detect memory leaks
+ __UHEAP_MARKEND;
+ return KErrNone;
+}
+
diff --git a/pjsip-apps/src/symsndtest/symsndtest_reg.rss b/pjsip-apps/src/symsndtest/symsndtest_reg.rss
new file mode 100644
index 0000000..642f7bf
--- /dev/null
+++ b/pjsip-apps/src/symsndtest/symsndtest_reg.rss
@@ -0,0 +1,10 @@
+#include <appinfo.rh>
+
+UID2 KUidAppRegistrationResourceFile
+UID3 0xA000000E
+
+RESOURCE APP_REGISTRATION_INFO
+{
+ app_file="symsndtest";
+}
+
diff --git a/pjsip-apps/src/vidgui/INSTALL.TXT b/pjsip-apps/src/vidgui/INSTALL.TXT
new file mode 100644
index 0000000..6f94c93
--- /dev/null
+++ b/pjsip-apps/src/vidgui/INSTALL.TXT
@@ -0,0 +1,32 @@
+
+ vidgui
+
+This directory contains a Qt based video GUI sample.
+
+Requirements:
+========================
+ - pjsip built with video support
+ - Qt SDK version 4.5 or above (version <4.5 doesn't have Cocoa support)
+
+Build instructions:
+===================
+ - Build pjsip first
+ - Follow the instructions for the appropriate platform below:
+
+ Visual Studio
+ -------------
+ - Run this to generate Visual Studio project file:
+ c:> qmake -tp vc
+ - Open vidgui.vcproj and build the app
+
+
+ Mac OS X
+ --------
+ $ qmake -spec macx-g++
+ $ make
+
+ Linux
+ -----
+ $ qmake
+ $ make
+
diff --git a/pjsip-apps/src/vidgui/pj-pkgconfig.mak b/pjsip-apps/src/vidgui/pj-pkgconfig.mak
new file mode 100644
index 0000000..9139dc1
--- /dev/null
+++ b/pjsip-apps/src/vidgui/pj-pkgconfig.mak
@@ -0,0 +1,10 @@
+include ../../../build.mak
+
+cflags:
+ @echo $(PJ_CFLAGS) $(CFLAGS)
+
+cxxflags: cflags
+
+ldflags:
+ @echo $(PJ_LDFLAGS) $(PJ_LDLIBS) $(LDFLAGS)
+
diff --git a/pjsip-apps/src/vidgui/vidgui.cpp b/pjsip-apps/src/vidgui/vidgui.cpp
new file mode 100644
index 0000000..9e1d540
--- /dev/null
+++ b/pjsip-apps/src/vidgui/vidgui.cpp
@@ -0,0 +1,735 @@
+/* $Id: vidgui.cpp 4060 2012-04-17 09:55:30Z ming $ */
+/*
+ * Copyright (C) 2011-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include "vidgui.h"
+#include "vidwin.h"
+
+#if defined(PJ_WIN32)
+# define SDL_MAIN_HANDLED
+#endif
+
+#include <SDL.h>
+#include <assert.h>
+#include <QMessageBox>
+
+#define LOG_FILE "vidgui.log"
+#define THIS_FILE "vidgui.cpp"
+
+///////////////////////////////////////////////////////////////////////////
+//
+// SETTINGS
+//
+
+//
+// These configure SIP registration
+//
+#define USE_REGISTRATION 0
+#define SIP_DOMAIN "pjsip.org"
+#define SIP_USERNAME "vidgui"
+#define SIP_PASSWORD "secret"
+#define SIP_PORT 5080
+#define SIP_TCP 1
+
+//
+// NAT helper settings
+//
+#define USE_ICE 1
+#define USE_STUN 0
+#define STUN_SRV "stun.pjsip.org"
+
+//
+// Devices settings
+//
+#define DEFAULT_CAP_DEV PJMEDIA_VID_DEFAULT_CAPTURE_DEV
+//#define DEFAULT_CAP_DEV 1
+#define DEFAULT_REND_DEV PJMEDIA_VID_DEFAULT_RENDER_DEV
+
+
+//
+// End of Settings
+///////////////////////////////////////////////////////////////////////////
+
+
+MainWin *MainWin::theInstance_;
+
+MainWin::MainWin(QWidget *parent)
+: QWidget(parent), accountId_(-1), currentCall_(-1),
+ preview_on(false), video_(NULL), video_prev_(NULL)
+{
+ theInstance_ = this;
+
+ initLayout();
+ emit signalCallReleased();
+}
+
+MainWin::~MainWin()
+{
+ quit();
+ theInstance_ = NULL;
+}
+
+MainWin *MainWin::instance()
+{
+ return theInstance_;
+}
+
+void MainWin::initLayout()
+{
+ //statusBar_ = new QStatusBar(this);
+
+ /* main layout */
+ QHBoxLayout *hbox_main = new QHBoxLayout;
+ //QVBoxLayout *vbox_left = new QVBoxLayout;
+ vbox_left = new QVBoxLayout;
+ QVBoxLayout *vbox_right = new QVBoxLayout;
+ hbox_main->addLayout(vbox_left);
+ hbox_main->addLayout(vbox_right);
+
+ /* Left pane */
+ QHBoxLayout *hbox_url = new QHBoxLayout;
+ hbox_url->addWidget(new QLabel(tr("Url:")));
+ hbox_url->addWidget(url_=new QLineEdit(tr("sip:")), 1);
+ vbox_left->addLayout(hbox_url);
+
+ /* Right pane */
+ vbox_right->addWidget((localUri_ = new QLabel));
+ vbox_right->addWidget((vidEnabled_ = new QCheckBox(tr("Enable &video"))));
+ vbox_right->addWidget((previewButton_=new QPushButton(tr("Start &Preview"))));
+ vbox_right->addWidget((callButton_=new QPushButton(tr("Call"))));
+ vbox_right->addWidget((hangupButton_=new QPushButton(tr("Hangup"))));
+ vbox_right->addWidget((quitButton_=new QPushButton(tr("Quit"))));
+
+#if PJMEDIA_HAS_VIDEO
+ vidEnabled_->setCheckState(Qt::Checked);
+#else
+ vidEnabled_->setCheckState(Qt::Unchecked);
+ vidEnabled_->setEnabled(false);
+#endif
+
+ /* Outest layout */
+ QVBoxLayout *vbox_outest = new QVBoxLayout;
+ vbox_outest->addLayout(hbox_main);
+ vbox_outest->addWidget((statusBar_ = new QLabel));
+
+ setLayout(vbox_outest);
+
+ connect(previewButton_, SIGNAL(clicked()), this, SLOT(preview()));
+ connect(callButton_, SIGNAL(clicked()), this, SLOT(call()));
+ connect(hangupButton_, SIGNAL(clicked()), this, SLOT(hangup()));
+ connect(quitButton_, SIGNAL(clicked()), this, SLOT(quit()));
+ //connect(this, SIGNAL(close()), this, SLOT(quit()));
+ connect(vidEnabled_, SIGNAL(stateChanged(int)), this, SLOT(onVidEnabledChanged(int)));
+
+ // UI updates must be done in the UI thread!
+ connect(this, SIGNAL(signalNewCall(int, bool)),
+ this, SLOT(onNewCall(int, bool)));
+ connect(this, SIGNAL(signalCallReleased()),
+ this, SLOT(onCallReleased()));
+ connect(this, SIGNAL(signalInitVideoWindow()),
+ this, SLOT(initVideoWindow()));
+ connect(this, SIGNAL(signalShowStatus(const QString&)),
+ this, SLOT(doShowStatus(const QString&)));
+}
+
+void MainWin::quit()
+{
+ delete video_prev_;
+ video_prev_ = NULL;
+ delete video_;
+ video_ = NULL;
+
+ pjsua_destroy();
+ qApp->quit();
+}
+
+void MainWin::showStatus(const char *msg)
+{
+ PJ_LOG(3,(THIS_FILE, "%s", msg));
+
+ QString msg_ = QString::fromUtf8(msg);
+ emit signalShowStatus(msg_);
+}
+
+void MainWin::doShowStatus(const QString& msg)
+{
+ //statusBar_->showMessage(msg);
+ statusBar_->setText(msg);
+}
+
+void MainWin::showError(const char *title, pj_status_t status)
+{
+ char errmsg[PJ_ERR_MSG_SIZE];
+ char errline[120];
+
+ pj_strerror(status, errmsg, sizeof(errmsg));
+ snprintf(errline, sizeof(errline), "%s error: %s", title, errmsg);
+ showStatus(errline);
+}
+
+void MainWin::onVidEnabledChanged(int state)
+{
+ pjsua_call_setting call_setting;
+
+ if (currentCall_ == -1)
+ return;
+
+ pjsua_call_setting_default(&call_setting);
+ call_setting.vid_cnt = (state == Qt::Checked);
+
+ pjsua_call_reinvite2(currentCall_, &call_setting, NULL);
+}
+
+void MainWin::onNewCall(int cid, bool incoming)
+{
+ pjsua_call_info ci;
+
+ pj_assert(currentCall_ == -1);
+ currentCall_ = cid;
+
+ pjsua_call_get_info(cid, &ci);
+ url_->setText(ci.remote_info.ptr);
+ url_->setEnabled(false);
+ hangupButton_->setEnabled(true);
+
+ if (incoming) {
+ callButton_->setText(tr("Answer"));
+ callButton_->setEnabled(true);
+ } else {
+ callButton_->setEnabled(false);
+ }
+
+ //video_->setText(ci.remote_contact.ptr);
+ //video_->setWindowTitle(ci.remote_contact.ptr);
+}
+
+void MainWin::onCallReleased()
+{
+ url_->setEnabled(true);
+ callButton_->setEnabled(true);
+ callButton_->setText(tr("Call"));
+ hangupButton_->setEnabled(false);
+ currentCall_ = -1;
+
+ delete video_;
+ video_ = NULL;
+}
+
+void MainWin::preview()
+{
+ if (preview_on) {
+ delete video_prev_;
+ video_prev_ = NULL;
+
+ pjsua_vid_preview_stop(DEFAULT_CAP_DEV);
+
+ showStatus("Preview stopped");
+ previewButton_->setText(tr("Start &Preview"));
+ } else {
+ pjsua_vid_win_id wid;
+ pjsua_vid_win_info wi;
+ pjsua_vid_preview_param pre_param;
+ pj_status_t status;
+
+ pjsua_vid_preview_param_default(&pre_param);
+ pre_param.rend_id = DEFAULT_REND_DEV;
+ pre_param.show = PJ_FALSE;
+
+ status = pjsua_vid_preview_start(DEFAULT_CAP_DEV, &pre_param);
+ if (status != PJ_SUCCESS) {
+ char errmsg[PJ_ERR_MSG_SIZE];
+ pj_strerror(status, errmsg, sizeof(errmsg));
+ QMessageBox::critical(0, "Error creating preview", errmsg);
+ return;
+ }
+ wid = pjsua_vid_preview_get_win(DEFAULT_CAP_DEV);
+ pjsua_vid_win_get_info(wid, &wi);
+
+ video_prev_ = new VidWin(&wi.hwnd);
+ video_prev_->putIntoLayout(vbox_left);
+ //Using this will cause SDL window to display blank
+ //screen sometimes, probably because it's using different
+ //X11 Display
+ //status = pjsua_vid_win_set_show(wid, PJ_TRUE);
+ //This is handled by VidWin now
+ //video_prev_->show_sdl();
+ showStatus("Preview started");
+
+ previewButton_->setText(tr("Stop &Preview"));
+ }
+ preview_on = !preview_on;
+}
+
+
+void MainWin::call()
+{
+ if (callButton_->text() == "Answer") {
+ pjsua_call_setting call_setting;
+
+ pj_assert(currentCall_ != -1);
+
+ pjsua_call_setting_default(&call_setting);
+ call_setting.vid_cnt = (vidEnabled_->checkState()==Qt::Checked);
+
+ pjsua_call_answer2(currentCall_, &call_setting, 200, NULL, NULL);
+ callButton_->setEnabled(false);
+ } else {
+ pj_status_t status;
+ QString dst = url_->text();
+ char uri[256];
+ pjsua_call_setting call_setting;
+
+ pj_ansi_strncpy(uri, dst.toAscii().data(), sizeof(uri));
+ pj_str_t uri2 = pj_str((char*)uri);
+
+ pj_assert(currentCall_ == -1);
+
+ pjsua_call_setting_default(&call_setting);
+ call_setting.vid_cnt = (vidEnabled_->checkState()==Qt::Checked);
+
+ status = pjsua_call_make_call(accountId_, &uri2, &call_setting,
+ NULL, NULL, &currentCall_);
+ if (status != PJ_SUCCESS) {
+ showError("make call", status);
+ return;
+ }
+ }
+}
+
+void MainWin::hangup()
+{
+ pj_assert(currentCall_ != -1);
+ //pjsua_call_hangup(currentCall_, PJSIP_SC_BUSY_HERE, NULL, NULL);
+ pjsua_call_hangup_all();
+ emit signalCallReleased();
+}
+
+
+void MainWin::initVideoWindow()
+{
+ pjsua_call_info ci;
+ unsigned i;
+
+ if (currentCall_ == -1)
+ return;
+
+ delete video_;
+ video_ = NULL;
+
+ pjsua_call_get_info(currentCall_, &ci);
+ for (i = 0; i < ci.media_cnt; ++i) {
+ if ((ci.media[i].type == PJMEDIA_TYPE_VIDEO) &&
+ (ci.media[i].dir & PJMEDIA_DIR_DECODING))
+ {
+ pjsua_vid_win_info wi;
+ pjsua_vid_win_get_info(ci.media[i].stream.vid.win_in, &wi);
+
+ video_= new VidWin(&wi.hwnd);
+ video_->putIntoLayout(vbox_left);
+
+ break;
+ }
+ }
+}
+
+void MainWin::on_reg_state(pjsua_acc_id acc_id)
+{
+ pjsua_acc_info info;
+
+ pjsua_acc_get_info(acc_id, &info);
+
+ char reg_status[80];
+ char status[120];
+
+ if (!info.has_registration) {
+ pj_ansi_snprintf(reg_status, sizeof(reg_status), "%.*s",
+ (int)info.status_text.slen,
+ info.status_text.ptr);
+
+ } else {
+ pj_ansi_snprintf(reg_status, sizeof(reg_status),
+ "%d/%.*s (expires=%d)",
+ info.status,
+ (int)info.status_text.slen,
+ info.status_text.ptr,
+ info.expires);
+
+ }
+
+ snprintf(status, sizeof(status),
+ "%.*s: %s\n",
+ (int)info.acc_uri.slen, info.acc_uri.ptr,
+ reg_status);
+ showStatus(status);
+}
+
+void MainWin::on_call_state(pjsua_call_id call_id, pjsip_event *e)
+{
+ pjsua_call_info ci;
+
+ PJ_UNUSED_ARG(e);
+
+ pjsua_call_get_info(call_id, &ci);
+
+ if (currentCall_ == -1 && ci.state < PJSIP_INV_STATE_DISCONNECTED &&
+ ci.role == PJSIP_ROLE_UAC)
+ {
+ emit signalNewCall(call_id, false);
+ }
+
+ char status[80];
+ if (ci.state == PJSIP_INV_STATE_DISCONNECTED) {
+ snprintf(status, sizeof(status), "Call is %s (%s)",
+ ci.state_text.ptr,
+ ci.last_status_text.ptr);
+ showStatus(status);
+ emit signalCallReleased();
+ } else {
+ snprintf(status, sizeof(status), "Call is %s", pjsip_inv_state_name(ci.state));
+ showStatus(status);
+ }
+}
+
+void MainWin::on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id,
+ pjsip_rx_data *rdata)
+{
+ PJ_UNUSED_ARG(acc_id);
+ PJ_UNUSED_ARG(rdata);
+
+ if (currentCall_ != -1) {
+ pjsua_call_answer(call_id, PJSIP_SC_BUSY_HERE, NULL, NULL);
+ return;
+ }
+
+ emit signalNewCall(call_id, true);
+
+ pjsua_call_info ci;
+ char status[80];
+
+ pjsua_call_get_info(call_id, &ci);
+ snprintf(status, sizeof(status), "Incoming call from %.*s",
+ (int)ci.remote_info.slen, ci.remote_info.ptr);
+ showStatus(status);
+}
+
+void MainWin::on_call_media_state(pjsua_call_id call_id)
+{
+ pjsua_call_info ci;
+
+ pjsua_call_get_info(call_id, &ci);
+
+ for (unsigned i=0; i<ci.media_cnt; ++i) {
+ if (ci.media[i].type == PJMEDIA_TYPE_AUDIO) {
+ switch (ci.media[i].status) {
+ case PJSUA_CALL_MEDIA_ACTIVE:
+ pjsua_conf_connect(ci.media[i].stream.aud.conf_slot, 0);
+ pjsua_conf_connect(0, ci.media[i].stream.aud.conf_slot);
+ break;
+ default:
+ break;
+ }
+ } else if (ci.media[i].type == PJMEDIA_TYPE_VIDEO) {
+ emit signalInitVideoWindow();
+ }
+ }
+}
+
+//
+// pjsua callbacks
+//
+static void on_reg_state(pjsua_acc_id acc_id)
+{
+ MainWin::instance()->on_reg_state(acc_id);
+}
+
+static void on_call_state(pjsua_call_id call_id, pjsip_event *e)
+{
+ MainWin::instance()->on_call_state(call_id, e);
+}
+
+static void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id,
+ pjsip_rx_data *rdata)
+{
+ MainWin::instance()->on_incoming_call(acc_id, call_id, rdata);
+}
+
+static void on_call_media_state(pjsua_call_id call_id)
+{
+ MainWin::instance()->on_call_media_state(call_id);
+}
+
+//
+// initStack()
+//
+bool MainWin::initStack()
+{
+ pj_status_t status;
+
+ //showStatus("Creating stack..");
+ status = pjsua_create();
+ if (status != PJ_SUCCESS) {
+ showError("pjsua_create", status);
+ return false;
+ }
+
+ showStatus("Initializing stack..");
+
+ pjsua_config ua_cfg;
+ pjsua_config_default(&ua_cfg);
+ pjsua_callback ua_cb;
+ pj_bzero(&ua_cb, sizeof(ua_cb));
+ ua_cfg.cb.on_reg_state = &::on_reg_state;
+ ua_cfg.cb.on_call_state = &::on_call_state;
+ ua_cfg.cb.on_incoming_call = &::on_incoming_call;
+ ua_cfg.cb.on_call_media_state = &::on_call_media_state;
+#if USE_STUN
+ ua_cfg.stun_srv_cnt = 1;
+ ua_cfg.stun_srv[0] = pj_str((char*)STUN_SRV);
+#endif
+
+ pjsua_logging_config log_cfg;
+ pjsua_logging_config_default(&log_cfg);
+ log_cfg.log_filename = pj_str((char*)LOG_FILE);
+
+ pjsua_media_config med_cfg;
+ pjsua_media_config_default(&med_cfg);
+ med_cfg.enable_ice = USE_ICE;
+
+ status = pjsua_init(&ua_cfg, &log_cfg, &med_cfg);
+ if (status != PJ_SUCCESS) {
+ showError("pjsua_init", status);
+ goto on_error;
+ }
+
+ //
+ // Create UDP and TCP transports
+ //
+ pjsua_transport_config udp_cfg;
+ pjsua_transport_id udp_id;
+ pjsua_transport_config_default(&udp_cfg);
+ udp_cfg.port = SIP_PORT;
+
+ status = pjsua_transport_create(PJSIP_TRANSPORT_UDP,
+ &udp_cfg, &udp_id);
+ if (status != PJ_SUCCESS) {
+ showError("UDP transport creation", status);
+ goto on_error;
+ }
+
+ pjsua_transport_info udp_info;
+ status = pjsua_transport_get_info(udp_id, &udp_info);
+ if (status != PJ_SUCCESS) {
+ showError("UDP transport info", status);
+ goto on_error;
+ }
+
+#if SIP_TCP
+ pjsua_transport_config tcp_cfg;
+ pjsua_transport_config_default(&tcp_cfg);
+ tcp_cfg.port = 0;
+
+ status = pjsua_transport_create(PJSIP_TRANSPORT_TCP,
+ &tcp_cfg, NULL);
+ if (status != PJ_SUCCESS) {
+ showError("TCP transport creation", status);
+ goto on_error;
+ }
+#endif
+
+ //
+ // Create account
+ //
+ pjsua_acc_config acc_cfg;
+ pjsua_acc_config_default(&acc_cfg);
+#if USE_REGISTRATION
+ acc_cfg.id = pj_str( (char*)"<sip:" SIP_USERNAME "@" SIP_DOMAIN ">");
+ acc_cfg.reg_uri = pj_str((char*) ("sip:" SIP_DOMAIN));
+ acc_cfg.cred_count = 1;
+ acc_cfg.cred_info[0].realm = pj_str((char*)"*");
+ acc_cfg.cred_info[0].scheme = pj_str((char*)"digest");
+ acc_cfg.cred_info[0].username = pj_str((char*)SIP_USERNAME);
+ acc_cfg.cred_info[0].data = pj_str((char*)SIP_PASSWORD);
+
+# if SIP_TCP
+ acc_cfg.proxy[acc_cfg.proxy_cnt++] = pj_str((char*) "<sip:" SIP_DOMAIN ";transport=tcp>");
+# endif
+
+#else
+ char sip_id[80];
+ snprintf(sip_id, sizeof(sip_id),
+ "sip:%s@%.*s:%u", SIP_USERNAME,
+ (int)udp_info.local_name.host.slen,
+ udp_info.local_name.host.ptr,
+ udp_info.local_name.port);
+ acc_cfg.id = pj_str(sip_id);
+#endif
+
+ acc_cfg.vid_cap_dev = DEFAULT_CAP_DEV;
+ acc_cfg.vid_rend_dev = DEFAULT_REND_DEV;
+ acc_cfg.vid_in_auto_show = PJ_TRUE;
+ acc_cfg.vid_out_auto_transmit = PJ_TRUE;
+
+ status = pjsua_acc_add(&acc_cfg, PJ_TRUE, &accountId_);
+ if (status != PJ_SUCCESS) {
+ showError("Account creation", status);
+ goto on_error;
+ }
+
+ localUri_->setText(acc_cfg.id.ptr);
+
+ //
+ // Start pjsua!
+ //
+ showStatus("Starting stack..");
+ status = pjsua_start();
+ if (status != PJ_SUCCESS) {
+ showError("pjsua_start", status);
+ goto on_error;
+ }
+
+ showStatus("Ready");
+
+ return true;
+
+on_error:
+ pjsua_destroy();
+ return false;
+}
+
+/*
+ * A simple registrar, invoked by default_mod_on_rx_request()
+ */
+static void simple_registrar(pjsip_rx_data *rdata)
+{
+ pjsip_tx_data *tdata;
+ const pjsip_expires_hdr *exp;
+ const pjsip_hdr *h;
+ unsigned cnt = 0;
+ pjsip_generic_string_hdr *srv;
+ pj_status_t status;
+
+ status = pjsip_endpt_create_response(pjsua_get_pjsip_endpt(),
+ rdata, 200, NULL, &tdata);
+ if (status != PJ_SUCCESS)
+ return;
+
+ exp = (pjsip_expires_hdr*)
+ pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_EXPIRES, NULL);
+
+ h = rdata->msg_info.msg->hdr.next;
+ while (h != &rdata->msg_info.msg->hdr) {
+ if (h->type == PJSIP_H_CONTACT) {
+ const pjsip_contact_hdr *c = (const pjsip_contact_hdr*)h;
+ int e = c->expires;
+
+ if (e < 0) {
+ if (exp)
+ e = exp->ivalue;
+ else
+ e = 3600;
+ }
+
+ if (e > 0) {
+ pjsip_contact_hdr *nc = (pjsip_contact_hdr*)
+ pjsip_hdr_clone(tdata->pool, h);
+ nc->expires = e;
+ pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)nc);
+ ++cnt;
+ }
+ }
+ h = h->next;
+ }
+
+ srv = pjsip_generic_string_hdr_create(tdata->pool, NULL, NULL);
+ srv->name = pj_str((char*)"Server");
+ srv->hvalue = pj_str((char*)"pjsua simple registrar");
+ pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)srv);
+
+ pjsip_endpt_send_response2(pjsua_get_pjsip_endpt(),
+ rdata, tdata, NULL, NULL);
+}
+
+/* Notification on incoming request */
+static pj_bool_t default_mod_on_rx_request(pjsip_rx_data *rdata)
+{
+ /* Simple registrar */
+ if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method,
+ &pjsip_register_method) == 0)
+ {
+ simple_registrar(rdata);
+ return PJ_TRUE;
+ }
+
+ return PJ_FALSE;
+}
+
+/* The module instance. */
+static pjsip_module mod_default_handler =
+{
+ NULL, NULL, /* prev, next. */
+ { (char*)"mod-default-handler", 19 }, /* Name. */
+ -1, /* Id */
+ PJSIP_MOD_PRIORITY_APPLICATION+99, /* Priority */
+ NULL, /* load() */
+ NULL, /* start() */
+ NULL, /* stop() */
+ NULL, /* unload() */
+ &default_mod_on_rx_request, /* on_rx_request() */
+ NULL, /* on_rx_response() */
+ NULL, /* on_tx_request. */
+ NULL, /* on_tx_response() */
+ NULL, /* on_tsx_state() */
+
+};
+
+int main(int argc, char *argv[])
+{
+ /* At least on Linux, we have to initialize SDL video subsystem prior to
+ * creating/initializing QApplication, otherwise we'll segfault miserably
+ * in SDL_CreateWindow(). Here's a stack trace if you're interested:
+
+ Thread [7] (Suspended: Signal 'SIGSEGV' received. Description: Segmentation fault.)
+ 13 XCreateIC()
+ 12 SetupWindowData()
+ 11 X11_CreateWindow()
+ 10 SDL_CreateWindow()
+ ..
+ */
+ if ( SDL_InitSubSystem(SDL_INIT_VIDEO) < 0 ) {
+ printf("Unable to init SDL: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ QApplication app(argc, argv);
+
+ MainWin win;
+ win.show();
+
+ if (!win.initStack()) {
+ win.quit();
+ return 1;
+ }
+
+ /* We want to be registrar too! */
+ if (pjsua_get_pjsip_endpt()) {
+ pjsip_endpt_register_module(pjsua_get_pjsip_endpt(),
+ &mod_default_handler);
+ }
+
+ return app.exec();
+}
+
diff --git a/pjsip-apps/src/vidgui/vidgui.h b/pjsip-apps/src/vidgui/vidgui.h
new file mode 100644
index 0000000..7b7ce7b
--- /dev/null
+++ b/pjsip-apps/src/vidgui/vidgui.h
@@ -0,0 +1,102 @@
+/* $Id: vidgui.h 3926 2011-12-27 12:50:17Z bennylp $ */
+/*
+ * Copyright (C) 2011-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef VIDGUI_H_
+#define VIDGUI_H_
+
+#include <QApplication>
+#include <QCheckBox>
+#include <QFont>
+#include <QLabel>
+#include <QLineEdit>
+#include <QMainWindow>
+#include <QObject>
+#include <QPushButton>
+#include <QStatusBar>
+#include <QTextEdit>
+#include <QVBoxLayout>
+#include <QWidget>
+
+#include <pjsua.h>
+
+class VidWin;
+
+class MainWin : public QWidget
+{
+ Q_OBJECT
+
+public:
+ MainWin(QWidget *parent = 0);
+ virtual ~MainWin();
+
+ static MainWin *instance();
+
+ bool initStack();
+ void showError(const char *title, pj_status_t status);
+ void showStatus(const char *msg);
+
+ void on_reg_state(pjsua_acc_id acc_id);
+ void on_call_state(pjsua_call_id call_id, pjsip_event *e);
+ void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id, pjsip_rx_data *rdata);
+ void on_call_media_state(pjsua_call_id call_id);
+
+signals:
+ void signalNewCall(int, bool);
+ void signalCallReleased();
+ void signalInitVideoWindow();
+ void signalShowStatus(const QString&);
+
+public slots:
+ void preview();
+ void call();
+ void hangup();
+ void quit();
+ void onVidEnabledChanged(int state);
+
+ void onNewCall(int cid, bool incoming);
+ void onCallReleased();
+ void initVideoWindow();
+ void doShowStatus(const QString& msg);
+
+private:
+ static MainWin *theInstance_;
+ pjsua_acc_id accountId_;
+ pjsua_call_id currentCall_;
+ bool preview_on;
+
+private:
+ QPushButton *callButton_,
+ *hangupButton_,
+ *quitButton_,
+ *previewButton_;
+ QCheckBox *vidEnabled_;
+ QLineEdit *url_;
+ VidWin *video_;
+ VidWin *video_prev_;
+ //QStatusBar *statusBar_;
+ QLabel *statusBar_;
+ QLabel *localUri_;
+
+ QVBoxLayout *vbox_left;
+
+ void initLayout();
+};
+
+
+
+#endif /* VIDGUI_H_ */
diff --git a/pjsip-apps/src/vidgui/vidgui.pro b/pjsip-apps/src/vidgui/vidgui.pro
new file mode 100644
index 0000000..806b2b6
--- /dev/null
+++ b/pjsip-apps/src/vidgui/vidgui.pro
@@ -0,0 +1,36 @@
+win32 {
+ DEFINES += PJ_WIN32=1
+ INCLUDEPATH += ../../../pjlib/include ../../../pjlib-util/include \
+ ../../../pjnath/include ../../../pjmedia/include \
+ ../../../pjsip/include
+
+ # These to enable static linking
+ #CONFIG += static
+ #DEFINES += STATIC
+
+ CONFIG(debug) {
+ LIBS += ../../../lib/libpjproject-i386-Win32-vc8-Debug.lib
+ } else {
+ LIBS += ../../../lib/libpjproject-i386-Win32-vc8-Release.lib
+ }
+ LIBS += Iphlpapi.lib dsound.lib \
+ dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib \
+ odbccp32.lib ole32.lib user32.lib gdi32.lib advapi32.lib
+} else {
+ LIBS += $$system(make -f pj-pkgconfig.mak ldflags)
+ QMAKE_CXXFLAGS += $$system(make --silent -f pj-pkgconfig.mak cflags)
+
+ macx {
+ QMAKE_CXXFLAGS += -ObjC++
+ }
+}
+
+TEMPLATE = app
+CONFIG += thread debug
+TARGET =
+DEPENDPATH += .
+
+# Input
+HEADERS += vidgui.h vidwin.h
+SOURCES += vidgui.cpp vidwin.cpp
+
diff --git a/pjsip-apps/src/vidgui/vidwin.cpp b/pjsip-apps/src/vidgui/vidwin.cpp
new file mode 100644
index 0000000..1caee89
--- /dev/null
+++ b/pjsip-apps/src/vidgui/vidwin.cpp
@@ -0,0 +1,309 @@
+/* $Id: vidwin.cpp 4060 2012-04-17 09:55:30Z ming $ */
+/*
+ * Copyright (C) 2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include "vidwin.h"
+#include <QEvent>
+
+#define THIS_FILE "vidwin.cpp"
+#define TRACE_(...) PJ_LOG(4,(THIS_FILE, __VA_ARGS__))
+
+VidWin::VidWin(const pjmedia_vid_dev_hwnd *hwnd_,
+ QWidget* parent,
+ Qt::WindowFlags f) :
+ QWidget(parent, f), orig_parent(NULL),
+ size_hint(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)
+{
+ setAttribute(Qt::WA_NativeWindow);
+
+ /* Make this widget a bit "lighter" */
+ setAttribute(Qt::WA_UpdatesDisabled);
+ setAttribute(Qt::WA_PaintOnScreen);
+ setAttribute(Qt::WA_NoSystemBackground);
+ setAttribute(Qt::WA_PaintOutsidePaintEvent);
+ setUpdatesEnabled(false);
+
+ pj_bzero(&hwnd, sizeof(hwnd));
+ if (hwnd_) {
+ hwnd = *hwnd_;
+ }
+}
+
+
+VidWin::~VidWin()
+{
+ show_sdl(false);
+ detach();
+}
+
+void VidWin::putIntoLayout(QBoxLayout *box)
+{
+ box->addWidget(this, 1);
+ show();
+ activateWindow();
+}
+
+bool VidWin::event(QEvent *e)
+{
+ switch(e->type()) {
+
+ case QEvent::Resize:
+ set_size();
+ break;
+
+ case QEvent::ParentChange:
+ get_size();
+ if (0) {
+ QRect qr = rect();
+ if (qr.width() > size_hint.width())
+ size_hint.setWidth(qr.width());
+ if (qr.height() > size_hint.height())
+ size_hint.setWidth(qr.height());
+ }
+ setFixedSize(size_hint);
+ attach();
+ break;
+
+ case QEvent::Show:
+ show_sdl(true);
+ // revert to default size hint, make it resizable
+ setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
+ break;
+
+ case QEvent::Hide:
+ show_sdl(false);
+ break;
+
+ default:
+ break;
+ }
+
+ return QWidget::event(e);
+}
+
+/* Platform specific code */
+
+#if defined(_WIN32) && !defined(_WIN32_WINCE)
+
+#include <windows.h>
+
+void VidWin::attach()
+{
+ if (!hwnd.info.win.hwnd) return;
+
+ HWND w = (HWND)hwnd.info.win.hwnd;
+ HWND new_parent = (HWND)winId();
+ orig_parent = GetParent(w);
+
+ //SetWindowLong(w, GWL_STYLE, WS_CHILD);
+ SetParent(w, new_parent);
+ TRACE_("%p new parent handle = %p", w, new_parent);
+}
+
+void VidWin::detach()
+{
+ if (!hwnd.info.win.hwnd) return;
+
+ HWND w = (HWND)hwnd.info.win.hwnd;
+ SetParent(w, (HWND)orig_parent);
+ TRACE_("%p revert parent handle to %p", w, orig_parent);
+}
+
+void VidWin::set_size()
+{
+ if (!hwnd.info.win.hwnd) return;
+
+ HWND w = (HWND)hwnd.info.win.hwnd;
+ QRect qr = rect();
+ UINT swp_flag = SWP_NOACTIVATE;
+ SetWindowPos(w, HWND_TOP, 0, 0, qr.width(), qr.height(), swp_flag);
+ TRACE_("%p new size = %dx%d", w, qr.width(), qr.height());
+}
+
+void VidWin::get_size()
+{
+ if (!hwnd.info.win.hwnd) return;
+
+ HWND w = (HWND)hwnd.info.win.hwnd;
+ RECT r;
+ if (GetWindowRect(w, &r))
+ size_hint = QSize(r.right-r.left+1, r.bottom-r.top+1);
+ TRACE_("%p size = %dx%d", w, size_hint.width(), size_hint.height());
+}
+
+void VidWin::show_sdl(bool visible)
+{
+ if (!hwnd.info.win.hwnd) return;
+
+ HWND w = (HWND)hwnd.info.win.hwnd;
+ ShowWindow(w, visible ? SW_SHOW : SW_HIDE);
+}
+
+#elif defined(__APPLE__)
+
+#import<Cocoa/Cocoa.h>
+
+void VidWin::attach()
+{
+ if (!hwnd.info.cocoa.window) return;
+
+ /* Embed hwnd to widget */
+ NSWindow *w = (NSWindow*)hwnd.info.cocoa.window;
+ NSWindow *parent = [(NSView*)winId() window];
+ orig_parent = [w parentWindow];
+
+ //[w setStyleMask:NSBorderlessWindowMask];
+
+ //Can't use this, as sometime the video window may not get reparented.
+ //[w setParentWindow:parent];
+
+ [parent addChildWindow:w ordered:NSWindowAbove];
+ TRACE_("%p new parent handle = %p", w, parent);
+}
+
+
+void VidWin::detach()
+{
+ if (!hwnd.info.cocoa.window) return;
+
+ NSWindow *w = (NSWindow*)hwnd.info.cocoa.window;
+ NSWindow *parent = [(NSView*)winId() window];
+ [parent removeChildWindow:w];
+}
+
+
+void VidWin::set_size()
+{
+ if (!hwnd.info.cocoa.window) return;
+
+ /* Update position and size */
+ NSWindow *w = (NSWindow*)hwnd.info.cocoa.window;
+ NSRect r;
+
+ NSView* v = (NSView*)winId();
+ r = [v bounds];
+ r = [v convertRectToBase:r];
+ r.origin = [[v window] convertBaseToScreen:r.origin];
+
+ QRect qr = rect();
+ [w setFrame:r display:NO];
+
+ TRACE_("%p new size = %dx%d", w, qr.width(), qr.height());
+}
+
+void VidWin::get_size()
+{
+ if (!hwnd.info.cocoa.window) return;
+
+ NSWindow *w = (NSWindow*)hwnd.info.cocoa.window;
+
+ size_hint = QSize(300, 200);
+
+ TRACE_("%p size = %dx%d", 0, size_hint.width(), size_hint.height());
+}
+
+void VidWin::show_sdl(bool visible)
+{
+ if (!hwnd.info.cocoa.window) return;
+
+ NSWindow *w = (NSWindow*)hwnd.info.cocoa.window;
+
+ if (visible) {
+ [[w contentView]setHidden:NO];
+ } else {
+ [[w contentView]setHidden:YES];
+ }
+}
+
+#elif defined(linux) || defined(__linux)
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <QX11Info>
+#include <stdio.h>
+
+#define GET_DISPLAY() QX11Info::display()
+//#define GET_DISPLAY() (Display*)hwnd.info.x11.display
+
+void VidWin::attach()
+{
+ if (!hwnd.info.x11.window) return;
+
+ /* Embed hwnd to widget */
+
+ // Use Qt X11 display here, using window creator X11 display may cause
+ // the window failing to embed to this QWidget.
+ //Display *d = (Display*)hwnd.info.x11.display;
+ Display *d = GET_DISPLAY();
+ Window w = (Window)hwnd.info.x11.window;
+ Window parent = (Window)this->winId();
+ int err = XReparentWindow(d, w, parent, 0, 0);
+ TRACE_("%p new parent handle = %p, err = %d",
+ (void*)w,(void*)parent, err);
+}
+
+
+void VidWin::detach()
+{
+}
+
+
+void VidWin::set_size()
+{
+ if (!hwnd.info.x11.window) return;
+
+ /* Update position and size */
+ Display *d = GET_DISPLAY();
+ Window w = (Window)hwnd.info.x11.window;
+ QRect qr = rect();
+
+ int err = XResizeWindow(d, w, qr.width(), qr.height());
+ TRACE_("[%p,%p] new size = %dx%d, err = %d",
+ (void*)d, (void*)w, qr.width(), qr.height(), err);
+}
+
+void VidWin::get_size()
+{
+ if (!hwnd.info.x11.window) return;
+
+ Display *d = GET_DISPLAY();
+ Window w = (Window)hwnd.info.x11.window;
+
+ XWindowAttributes attr;
+ XGetWindowAttributes(d, w, &attr);
+ size_hint = QSize(attr.width, attr.height);
+ TRACE_("%p size = %dx%d", w, size_hint.width(), size_hint.height());
+}
+
+void VidWin::show_sdl(bool visible)
+{
+ if (!hwnd.info.x11.window) return;
+
+ Display *d = GET_DISPLAY();
+ Window w = (Window)hwnd.info.x11.window;
+
+ if (visible) {
+ XMapRaised(d, w);
+ } else {
+ XUnmapWindow(d, w);
+ }
+
+ XFlush(d);
+}
+
+#endif
+
diff --git a/pjsip-apps/src/vidgui/vidwin.h b/pjsip-apps/src/vidgui/vidwin.h
new file mode 100644
index 0000000..3ab10b2
--- /dev/null
+++ b/pjsip-apps/src/vidgui/vidwin.h
@@ -0,0 +1,55 @@
+/* $Id: vidwin.h 4060 2012-04-17 09:55:30Z ming $ */
+/*
+ * Copyright (C) 2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef VIDWIN_H
+#define VIDWIN_H
+
+#include <pjsua.h>
+#include <QWidget>
+#include <QBoxLayout>
+
+class VidWin : public QWidget
+{
+ Q_OBJECT
+
+public:
+ VidWin(const pjmedia_vid_dev_hwnd *hwnd,
+ QWidget* parent = 0,
+ Qt::WindowFlags f = 0);
+ virtual ~VidWin();
+ QSize sizeHint() const { return size_hint; }
+
+ void putIntoLayout(QBoxLayout *layout);
+
+protected:
+ virtual bool event(QEvent *e);
+
+private:
+ pjmedia_vid_dev_hwnd hwnd;
+ void *orig_parent;
+ QSize size_hint;
+
+ void attach();
+ void detach();
+ void set_size();
+ void get_size();
+ void show_sdl(bool visible=true);
+};
+
+#endif
+