]> sjero.net Git - linphone/commitdiff
Merge branch 'master' of git.linphone.org:linphone into dev_gtk_new_ui
authorMargaux Clerc <margaux.clerc@belledonne-communications>
Fri, 14 Dec 2012 15:36:15 +0000 (16:36 +0100)
committerMargaux Clerc <margaux.clerc@belledonne-communications>
Fri, 14 Dec 2012 15:36:15 +0000 (16:36 +0100)
Conflicts:
gtk/parameters.ui

56 files changed:
Makefile.am
README.macos
build/android/common.mk
configure.ac
console/Makefile.am
coreapi/.gitignore
coreapi/Makefile.am
coreapi/callbacks.c
coreapi/conference.c
coreapi/help/Makefile.am
coreapi/help/doxygen.dox
coreapi/linphonecall.c
coreapi/linphonecore.c
coreapi/linphonecore.h
coreapi/linphonecore_jni.cc
coreapi/linphonecore_utils.h
coreapi/lpconfig.h
coreapi/misc.c
coreapi/plugins/buddylookup/Makefile.am
coreapi/private.h
coreapi/proxy.c
coreapi/sal.c
coreapi/sal.h
coreapi/sal_eXosip2.c
coreapi/test_numbers.c
gtk/main.c
gtk/parameters.ui
gtk/propertybox.c
java/common/org/linphone/core/LinphoneCall.java
java/common/org/linphone/core/LinphoneCallLog.java
java/common/org/linphone/core/LinphoneCallParams.java
java/common/org/linphone/core/LinphoneCallStats.java
java/common/org/linphone/core/LinphoneChatMessage.java
java/common/org/linphone/core/LinphoneCore.java
java/common/org/linphone/core/LinphoneCoreFactory.java
java/common/org/linphone/core/LinphoneFriend.java
java/common/org/linphone/core/OnlineStatus.java
java/common/org/linphone/core/PayloadType.java
java/impl/org/linphone/core/LinphoneCallImpl.java
java/impl/org/linphone/core/LinphoneCallLogImpl.java
java/impl/org/linphone/core/LinphoneCallParamsImpl.java
java/impl/org/linphone/core/LinphoneCoreImpl.java
m4/Makefile.am
m4/intl.m4
m4/obsolete.m4 [new file with mode: 0644]
m4/po.m4
mediastreamer2
oRTP
share/Makefile.am
share/Makefile.inc
share/xml/Makefile.am [new file with mode: 0644]
share/xml/lpconfig.xsd [new file with mode: 0644]
tools/Makefile.am [new file with mode: 0644]
tools/xml2lpc.c [new file with mode: 0644]
tools/xml2lpc.h [new file with mode: 0644]
tools/xml2lpc_test.c [new file with mode: 0644]

index 4aa4332f2f99962cc4b085e3c66f015dbb994c12..507e6f4dc8e209d29720369dbf30b232ce9b0c30 100644 (file)
@@ -4,7 +4,7 @@
 ACLOCAL_AMFLAGS = -I m4 $(ACLOCAL_MACOS_FLAGS)
 
 SUBDIRS = build m4 pixmaps po @ORTP_DIR@ @MS2_DIR@ \
-               coreapi console gtk share scripts
+               coreapi console gtk share scripts tools
 
 
 
@@ -18,13 +18,13 @@ OPTIONAL_SOUNDS=\
                share/sounds/linphone/rings/rock.wav
 
 
-INSTALLDIR=$(shell cd $(top_builddir) && pwd)/linphone-install
+INSTALLDIR=$(abs_top_builddir)/linphone-install
 INSTALLDIR_WITH_PREFIX=$(INSTALLDIR)/$(prefix)
-ZIPFILE=$(shell cd $(top_builddir) && pwd)/$(PACKAGE)-win32-$(VERSION).zip
+ZIPFILE=$(abs_top_builddir)/$(PACKAGE)-win32-$(VERSION).zip
 ZIP_EXCLUDED=include lib \
                $(OPTIONAL_SOUNDS)
 
-SDK_ZIPFILE=$(shell cd $(top_builddir) && pwd)/lib$(PACKAGE)-win32-$(VERSION).zip
+SDK_ZIPFILE=$(abs_top_builddir)/lib$(PACKAGE)-win32-$(VERSION).zip
 SDK_EXCLUDED= \
        bin/linphone.exe \
        lib/*.la \
@@ -38,11 +38,11 @@ SDK_EXCLUDED= \
 GTK_PREFIX=/
 GTK_THEME=Outcrop
 GTK_FILELIST=gtk+-2.22.1.filelist
-GTK_FILELIST_PATH=$(shell cd $(top_srcdir) && pwd)/$(GTK_FILELIST)
+GTK_FILELIST_PATH=$(abs_top_srcdir)/$(GTK_FILELIST)
 LINPHONEDEPS_FILELIST=linphone-deps.filelist
-WINBINDIST_FILES=$(shell cat $(top_srcdir)/$(LINPHONEDEPS_FILELIST))
+WINBINDIST_FILES=`cat $(abs_top_srcdir)/$(LINPHONEDEPS_FILELIST)`
 ISS_SCRIPT=linphone.iss
-ISS_SCRIPT_PATH=$(shell cd $(top_srcdir) && pwd)/$(ISS_SCRIPT)
+ISS_SCRIPT_PATH=$(abs_top_srcdir)/$(ISS_SCRIPT)
 #path to Inno Setup 5 compiler
 ISCC=ISCC.exe
 PACKAGE_WIN32_FILELIST=$(PACKAGE)-win32.filelist
@@ -102,7 +102,7 @@ other-cherrypick:
        cd $(GTK_PREFIX) && \
        for file in $(WINBINDIST_FILES) ; do \
                if test -d $$file; then \
-                       mkdir -p $(INSTALLDIR_WITH_PREFIX)/$$file ;\
+                       $(MKDIR_P) $(INSTALLDIR_WITH_PREFIX)/$$file ;\
                else \
                        cp $$file $(INSTALLDIR_WITH_PREFIX)/$$file ;\
                fi \
@@ -119,18 +119,18 @@ gtk-cherrypick:
        cd $(GTK_PREFIX) && \
        for file in `cat $(GTK_FILELIST_PATH)` ; do \
                if test -d $$file; then \
-                       mkdir -p $(INSTALLDIR_WITH_PREFIX)/$$file ;\
+                       $(MKDIR_P) $(INSTALLDIR_WITH_PREFIX)/$$file ;\
                else \
                        cp $$file $(INSTALLDIR_WITH_PREFIX)/$$file ;\
                fi \
        done && \
-       mkdir -p  $(INSTALLDIR_WITH_PREFIX)/share/themes && \
+       $(MKDIR_P) $(INSTALLDIR_WITH_PREFIX)/share/themes && \
        cp -rf share/themes/$(GTK_THEME) $(INSTALLDIR_WITH_PREFIX)/share/themes/.
 
 zip:
        rm -f $(ZIPFILE)
        rm -rf $(INSTALLDIR)
-       mkdir -p $(INSTALLDIR)
+       $(MKDIR_P) $(INSTALLDIR)
        make install DESTDIR=$(INSTALLDIR)
 #remove unwanted linphone stuff
        cd $(INSTALLDIR_WITH_PREFIX) && rm -rf $(ZIP_EXCLUDED)
@@ -145,7 +145,7 @@ zip:
 sdk:
        rm -f $(SDK_ZIPFILE)
        rm -rf $(INSTALLDIR)
-       mkdir -p $(INSTALLDIR)
+       $(MKDIR_P) $(INSTALLDIR)
        make install DESTDIR=$(INSTALLDIR)
 # remove unwanted stuff (gtk interface)
        cd $(INSTALLDIR_WITH_PREFIX) && rm -rf $(SDK_EXCLUDED)
@@ -182,12 +182,12 @@ newdate:
        cd gtk && $(MAKE) newdate
 
 if HAVE_MD5SUM
-GEN_MD5=$(shell $(MD5SUM) linphone-$(VERSION).tar.gz | awk {'print $$4'})
+GEN_MD5=`$(MD5SUM) linphone-$(VERSION).tar.gz | awk {'print $$4'}`
 else
-GEN_MD5=$(shell $(MD5SUM) linphone-$(VERSION).tar.gz | awk {'print $$1'})
+GEN_MD5=`$(MD5SUM) linphone-$(VERSION).tar.gz | awk {'print $$1'}`
 endif
 
-Portfile:      $(top_srcdir)/scripts/Portfile.tmpl dist
+Portfile: $(top_srcdir)/scripts/Portfile.tmpl dist
        sed -e 's/\@VERSION\@/$(LINPHONE_VERSION)/g' \
          -e 's/\@LINPHONE_MD5\@/$(GEN_MD5)/' < $< > $@
 
@@ -210,7 +210,7 @@ $(LIBICONV_HACK):
 
 bundle: $(LIBICONV_HACK)
        rm -rf $(INSTALLDIR)
-       mkdir -p $(INSTALLDIR)
+       $(MKDIR_P) $(INSTALLDIR)
        make install DESTDIR=$(INSTALLDIR)
        BUNDLE_PREFIX=$(BUNDLEPREFIX) \
        LINPHONE_INSTALL_PREFIX=$(INSTALLDIR_WITH_PREFIX) \
index aecd2922fab00e70e1f69e7e6165a1a72d273733..1648a3135fb691a05c030efbcdd84a4788dbd760 100644 (file)
@@ -28,7 +28,7 @@ You need:
 - Install zrtpcpp (optional), for unbreakable call encryption
  $ port install cmake
  $ git clone git://git.linphone.org/zrtpcpp.git
- $ cd zrtpcpp && cmake -Denable_ccrtp=false . && make
+ $ cd zrtpcpp && cmake -Denable-ccrtp=false . && make
  $ sudo make install
 
 - Install gtk. It is recommended to use the quartz backend for better integration.
index 4db1f68090a2452e0058c324429ef79ac2526ded..99e1787a752ff4f7381cfb8a7bf714a04155e8bf 100644 (file)
@@ -57,13 +57,16 @@ endif
 LOCAL_CFLAGS += \
        -D_BYTE_ORDER=_LITTLE_ENDIAN \
        -DORTP_INET6 \
-        -DINET6 \
-        -DOSIP_MT \
+       -DINET6 \
+       -DOSIP_MT \
+       -DHAVE_EXOSIP_GET_VERSION \
        -DHAVE_EXOSIP_RESET_TRANSPORTS \
        -DENABLE_TRACE \
        -DLINPHONE_VERSION=\"$(LINPHONE_VERSION)\" \
        -DLINPHONE_PLUGINS_DIR=\"\\tmp\" \
-       -DLOG_DOMAIN=$(MY_LOG_DOMAIN) 
+       -DLOG_DOMAIN=$(MY_LOG_DOMAIN) \
+       -DHAVE_EXOSIP_TRYLOCK=1 \
+       -DHAVE_EXOSIP_TLS_VERIFY_CERTIFICATE=1 
 
 LOCAL_CFLAGS += -DIN_LINPHONE
 
@@ -74,13 +77,18 @@ LOCAL_CFLAGS += -DHAVE_X264
 endif
 endif
 
+ifeq ($(USE_JAVAH),1)
+LOCAL_CFLAGS += -DUSE_JAVAH
+endif
+
 LOCAL_C_INCLUDES += \
        $(LOCAL_PATH) \
        $(LOCAL_PATH)/include \
        $(LOCAL_PATH)/../oRTP/include \
        $(LOCAL_PATH)/../mediastreamer2/include \
        $(LOCAL_PATH)/../../externals/exosip/include \
-       $(LOCAL_PATH)/../../externals/osip/include 
+       $(LOCAL_PATH)/../../externals/osip/include \
+       $(LOCAL_PATH)/../../../gen
 
 LOCAL_LDLIBS += -llog -ldl
 
index 84081f46c76fa15c80028fd6b7e62e4b6fb80e38..1005ab2f598d11fbcb486437f22943fb5bd2ee30 100644 (file)
@@ -32,9 +32,9 @@ AC_MSG_NOTICE([licensed under the terms of the General Public License (GPL)])
 AM_INIT_AUTOMAKE
 AC_SUBST([LIBTOOL_DEPS])
 m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])],)
+AC_SUBST([docdir], [${datadir}/doc])
 AC_CONFIG_HEADER(config.h)
 AC_CONFIG_MACRO_DIR([m4])
-AC_SUBST([mkdir_p])
 AC_ISC_POSIX
 AC_PROG_CC
 AC_PROG_CXX
@@ -118,31 +118,58 @@ fi
 
 GETTEXT_PACKAGE=linphone
 AC_SUBST(GETTEXT_PACKAGE)
-AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE",[The name of the gettext package name])
+AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE",[The name of the gettext package name])
 dnl AC_CHECK_LIB(intl,libintl_gettext)
 
 AC_CHECK_FUNCS([get_current_dir_name strndup stpcpy] )
 
 AC_ARG_ENABLE(x11,
-                         [  --disable-x11    Disable X11 support],
-                         [case "${enableval}" in
-                         yes) enable_x11=true ;;
-                         no)  enable_x11=false ;;
-                         *) AC_MSG_ERROR(bad value ${enableval} for --disable-x11) ;;
-                         esac],[enable_x11=true])
+      [AS_HELP_STRING([--disable-x11], [Disable X11 support (default=no)])],
+      [case "${enableval}" in
+        yes) enable_x11=true ;;
+        no)  enable_x11=false ;;
+        *) AC_MSG_ERROR(bad value ${enableval} for --disable-x11) ;;
+      esac],[enable_x11=true])
 
 dnl conditionnal build of console interface.
 AC_ARG_ENABLE(console_ui,
-      [  --enable-console_ui=[yes/no]    Turn on or off compilation of console interface [default=yes]],
+      [AS_HELP_STRING([--enable-console_ui=[yes/no]], [Turn on or off compilation of console interface (default=yes)])],
       [case "${enableval}" in
         yes) console_ui=true ;;
         no)  console_ui=false ;;
         *) AC_MSG_ERROR(bad value ${enableval} for --enable-console_ui) ;;
       esac],[console_ui=true])
 
+dnl conditionnal build of tools.
+AC_ARG_ENABLE(tools,
+      [AS_HELP_STRING([--enable-tools=[yes/no]], [Turn on or off compilation of console interface (default=yes)])],
+      [case "${enableval}" in
+        yes) build_tools=true ;;
+        no)  build_tools=false ;;
+        *) AC_MSG_ERROR(bad value ${enableval} for --enable-tools) ;;
+      esac],[build_tools=check])
+
+dnl check libxml2 (needed for tools)
+if test "$build_tools" != "false" ; then
+       PKG_CHECK_MODULES(LIBXML2, [libxml-2.0],[],
+       [
+               if test "$build_tools" = "true" ; then
+                       AC_MSG_ERROR([Could not found libxml2, tools cannot be compiled.])
+               else
+                       build_tools=false
+               fi
+       ])
+fi
+
+AM_CONDITIONAL(BUILD_TOOLS, test x$build_tools != xfalse)
+if test "$build_tools" != "false" ; then
+   build_tools=true
+   AC_DEFINE(BUILD_TOOLS, 1, [Define if tools enabled] ) 
+fi
+
 dnl conditionnal build of gtk interface.
 AC_ARG_ENABLE(gtk_ui,
-      [  --enable-gtk_ui=[yes/no]    Turn on or off compilation of gtk interface [default=yes]],
+      [AS_HELP_STRING([--enable-gtk_ui=[yes/no]], [Turn on or off compilation of gtk interface (default=yes)])],
       [case "${enableval}" in
         yes) gtk_ui=true ;;
         no)  gtk_ui=false ;;
@@ -160,12 +187,12 @@ else
 fi
 
 AC_ARG_ENABLE(notify,
-               [  --enable-notify=[yes/no]    Enable libnotify support [default=yes]],
-               [case "${enableval}" in
-                 yes) notify=true ;;
-                 no)  notify=false ;;
-                 *) AC_MSG_ERROR(bad value ${enableval} for --enable-notify) ;;
-               esac],[notify=true])
+      [AS_HELP_STRING([--enable-notify=[yes/no]], [Enable libnotify support (default=yes)])],
+      [case "${enableval}" in
+        yes) notify=true ;;
+        no)  notify=false ;;
+        *) AC_MSG_ERROR(bad value ${enableval} for --enable-notify) ;;
+      esac],[notify=true])
 
 dnl conditionnal build of the notify library
 if test "$gtk_ui" = "true" ; then
@@ -205,14 +232,14 @@ case "$host_cpu" in
                ;;
 esac
 
-AC_ARG_WITH( configdir,
-      [  --with-configdir      Set a APPDATA subdir where linphone is supposed to find its config (windows only) ],
+AC_ARG_WITH(configdir,
+      [AS_HELP_STRING([--with-configdir], [Set a APPDATA subdir where linphone is supposed to find its config (windows only)])],
       [ configdir=${withval}],[ configdir="Linphone" ])
 
 AC_DEFINE_UNQUOTED(LINPHONE_CONFIG_DIR,"$configdir",[Windows appdata subdir where linphonerc can be found])
 
 AC_ARG_ENABLE(relativeprefix,
-      [  --enable-relativeprefix    Build a linphone that finds its resources relatively to the directory where it is installed],
+      [AS_HELP_STRING([--enable-relativeprefix], [Build a linphone that finds its resources relatively to the directory where it is installed])],
       [case "${enableval}" in
         yes) relativeprefix=yes ;;
         no)  relativeprefix=no ;;
@@ -220,7 +247,7 @@ AC_ARG_ENABLE(relativeprefix,
       esac],[relativeprefix=guess])
 
 AC_ARG_ENABLE(date,
-      [  --enable-date    Use build date in internal version number],
+      [AS_HELP_STRING([--enable-date], [Use build date in internal version number])],
       [case "${enableval}" in
         yes) use_date=yes ;;
         no)  use_date=no ;;
@@ -234,7 +261,7 @@ fi
 
 dnl enable ipv6 support
 AC_ARG_ENABLE(ipv6,
-      [  --enable-ipv6    Turn on ipv6 support],
+      [AS_HELP_STRING([--enable-ipv6], [Turn on ipv6 support])],
       [case "${enableval}" in
         yes)  ipv6=true;;
         no)   ipv6=false;;
@@ -248,7 +275,7 @@ AC_SUBST(IPV6_CFLAGS)
 
 dnl enable timestamp support
 AC_ARG_ENABLE(ntp-timestamp,
-      [  --enable-ntp-timestamp Turn on NTP timestamping on received packet],
+      [AS_HELP_STRING([--enable-ntp-timestamp], [Turn on NTP timestamping on received packet])],
       [case "${enableval}" in
         yes)  ntptimestamp=true;;
         no)   ntptimestamp=false;;
@@ -256,17 +283,16 @@ AC_ARG_ENABLE(ntp-timestamp,
       esac],[ntptimestamp=false])
 
 AC_ARG_ENABLE(debug,
-                        [  --enable-debug=[yes/no]   enables the display of traces showing the execution of the library. [default=yes]],
-                        [case "${enableval}" in
-                                yes) debug_enabled=yes;;
-                                no) debug_enabled=no;;
-                                *) AC_MSG_ERROR("Bad value for --enable-debug");;
-                        esac],
-                        [debug_enabled=no])
+      [AS_HELP_STRING([--enable-debug=[yes/no]], [Enables the display of traces showing the execution of the library. (default=yes)])],
+      [case "${enableval}" in
+        yes) debug_enabled=yes;;
+        no) debug_enabled=no;;
+        *) AC_MSG_ERROR("Bad value for --enable-debug");;
+      esac],[debug_enabled=no])
 
 dnl enable truespeech codec support
 AC_ARG_ENABLE(truespeech,
-      [  --enable-truespeech    Turn on TrueSpeech support (x86 only)],
+      [AS_HELP_STRING([--enable-truespeech], [Turn on TrueSpeech support (x86 only)])],
       [case "${enableval}" in
         yes)  truespeech=true;;
         no)   truespeech=false;;
@@ -280,11 +306,11 @@ AC_SUBST(TRUESPEECH_CFLAGS)
 AM_CONDITIONAL([BUILD_TRUESPEECH], [test x$truespeech = xtrue])
 
 AC_ARG_ENABLE(nonstandard-gsm,
-      [  --enable-nonstandard-gsm    Enable GSM codec at nonstandard rates (11025hz, 16000hz)],
+      [AS_HELP_STRING([--enable-nonstandard-gsm], [Enable GSM codec at nonstandard rates (11025hz, 16000hz)])],
       [case "${enableval}" in
         yes) exotic_gsm=yes
-       AC_DEFINE(ENABLE_NONSTANDARD_GSM,1,[Defined when using gsm at nonstandard rates])
-        ;;
+         AC_DEFINE(ENABLE_NONSTANDARD_GSM,1,[Defined when using gsm at nonstandard rates])
+         ;;
         no)  exotic_gsm=no ;;
         *) AC_MSG_ERROR(bad value ${enableval} for --enable-nonstandard-gsm) ;;
       esac],[exotic_gsm=no])
@@ -292,7 +318,7 @@ AC_ARG_ENABLE(nonstandard-gsm,
 
 dnl support for RSVP (by Vincent Maury)
 AC_ARG_ENABLE(rsvp,
-[  --enable-rsvp           enable support for QoS reservations.],
+[AS_HELP_STRING([--enable-rsvp], [Enable support for QoS reservations.])],
 AC_DEFINE(VINCENT_MAURY_RSVP,1,[Tell whether RSVP support
 should be compiled.]) )
 
@@ -331,12 +357,12 @@ LP_CHECK_OSIP2
 
 dnl conditionnal build for ssl
 AC_ARG_ENABLE(ssl,
-               [  --enable-ssl    Turn on ssl support compiling. Required for sip tls. default = false],
-               [case "${enableval}" in
-               yes) build_ssl=true ;;
-               no)  build_ssl=false ;;
-               *) AC_MSG_ERROR(bad value ${enableval} for --enable-ssl) ;;
-               esac],[build_ssl=false])
+      [AS_HELP_STRING([--enable-ssl], [Turn on ssl support compiling. Required for sip tls. (default=false)])],
+      [case "${enableval}" in
+        yes) build_ssl=true ;;
+        no)  build_ssl=false ;;
+        *) AC_MSG_ERROR(bad value ${enableval} for --enable-ssl) ;;
+      esac],[build_ssl=false])
 
 if test "$build_ssl" = "true"; then
        PKG_CHECK_MODULES(OPENSSL, libssl >= 0.9.8)
@@ -367,16 +393,16 @@ fi
 
 dnl conditionnal build of video support
 AC_ARG_ENABLE(video,
-               [  --enable-video    Turn on video support compiling],
-               [case "${enableval}" in
-               yes) video=true ;;
-               no)  video=false ;;
-               *) AC_MSG_ERROR(bad value ${enableval} for --enable-video) ;;
-               esac],[video=true])
-               
+      [AS_HELP_STRING([--enable-video], [Turn on video support compiling])],
+      [case "${enableval}" in
+        yes) video=true ;;
+        no)  video=false ;;
+        *) AC_MSG_ERROR(bad value ${enableval} for --enable-video) ;;
+      esac],[video=true])
+
 AC_ARG_WITH( ffmpeg,
-               [  --with-ffmpeg                Sets the installation prefix of ffmpeg, needed for video support. [default=/usr] ],
-               [ ffmpegdir=${withval}],[ ffmpegdir=/usr ])
+      [AS_HELP_STRING([--with-ffmpeg], [Sets the installation prefix of ffmpeg, needed for video support. (default=/usr)])],
+      [ ffmpegdir=${withval}],[ ffmpegdir=/usr ])
 
 if test "$video" = "true"; then
        
@@ -393,7 +419,7 @@ if test "$video" = "true"; then
 fi
 
 AC_ARG_ENABLE(alsa,
-      [  --enable-alsa    Turn on alsa native support compiling],
+      [AS_HELP_STRING([--enable-alsa], [Turn on alsa native support compiling])],
       [case "${enableval}" in
         yes) alsa=true ;;
         no)  alsa=false ;;
@@ -401,7 +427,7 @@ AC_ARG_ENABLE(alsa,
       esac],[alsa=true])
 
 AC_ARG_ENABLE(zrtp,
-      [  --enable-zrtp    Turn on zrtp support ],
+      [AS_HELP_STRING([--enable-zrtp], [Turn on zrtp support])],
       [case "${enableval}" in
         yes) zrtp=true ;;
         no)  zrtp=false ;;
@@ -410,7 +436,7 @@ AC_ARG_ENABLE(zrtp,
 
 
 AC_ARG_ENABLE(portaudio,
-      [  --enable-portaudio    Turn on portaudio native support compiling],
+      [AS_HELP_STRING([--enable-portaudio], [Turn on portaudio native support compiling])],
       [case "${enableval}" in
         yes) portaudio=true ;;
         no)  portaudio=false ;;
@@ -419,8 +445,10 @@ AC_ARG_ENABLE(portaudio,
 
 dnl build console if required
 AM_CONDITIONAL(BUILD_CONSOLE, test x$console_ui = xtrue)
+
 dnl special things for arm-linux cross compilation toolchain
 AM_CONDITIONAL(ARMBUILD, test x$use_arm_toolchain = xyes)
+
 dnl compilation of gtk user interface
 AM_CONDITIONAL(BUILD_GTK_UI, [test x$gtk_ui = xtrue ] )
 AM_CONDITIONAL(BUILD_WIN32, test x$mingw_found = xyes )
@@ -440,7 +468,7 @@ if test "$has_sighandler_t" = "yes" ; then
 fi
 
 AC_ARG_ENABLE(assistant,
-      [  --enable-assistant    Turn on assistant compiling],
+      [AS_HELP_STRING([--enable-assistant], [Turn on assistant compiling])],
       [case "${enableval}" in
         yes) build_wizard=true ;;
         no)  build_wizard=false ;;
@@ -449,7 +477,7 @@ AC_ARG_ENABLE(assistant,
 
 dnl check libsoup (needed for wizard)
 if test "$build_wizard" != "false" ; then
-       PKG_CHECK_MODULES(LIBSOUP, [libsoup-2.4 >= 2.26],[build_wizard=true],
+       PKG_CHECK_MODULES(LIBSOUP, [libsoup-2.4 >= 2.26],[],
        [
                if test "$build_wizard" = "true" ; then
                        AC_MSG_ERROR([Could not found libsoup, assistant cannot be compiled.])
@@ -458,11 +486,22 @@ if test "$build_wizard" != "false" ; then
                fi
        ])
 fi
+if test "$build_wizard" != "false" ; then
+       PKG_CHECK_MODULES(LIBGTKWIZARD, [gtk+-2.0 >= 2.22.0],[],
+       [
+               if test "$build_wizard" = "true" ; then
+                       AC_MSG_ERROR([gtk+-2.0 < 2.22.0, assistant cannot be compiled.])
+               else
+                       build_wizard=false
+               fi
+       ])
+fi
 AC_SUBST(LIBSOUP_CFLAGS)
 AC_SUBST(LIBSOUP_LIBS)
-AM_CONDITIONAL(BUILD_WIZARD, test x$build_wizard = xtrue)
-if test "$build_wizard" = "true" ; then
-   AC_DEFINE( BUILD_WIZARD, 1, [Define if wizard enabled] ) 
+AM_CONDITIONAL(BUILD_WIZARD, test x$build_wizard != xfalse)
+if test "$build_wizard" != "false" ; then
+   build_wizard=true
+   AC_DEFINE(BUILD_WIZARD, 1, [Define if wizard enabled] ) 
 fi
 
 AC_CHECK_HEADERS(libudev.h)
@@ -520,7 +559,7 @@ AC_SUBST([MS2_DIR])
 
 
 AC_ARG_ENABLE(tunnel,
-      [  --enable-tunnel=[yes/no]    Turn on compilation of tunnel support [default=no]],
+      [AS_HELP_STRING([--enable-tunnel=[yes/no]], [Turn on compilation of tunnel support (default=no)])],
       [case "${enableval}" in
         yes) enable_tunnel=true ;;
         no)  enable_tunnel=false ;;
@@ -564,7 +603,7 @@ LINPHONE_PLUGINS_DIR="${package_prefix}/lib/liblinphone/plugins"
 AC_SUBST(LINPHONE_PLUGINS_DIR)
 
 AC_ARG_ENABLE(external-ortp,
-      [  --enable-external-ortp    Use external oRTP library],
+      [AS_HELP_STRING([--enable-external-ortp], [Use external oRTP library])],
       [case "${enableval}" in
         yes) external_ortp=true ;;
         no)  external_ortp=false ;;
@@ -595,7 +634,7 @@ AC_SUBST([ORTP_VERSION])
 AC_SUBST([ORTP_DIR])
 
 AC_ARG_ENABLE(tests_enabled,
-      [  --disable-tests    Disable compilation of tests],
+      [AS_HELP_STRING([--disable-tests], [Disable compilation of tests])],
       [case "${enableval}" in
         yes) tests_enabled=true ;;
         no)  tests_enabled=false ;;
@@ -632,9 +671,11 @@ share/fr/Makefile
 share/it/Makefile
 share/ja/Makefile
 share/cs/Makefile
+share/xml/Makefile
 share/linphone.pc
 share/linphone.desktop
 scripts/Makefile
+tools/Makefile
 linphone.spec
 linphone.iss
 ])
@@ -647,6 +688,7 @@ printf "* Video support\t\t\t%s\n" $video
 printf "* GTK interface\t\t\t%s\n" $gtk_ui
 printf "* Account assistant\t\t%s\n" $build_wizard
 printf "* Console interface\t\t%s\n" $console_ui
+printf "* Tools\t\t\t\t%s\n" $build_tools
 printf "* zRTP encryption (GPLv3)\t%s\n" $zrtp
 
 if test "$enable_tunnel" = "true" ; then
@@ -654,4 +696,3 @@ if test "$enable_tunnel" = "true" ; then
 fi
 
 echo "Now type 'make' to compile, and then 'make install' as root to install it."
-
index bbc310967e43b6b0090968975514ad26ef20de48..23a7635d1713109b23aea8fc625ec42519fe953c 100644 (file)
@@ -1,25 +1,32 @@
 ## Process this file with automake to produce Makefile.in
 
-COMMON_CFLAGS=$(STRICT_OPTIONS) -DIN_LINPHONE -DENABLE_TRACE -D_ORTP_SOURCE $(VIDEO_CFLAGS) $(READLINE_CFLAGS) $(OSIP_CFLAGS)
-
-if BUILD_CONSOLE
-
-INCLUDES = \
-       -I$(top_srcdir)\
-       -I$(top_srcdir)/coreapi\
+AM_CPPFLAGS=\
+       -I$(top_srcdir) \
+       -I$(top_srcdir)/coreapi \
+       -I$(top_srcdir)/exosip
+
+COMMON_CFLAGS=\
+       -DIN_LINPHONE \
+       -DENABLE_TRACE \
+       -D_ORTP_SOURCE \
+       $(STRICT_OPTIONS) \
+       $(VIDEO_CFLAGS) \
+       $(READLINE_CFLAGS) \
+       $(OSIP_CFLAGS) \
        $(ORTP_CFLAGS) \
-       -I$(top_srcdir)/exosip \
        $(MEDIASTREAMER_CFLAGS)
 
-bin_PROGRAMS =  linphonec linphonecsh
+if BUILD_CONSOLE
+
+bin_PROGRAMS=linphonec linphonecsh
 
 if BUILD_WIN32
-bin_PROGRAMS += linphoned
+bin_PROGRAMS+=linphoned
 endif
 
-linphonec_SOURCES = linphonec.c linphonec.h commands.c
+linphonec_SOURCES=linphonec.c linphonec.h commands.c
 linphonec_CFLAGS=$(COMMON_CFLAGS) $(CONSOLE_FLAGS)
-linphonec_LDADD = $(top_builddir)/coreapi/liblinphone.la $(READLINE_LIBS)  \
+linphonec_LDADD=$(top_builddir)/coreapi/liblinphone.la $(READLINE_LIBS)  \
                $(MEDIASTREAMER_LIBS) \
                $(ORTP_LIBS) \
                $(SPEEX_LIBS) \
@@ -28,15 +35,15 @@ linphonec_LDADD = $(top_builddir)/coreapi/liblinphone.la $(READLINE_LIBS)  \
 
 if BUILD_WIN32
 #special build of linphonec to detach from the windows console
-linphoned_SOURCES = $(linphonec_SOURCES)
+linphoned_SOURCES=$(linphonec_SOURCES)
 linphoned_CFLAGS=$(COMMON_CFLAGS) $(GUI_FLAGS)
 linphoned_LDADD=$(linphonec_LDADD)
 endif
 
 
-linphonecsh_SOURCES = shell.c
-linphonecsh_CFLAGS = $(CONSOLE_FLAGS)
-linphonecsh_LDADD = $(ORTP_LIBS)
+linphonecsh_SOURCES=shell.c
+linphonecsh_CFLAGS=$(COMMON_CFLAGS) $(CONSOLE_FLAGS)
+linphonecsh_LDADD=$(ORTP_LIBS)
 
 endif
 
index c5d084fa64ad39cdab4eb498e31c51626800433a..81d1b7647313ee440fdf0a055d1aac2c6801eed5 100644 (file)
@@ -5,3 +5,4 @@ Makefile.in
 *.lo
 *.la
 *.loT
+liblinphone_gitversion.h
index c706751ac1b06ab477524211612d02e1f0ccc5ec..790612cab48b7b59ece5d5664e575cc6b78b077e 100644 (file)
@@ -1,7 +1,17 @@
+GITVERSION_FILE=liblinphone_gitversion.h
+GITVERSION_FILE_TMP=liblinphone_gitversion.h.tmp
+GITDESCRIBE=`git describe`
+GITREVISION=`git rev-parse HEAD`
+
+ECHO=/bin/echo
 
 SUBDIRS=. help
 
-EXTRA_DIST=linphonecore_jni.cc
+EXTRA_DIST=linphonecore_jni.cc $(GITVERSION_FILE)
+
+BUILT_SOURCES=$(GITVERSION_FILE)
+
+CLEANFILES=$(GITVERSION_FILE)
 
 ## Process this file with automake to produce Makefile.in
 linphone_includedir=$(includedir)/linphone
@@ -12,10 +22,6 @@ if BUILD_TUNNEL
 linphone_include_HEADERS+=linphone_tunnel.h
 endif
 
-INCLUDES = \
-       -I$(top_srcdir)
-
-
 lib_LTLIBRARIES=liblinphone.la
 
 liblinphone_la_SOURCES=\
@@ -41,7 +47,8 @@ liblinphone_la_SOURCES=\
        lsd.c linphonecore_utils.h \
        ec-calibrator.c \
        conference.c \
-       linphone_tunnel.cc
+       linphone_tunnel.cc \
+       $(GITVERSION_FILE)
        
 if BUILD_WIZARD
 liblinphone_la_SOURCES+=sipwizard.c 
@@ -78,8 +85,11 @@ test_numbers_SOURCES=test_numbers.c
 test_numbers_LDADD=liblinphone.la $(liblinphone_la_LIBADD)
 endif
 
+AM_CPPFLAGS=\
+       -I$(top_srcdir)
 
-AM_CFLAGS=$(STRICT_OPTIONS)  -DIN_LINPHONE \
+AM_CFLAGS=\
+       $(STRICT_OPTIONS)  -DIN_LINPHONE \
        $(ORTP_CFLAGS) \
        $(MEDIASTREAMER_CFLAGS) \
        $(OSIP_CFLAGS) \
@@ -97,3 +107,21 @@ AM_CFLAGS+= -DBUILD_WIZARD
 endif
 
 AM_CXXFLAGS=$(AM_CFLAGS)
+
+make_gitversion_h:
+       if test "$(GITDESCRIBE)" != "" ; then \
+               $(ECHO) -n "#define LIBLINPHONE_GIT_VERSION \"$(GITDESCRIBE)\"" > $(GITVERSION_FILE_TMP) ; \
+       elif test "$(GITREVISION)" != "" ; then \
+               $(ECHO) -n "#define LIBLINPHONE_GIT_VERSION \"$(LINPHONE_VERSION)_$(GITREVISION)\"" > $(GITVERSION_FILE_TMP) ; \
+       else \
+               $(ECHO) -n "" > $(GITVERSION_FILE_TMP) ; \
+       fi
+       if test ! -f $(srcdir)/$(GITVERSION_FILE) ; then \
+               cp -f $(GITVERSION_FILE_TMP) $(srcdir)/$(GITVERSION_FILE) ; \
+       fi
+       if test "`cat $(GITVERSION_FILE_TMP)`" != "`cat $(srcdir)/$(GITVERSION_FILE)`" ; then \
+               cp -f $(GITVERSION_FILE_TMP) $(srcdir)/$(GITVERSION_FILE) ; \
+       fi
+       rm -f $(GITVERSION_FILE_TMP) ;
+
+$(GITVERSION_FILE): make_gitversion_h
index e7f6a7b219846c85b47eb1a76d90b2a39ca3cbf4..134c336abe3cc946715746477b40c9b35bbb7e93 100644 (file)
@@ -27,9 +27,63 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 static void register_failure(SalOp *op, SalError error, SalReason reason, const char *details);
 
-static bool_t media_parameters_changed(LinphoneCall *call, SalMediaDescription *oldmd, SalMediaDescription *newmd){
-       if (call->params.in_conference!=call->current_params.in_conference) return TRUE;
-       return !sal_media_description_equals(oldmd,newmd)  || call->up_bw!=linphone_core_get_upload_bandwidth(call->core);
+static int media_parameters_changed(LinphoneCall *call, SalMediaDescription *oldmd, SalMediaDescription *newmd) {
+       if (call->params.in_conference != call->current_params.in_conference) return SAL_MEDIA_DESCRIPTION_CHANGED;
+       if (call->up_bw != linphone_core_get_upload_bandwidth(call->core)) return SAL_MEDIA_DESCRIPTION_CHANGED;
+       return sal_media_description_equals(oldmd, newmd);
+}
+
+void linphone_core_update_streams_destinations(LinphoneCore *lc, LinphoneCall *call, SalMediaDescription *old_md, SalMediaDescription *new_md) {
+       SalStreamDescription *old_audiodesc = NULL;
+       SalStreamDescription *old_videodesc = NULL;
+       SalStreamDescription *new_audiodesc = NULL;
+       SalStreamDescription *new_videodesc = NULL;
+       char *rtp_addr, *rtcp_addr;
+       int i;
+
+       for (i = 0; i < old_md->nstreams; i++) {
+               if (old_md->streams[i].type == SalAudio) {
+                       old_audiodesc = &old_md->streams[i];
+               } else if (old_md->streams[i].type == SalVideo) {
+                       old_videodesc = &old_md->streams[i];
+               }
+       }
+       for (i = 0; i < new_md->nstreams; i++) {
+               if (new_md->streams[i].type == SalAudio) {
+                       new_audiodesc = &new_md->streams[i];
+               } else if (new_md->streams[i].type == SalVideo) {
+                       new_videodesc = &new_md->streams[i];
+               }
+       }
+       if (call->audiostream && new_audiodesc) {
+               rtp_addr = (new_audiodesc->rtp_addr[0] != '\0') ? new_audiodesc->rtp_addr : new_md->addr;
+               rtcp_addr = (new_audiodesc->rtcp_addr[0] != '\0') ? new_audiodesc->rtcp_addr : new_md->addr;
+               ms_message("Change audio stream destination: RTP=%s:%d RTCP=%s:%d", rtp_addr, new_audiodesc->rtp_port, rtcp_addr, new_audiodesc->rtcp_port);
+               rtp_session_set_remote_addr_full(call->audiostream->session, rtp_addr, new_audiodesc->rtp_port, rtcp_addr, new_audiodesc->rtcp_port);
+       }
+#ifdef VIDEO_ENABLED
+       if (call->videostream && new_videodesc) {
+               rtp_addr = (new_videodesc->rtp_addr[0] != '\0') ? new_videodesc->rtp_addr : new_md->addr;
+               rtcp_addr = (new_videodesc->rtcp_addr[0] != '\0') ? new_videodesc->rtcp_addr : new_md->addr;
+               ms_message("Change video stream destination: RTP=%s:%d RTCP=%s:%d", rtp_addr, new_videodesc->rtp_port, rtcp_addr, new_videodesc->rtcp_port);
+               rtp_session_set_remote_addr_full(call->videostream->session, rtp_addr, new_videodesc->rtp_port, rtcp_addr, new_videodesc->rtcp_port);
+       }
+#endif
+
+       /* Copy address and port values from new_md to old_md since we will keep old_md as resultdesc */
+       strcpy(old_md->addr, new_md->addr);
+       if (old_audiodesc && new_audiodesc) {
+               strcpy(old_audiodesc->rtp_addr, new_audiodesc->rtp_addr);
+               strcpy(old_audiodesc->rtcp_addr, new_audiodesc->rtcp_addr);
+               old_audiodesc->rtp_port = new_audiodesc->rtp_port;
+               old_audiodesc->rtcp_port = new_audiodesc->rtcp_port;
+       }
+       if (old_videodesc && new_videodesc) {
+               strcpy(old_videodesc->rtp_addr, new_videodesc->rtp_addr);
+               strcpy(old_videodesc->rtcp_addr, new_videodesc->rtcp_addr);
+               old_videodesc->rtp_port = new_videodesc->rtp_port;
+               old_videodesc->rtcp_port = new_videodesc->rtcp_port;
+       }
 }
 
 void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMediaDescription *new_md){
@@ -49,7 +103,8 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia
        if ((call->audiostream && call->audiostream->ticker) || (call->videostream && call->videostream->ticker)){
                /* we already started media: check if we really need to restart it*/
                if (oldmd){
-                       if (!media_parameters_changed(call,oldmd,new_md) && !call->playing_ringbacktone){
+                       int md_changed = media_parameters_changed(call, oldmd, new_md);
+                       if ((md_changed == SAL_MEDIA_DESCRIPTION_UNCHANGED) && !call->playing_ringbacktone) {
                                /*as nothing has changed, keep the oldmd */
                                call->resultdesc=oldmd;
                                sal_media_description_unref(new_md);
@@ -66,6 +121,12 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia
                                }
                                ms_message("No need to restart streams, SDP is unchanged.");
                                return;
+                       } else if ((md_changed == SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED) && !call->playing_ringbacktone) {
+                               call->resultdesc = oldmd;
+                               ms_message("Network parameters have changed, update them.");
+                               linphone_core_update_streams_destinations(lc, call, oldmd, new_md);
+                               sal_media_description_unref(new_md);
+                               return;
                        }else{
                                ms_message("Media descriptions are different, need to restart the streams.");
                        }
@@ -718,14 +779,35 @@ static void refer_received(Sal *sal, SalOp *op, const char *referto){
        }
 }
 
-static void text_received(Sal *sal, const char *from, const char *msg){
-       LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal);
-       linphone_core_message_received(lc,from,msg,NULL);
+static bool_t is_duplicate_msg(LinphoneCore *lc, const char *msg_id){
+       MSList *elem=lc->last_recv_msg_ids;
+       MSList *tail=NULL;
+       int i;
+       bool_t is_duplicate=FALSE;
+       for(i=0;elem!=NULL;elem=elem->next,i++){
+               if (strcmp((const char*)elem->data,msg_id)==0){
+                       is_duplicate=TRUE;
+               }
+               tail=elem;
+       }
+       if (!is_duplicate){
+               lc->last_recv_msg_ids=ms_list_prepend(lc->last_recv_msg_ids,ms_strdup(msg_id));
+       }
+       if (i>=10){
+               ms_free(tail->data);
+               lc->last_recv_msg_ids=ms_list_remove_link(lc->last_recv_msg_ids,tail);
+       }
+       return is_duplicate;
 }
-void message_external_body_received(Sal *sal, const char *from, const char *url) {
+
+
+static void text_received(Sal *sal, const SalMessage *msg){
        LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal);
-       linphone_core_message_received(lc,from,NULL,url);
+       if (is_duplicate_msg(lc,msg->message_id)==FALSE){
+               linphone_core_message_received(lc,msg->from,msg->text,msg->url);
+       }
 }
+
 static void notify(SalOp *op, const char *from, const char *msg){
        LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
        LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer (op);
@@ -841,7 +923,6 @@ SalCallbacks linphone_sal_callbacks={
        dtmf_received,
        refer_received,
        text_received,
-       message_external_body_received,
        text_delivery_update,
        notify,
        notify_presence,
index 5ca465254d1acb71b96d813b6843889cc38c9788..9f1538f4225b2db301f1a6702cc787cd0e1dc549 100644 (file)
 
 #include "mediastreamer2/msvolume.h"
 
+/**
+ * @addtogroup conferencing
+ * @{
+**/
+
+
 static int convert_conference_to_call(LinphoneCore *lc);
 
 static void conference_check_init(LinphoneConference *ctx, int samplerate){
@@ -131,6 +137,11 @@ static void add_local_endpoint(LinphoneConference *conf,LinphoneCore *lc){
        
 }
 
+/**
+ * Returns the sound volume (mic input) of the local participant of the conference.
+ * @param lc the linphone core
+ * @returns the measured input volume expressed in dbm0.
+ **/
 float linphone_core_get_conference_local_input_volume(LinphoneCore *lc){
        LinphoneConference *conf=&lc->conf_ctx;
        AudioStream *st=conf->local_participant;
@@ -143,6 +154,16 @@ float linphone_core_get_conference_local_input_volume(LinphoneCore *lc){
        return LINPHONE_VOLUME_DB_LOWEST;
 }
 
+/**
+ * Merge a call into a conference.
+ * @param lc the linphone core
+ * @param call an established call, either in LinphoneCallStreamsRunning or LinphoneCallPaused state.
+ * 
+ * If this is the first call that enters the conference, the virtual conference will be created automatically.
+ * If the local user was actively part of the call (ie not in paused state), then the local user is automatically entered into the conference.
+ * 
+ * @returns 0 if successful, -1 otherwise.
+**/
 int linphone_core_add_to_conference(LinphoneCore *lc, LinphoneCall *call){
        LinphoneCallParams params;
        LinphoneConference *conf=&lc->conf_ctx;
@@ -229,7 +250,18 @@ static int convert_conference_to_call(LinphoneCore *lc){
        return err;
 }
 
-
+/**
+ * Remove a call from the conference.
+ * @param lc the linphone core
+ * @param call a call that has been previously merged into the conference.
+ * 
+ * After removing the remote participant belonging to the supplied call, the call becomes a normal call in paused state.
+ * If one single remote participant is left alone in the conference after the removal, then it is
+ * automatically removed from the conference and put into a simple call, like before entering the conference.
+ * The conference's resources are then automatically destroyed.
+ * 
+ * @returns 0 if successful, -1 otherwise.
+ **/
 int linphone_core_remove_from_conference(LinphoneCore *lc, LinphoneCall *call){
        char * str=linphone_call_get_remote_address_as_string(call);
        ms_message("Removing call %s from the conference", str);
@@ -249,10 +281,21 @@ int linphone_core_remove_from_conference(LinphoneCore *lc, LinphoneCall *call){
        return err;
 }
 
+/**
+ * Indicates whether the local participant is part of the conference.
+ * @param lc the linphone core
+ * @returns TRUE if the local participant is in the conference, FALSE otherwise.
+**/
 bool_t linphone_core_is_in_conference(const LinphoneCore *lc){
        return lc->conf_ctx.local_participant!=NULL;
 }
 
+/**
+ * Moves the local participant out of the conference.
+ * @param lc the linphone core
+ * When the local participant is out of the conference, the remote participants can continue to talk normally.
+ * @returns 0 if successful, -1 otherwise.
+**/
 int linphone_core_leave_conference(LinphoneCore *lc){
        LinphoneConference *conf=&lc->conf_ctx;
        if (linphone_core_is_in_conference(lc))
@@ -260,7 +303,17 @@ int linphone_core_leave_conference(LinphoneCore *lc){
        return 0;
 }
 
-
+/**
+ * Moves the local participant inside the conference.
+ * @param lc the linphone core
+ * 
+ * Makes the local participant to join the conference. 
+ * Typically, the local participant is by default always part of the conference when joining an active call into a conference.
+ * However, by calling linphone_core_leave_conference() and linphone_core_enter_conference() the application can decide to temporarily
+ * move out and in the local participant from the conference.
+ * 
+ * @returns 0 if successful, -1 otherwise
+**/
 int linphone_core_enter_conference(LinphoneCore *lc){
        if (linphone_core_sound_resources_locked(lc)) {
                return -1;
@@ -273,6 +326,14 @@ int linphone_core_enter_conference(LinphoneCore *lc){
        return 0;
 }
 
+/**
+ * Add all calls into a conference.
+ * @param lc the linphone core
+ * 
+ * Merge all established calls (either in LinphoneCallStreamsRunning or LinphoneCallPaused) into a conference.
+ * 
+ * @returns 0 if successful, -1 otherwise
+**/
 int linphone_core_add_all_to_conference(LinphoneCore *lc) {
        MSList *calls=lc->calls;
        while (calls) {
@@ -286,6 +347,14 @@ int linphone_core_add_all_to_conference(LinphoneCore *lc) {
        return 0;
 }
 
+/**
+ * Terminates the conference and the calls associated with it.
+ * @param lc the linphone core
+ * 
+ * All the calls that were merged to the conference are terminated, and the conference resources are destroyed.
+ * 
+ * @returns 0 if successful, -1 otherwise
+**/
 int linphone_core_terminate_conference(LinphoneCore *lc) {
        MSList *calls=lc->calls;
        while (calls) {
@@ -298,9 +367,23 @@ int linphone_core_terminate_conference(LinphoneCore *lc) {
        return 0;
 }
 
+/**
+ * Returns the number of participants to the conference, including the local participant.
+ * @param lc the linphone core
+ * 
+ * Typically, after merging two calls into the conference, there is total of 3 participants:
+ * the local participant (or local user), and two remote participants that were the destinations of the two previously establised calls.
+ * 
+ * @returns the number of participants to the conference
+**/
 int linphone_core_get_conference_size(LinphoneCore *lc) {
        if (lc->conf_ctx.conf == NULL) {
                return 0;
        }
        return ms_audio_conference_get_size(lc->conf_ctx.conf);
 }
+
+/**
+ * @}
+**/
+
index a68ab2f19c7cfe0b28d899ad56b42a31ff7bb3bc..902d23c9c0ec166df5354a7655e2cce029646bc9 100644 (file)
@@ -1,21 +1,20 @@
 
-EXTRA_DIST = Doxyfile.in doxygen.dox
+EXTRA_DIST=Doxyfile.in doxygen.dox
 
-SOURCES= doxygen.dox $(top_srcdir)/coreapi/help/*.c $(top_srcdir)/coreapi/*.c $(top_srcdir)/coreapi/*.h  
+SOURCES=doxygen.dox $(top_srcdir)/coreapi/help/*.c $(top_srcdir)/coreapi/*.c $(top_srcdir)/coreapi/*.h  
 
 
-#html doc
+# html doc
 if HAVE_DOXYGEN
 
-# doxdir & pkgdocdir are not always defined by automake
-docdir=$(datadir)/doc
+# docdir & pkgdocdir are not always defined by automake
 pkgdocdir=$(docdir)/$(PACKAGE)-$(VERSION)
 doc_htmldir=$(pkgdocdir)/html
 
 doc_html_DATA = $(top_builddir)/coreapi/help/doc/html/html.tar
 
 $(doc_html_DATA): $(top_builddir)/coreapi/help/doc/html/index.html
-       cd $(<D) && tar cf html.tar *
+       cd $(top_builddir)/coreapi/help/doc/html/ && tar cf html.tar *
 
 $(top_builddir)/coreapi/help/doc/html/index.html: $(SOURCES) Doxyfile Makefile.am
        rm -rf doc
@@ -60,21 +59,20 @@ LINPHONE_TUTOS+=$(chatroom_SOURCES)
 chatroom_LDADD=$(helloworld_LDADD)
 endif
                                                                                                
-endif                  
-
-INCLUDES=-I$(top_srcdir)/coreapi \
-               $(MEDIASTREAMER_CFLAGS)
+endif
 
-AM_CFLAGS=$(STRICT_OPTIONS)  -DIN_LINPHONE \
+AM_CFLAGS=\
+       $(STRICT_OPTIONS) \
+       -DIN_LINPHONE \
        $(ORTP_CFLAGS) \
        $(OSIP_CFLAGS) \
        $(MEDIASTREAMER_CFLAGS) \
        $(EXOSIP_CFLAGS) \
        -DENABLE_TRACE  \
        -DLOG_DOMAIN=\"LinphoneCore\" \
-        $(IPV6_CFLAGS) \
-        -DORTP_INET6 \
-        $(VIDEO_CFLAGS) 
+       $(IPV6_CFLAGS) \
+       -DORTP_INET6 \
+       $(VIDEO_CFLAGS)
 
 
 tutodir=$(datadir)/tutorials/linphone
index 87229f276855ccd333bcd6027aac1b08e62682e2..8b2e6b7b997e07f79ce4dbca0be7ff525cb947b0 100644 (file)
@@ -195,6 +195,27 @@ void text_received(LinphoneCore *lc, LinphoneChatRoom *room, const LinphoneAddre
  * This api is useful for manipulating SIP addresses ('from' or 'to' headers).
 **/
 
+/**
+ * @defgroup conferencing Making an audio conference.
+ * This API allows to create a conference entirely managed by the client. No server capabilities are required.
+ * The way such conference is created is by doing the following:<br>
+ * The application shall makes "normal" calls to several destinations (using linphone_core_invite() ), one after another. 
+ * While initiating the second call, the first one is automatically paused.
+ * Then, once the second call is established, the application has the possibility to merge the two calls to form a conference where each participant
+ * (the local participant, the remote destination of the first call, the remote destination of the second call) can talk together.
+ * This must be done by adding the two calls to the conference using \link linphone_call_add_to_conference() \endlink
+ *
+ * Once merged into a conference the LinphoneCall objects representing the calls that were established remain unchanged, except that 
+ * they are tagged as part of the conference (see \link linphone_call_is_in_conference() \endlink ). The calls in a conference are in the LinphoneCallStreamsRunning state.
+ * 
+ * Only a single conference can be created: the purpose of this feature is to allow the local user to create, take part and manage the conference. 
+ * This API is not designed to create a conference server application.
+ *
+ * Up to 10 calls can be merged into the conference, however depending on the CPU usage required for doing the encoding/decoding of the streams of each participants,
+ * the effective limit can be lower.
+ * 
+**/
+
 /**
  * @defgroup misc Miscenalleous: logs, version strings, config storage
 **/
index 32dc9d59c37a398208c554c8a7300a5046f7074e..5a18a052547ef6649a8b23e415a94c7bb0995fed 100644 (file)
@@ -27,7 +27,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #include "private.h"
 #include <ortp/event.h>
 #include <ortp/b64.h>
-
+#include <math.h>
 
 #include "mediastreamer2/mediastream.h"
 #include "mediastreamer2/msvolume.h"
@@ -208,22 +208,21 @@ static void update_media_description_from_stun(SalMediaDescription *md, const St
        
 }
 
-
-static SalMediaDescription *_create_local_media_description(LinphoneCore *lc, LinphoneCall *call, unsigned int session_id, unsigned int session_ver){
+void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *call){
        MSList *l;
        PayloadType *pt;
+       SalMediaDescription *old_md=call->localdesc;
        int i;
        const char *me=linphone_core_get_identity(lc);
        LinphoneAddress *addr=linphone_address_new(me);
        const char *username=linphone_address_get_username (addr);
        SalMediaDescription *md=sal_media_description_new();
+       bool_t keep_srtp_keys=lp_config_get_int(lc->config,"sip","keep_srtp_keys",0);
        
-       if (call->ping_time>0) {
-               linphone_core_adapt_to_network(lc,call->ping_time,&call->params);
-       }
+       linphone_core_adapt_to_network(lc,call->ping_time,&call->params);
 
-       md->session_id=session_id;
-       md->session_ver=session_ver;
+       md->session_id=(old_md ? old_md->session_id : (rand() & 0xfff));
+       md->session_ver=(old_md ? (old_md->session_ver+1) : (rand() & 0xfff));
        md->nstreams=1;
        strncpy(md->addr,call->localip,sizeof(md->addr));
        strncpy(md->username,username,sizeof(md->username));
@@ -248,8 +247,6 @@ static SalMediaDescription *_create_local_media_description(LinphoneCore *lc, Li
        pt=payload_type_clone(rtp_profile_get_payload_from_mime(&av_profile,"telephone-event"));
        l=ms_list_append(l,pt);
        md->streams[0].payloads=l;
-       
-
 
        if (call->params.has_video){
                md->nstreams++;
@@ -263,15 +260,22 @@ static SalMediaDescription *_create_local_media_description(LinphoneCore *lc, Li
        
        for(i=0; i<md->nstreams; i++) {
                if (md->streams[i].proto == SalProtoRtpSavp) {
-                       md->streams[i].crypto[0].tag = 1;
-                       md->streams[i].crypto[0].algo = AES_128_SHA1_80;
-                       if (!generate_b64_crypto_key(30, md->streams[i].crypto[0].master_key))
-                               md->streams[i].crypto[0].algo = 0;
-                       md->streams[i].crypto[1].tag = 2;
-                       md->streams[i].crypto[1].algo = AES_128_SHA1_32;
-                       if (!generate_b64_crypto_key(30, md->streams[i].crypto[1].master_key))
-                               md->streams[i].crypto[1].algo = 0;
-                       md->streams[i].crypto[2].algo = 0;
+                       if (keep_srtp_keys && old_md && old_md->streams[i].proto==SalProtoRtpSavp){
+                               int j;
+                               for(j=0;j<SAL_CRYPTO_ALGO_MAX;++j){
+                                       memcpy(&md->streams[i].crypto[j],&old_md->streams[i].crypto[j],sizeof(SalSrtpCryptoAlgo));
+                               }
+                       }else{
+                               md->streams[i].crypto[0].tag = 1;
+                               md->streams[i].crypto[0].algo = AES_128_SHA1_80;
+                               if (!generate_b64_crypto_key(30, md->streams[i].crypto[0].master_key))
+                                       md->streams[i].crypto[0].algo = 0;
+                               md->streams[i].crypto[1].tag = 2;
+                               md->streams[i].crypto[1].algo = AES_128_SHA1_32;
+                               if (!generate_b64_crypto_key(30, md->streams[i].crypto[1].master_key))
+                                       md->streams[i].crypto[1].algo = 0;
+                               md->streams[i].crypto[2].algo = 0;
+                       }
                }
        }
        update_media_description_from_stun(md,&call->ac,&call->vc);
@@ -280,22 +284,8 @@ static SalMediaDescription *_create_local_media_description(LinphoneCore *lc, Li
                linphone_core_update_ice_state_in_call_stats(call);
        }
        linphone_address_destroy(addr);
-       return md;
-}
-
-void update_local_media_description(LinphoneCore *lc, LinphoneCall *call){
-       SalMediaDescription *md=call->localdesc;
-       if (md== NULL) {
-               call->localdesc = create_local_media_description(lc,call);
-       } else {
-               call->localdesc = _create_local_media_description(lc,call,md->session_id,md->session_ver+1);
-               sal_media_description_unref(md);
-       }
-}
-
-SalMediaDescription *create_local_media_description(LinphoneCore *lc, LinphoneCall *call){
-       unsigned int id=rand() & 0xfff;
-       return _create_local_media_description(lc,call,id,id);
+       call->localdesc=md;
+       if (old_md) sal_media_description_unref(old_md);
 }
 
 static int find_port_offset(LinphoneCore *lc, SalStreamType type){
@@ -472,6 +462,7 @@ LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddr
 LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, SalOp *op){
        LinphoneCall *call=ms_new0(LinphoneCall,1);
        char *from_str;
+       const SalMediaDescription *md;
 
        call->dir=LinphoneCallIncoming;
        sal_op_set_user_pointer(op,call);
@@ -494,8 +485,13 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro
        linphone_call_init_common(call, from, to);
        call->log->call_id=ms_strdup(sal_op_get_call_id(op)); /*must be known at that time*/
        linphone_core_init_default_params(lc, &call->params);
+       md=sal_call_get_remote_media_description(op);
        call->params.has_video &= !!lc->video_policy.automatically_accept;
-       call->params.has_video &= linphone_core_media_description_contains_video_stream(sal_call_get_remote_media_description(op));
+       if (md) {
+               // It is licit to receive an INVITE without SDP
+               // In this case WE chose the media parameters according to policy.
+               call->params.has_video &= linphone_core_media_description_contains_video_stream(md);
+       }
        switch (linphone_core_get_firewall_policy(call->core)) {
                case LinphonePolicyUseIce:
                        call->ice_session = ice_session_new();
@@ -754,6 +750,11 @@ const LinphoneCallParams * linphone_call_get_remote_params(LinphoneCall *call){
                        }else if (vsd){
                                cp->has_video=is_video_active(vsd);
                        }
+                       if (!cp->has_video){
+                               if (md->bandwidth>0 && md->bandwidth<=linphone_core_get_edge_bw(call->core)){
+                                       cp->low_bandwidth=TRUE;
+                               }
+                       }
                        return cp;
                }
        }
@@ -933,9 +934,31 @@ const PayloadType* linphone_call_params_get_used_video_codec(const LinphoneCallP
        return cp->video_codec;
 }
 
+/**
+ * @ingroup call_control
+ * Use to know if this call has been configured in low bandwidth mode.
+ * This mode can be automatically discovered thanks to a stun server when activate_edge_workarounds=1 in section [net] of configuration file.
+ * An application that would have reliable way to know network capacity may not use activate_edge_workarounds=1 but instead manually configure
+ * low bandwidth mode with linphone_call_params_enable_low_bandwidth().
+ * <br> When enabled, this param may transform a call request with video in audio only mode.
+ * @return TRUE if low bandwidth has been configured/detected
+ */
 bool_t linphone_call_params_low_bandwidth_enabled(const LinphoneCallParams *cp) {
        return cp->low_bandwidth;
 }
+
+/**
+ * @ingroup call_control
+ * Indicate low bandwith mode. 
+ * Configuring a call to low bandwidth mode will result in the core to activate several settings for the call in order to ensure that bitrate usage
+ * is lowered to the minimum possible. Typically, ptime (packetization time) will be increased, audio codec's output bitrate will be targetted to 20kbit/s provided
+ * that it is achievable by the codec selected after SDP handshake. Video is automatically disabled.
+ * 
+**/
+void linphone_call_params_enable_low_bandwidth(LinphoneCallParams *cp, bool_t enabled){
+       cp->low_bandwidth=enabled;
+}
+
 /**
  * Returns whether video is enabled.
 **/
@@ -1026,11 +1049,11 @@ static void video_stream_event_cb(void *user_pointer, const MSFilter *f, const u
                        ms_warning("Case is MS_VIDEO_DECODER_DECODING_ERRORS");
                        linphone_call_send_vfu_request(call);
                        break;
-        case MS_VIDEO_DECODER_FIRST_IMAGE_DECODED:
-            ms_message("First video frame decoded successfully");
-            if (call->nextVideoFrameDecoded._func != NULL)
-                call->nextVideoFrameDecoded._func(call, call->nextVideoFrameDecoded._user_data);
-            break;
+               case MS_VIDEO_DECODER_FIRST_IMAGE_DECODED:
+                       ms_message("First video frame decoded successfully");
+                       if (call->nextVideoFrameDecoded._func != NULL)
+                       call->nextVideoFrameDecoded._func(call, call->nextVideoFrameDecoded._user_data);
+                       break;
                default:
                        ms_warning("Unhandled event %i", event_id);
                        break;
@@ -1039,10 +1062,10 @@ static void video_stream_event_cb(void *user_pointer, const MSFilter *f, const u
 #endif
 
 void linphone_call_set_next_video_frame_decoded_callback(LinphoneCall *call, LinphoneCallCbFunc cb, void* user_data) {
-    call->nextVideoFrameDecoded._func = cb;
-    call->nextVideoFrameDecoded._user_data = user_data;
+       call->nextVideoFrameDecoded._func = cb;
+       call->nextVideoFrameDecoded._user_data = user_data;
 #ifdef VIDEO_ENABLED
-    ms_filter_call_method_noarg(call->videostream->decoder, MS_VIDEO_DECODER_RESET_FIRST_IMAGE_NOTIFICATION);
+       ms_filter_call_method_noarg(call->videostream->decoder, MS_VIDEO_DECODER_RESET_FIRST_IMAGE_NOTIFICATION);
 #endif
 }
 
@@ -1189,7 +1212,7 @@ static void parametrize_equalizer(LinphoneCore *lc, AudioStream *st){
 }
 
 void _post_configure_audio_stream(AudioStream *st, LinphoneCore *lc, bool_t muted){
-       float mic_gain=lp_config_get_float(lc->config,"sound","mic_gain",1);
+       float mic_gain=lc->sound_conf.soft_mic_lev;
        float thres = 0;
        float recv_gain;
        float ng_thres=lp_config_get_float(lc->config,"sound","ng_thres",0.05);
@@ -1197,7 +1220,7 @@ void _post_configure_audio_stream(AudioStream *st, LinphoneCore *lc, bool_t mute
        int dc_removal=lp_config_get_int(lc->config,"sound","dc_removal",0);
 
        if (!muted)
-               audio_stream_set_mic_gain(st,mic_gain);
+               linphone_core_set_mic_gain_db (lc, mic_gain);
        else
                audio_stream_set_mic_gain(st,0);
 
@@ -1231,7 +1254,7 @@ void _post_configure_audio_stream(AudioStream *st, LinphoneCore *lc, bool_t mute
        }
        if (st->volrecv){
                /* parameters for a limited noise-gate effect, using echo limiter threshold */
-               float floorgain = 1/mic_gain;
+               float floorgain = 1/pow(10,(mic_gain)/10);
                int spk_agc=lp_config_get_int(lc->config,"sound","speaker_agc_enabled",0);
                ms_filter_call_method(st->volrecv, MS_VOLUME_ENABLE_AGC, &spk_agc);
                ms_filter_call_method(st->volrecv,MS_VOLUME_SET_NOISE_GATE_THRESHOLD,&ng_thres);
@@ -2089,6 +2112,10 @@ void linphone_call_set_transfer_state(LinphoneCall* call, LinphoneCallState stat
        }
 }
 
+/**
+ * Returns true if the call is part of the conference.
+ * @ingroup conferencing
+**/
 bool_t linphone_call_is_in_conference(const LinphoneCall *call) {
        return call->params.in_conference;
 }
@@ -2096,6 +2123,7 @@ bool_t linphone_call_is_in_conference(const LinphoneCall *call) {
 
 /**
  * Perform a zoom of the video displayed during a call.
+ * @param call the call.
  * @param zoom_factor a floating point number describing the zoom factor. A value 1.0 corresponds to no zoom applied.
  * @param cx a floating point number pointing the horizontal center of the zoom to be applied. This value should be between 0.0 and 1.0.
  * @param cy a floating point number pointing the vertical center of the zoom to be applied. This value should be between 0.0 and 1.0.
@@ -2104,7 +2132,7 @@ bool_t linphone_call_is_in_conference(const LinphoneCall *call) {
 **/
 void linphone_call_zoom_video(LinphoneCall* call, float zoom_factor, float* cx, float* cy) {
        VideoStream* vstream = call->videostream;
-       if (vstream) {
+       if (vstream && vstream->output) {
                float zoom[3];
                
                if (zoom_factor < 1)
index d96a1905b50dfb23cdf7a874b2b03d960f1fb516..e52fff00ebf228c9157a75e1241dfe0b81921151 100644 (file)
@@ -24,6 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #include "lpconfig.h"
 #include "private.h"
 
+#include <math.h>
 #include <ortp/telephonyevents.h>
 #include <ortp/zrtp.h>
 #include "mediastreamer2/mediastream.h"
@@ -40,13 +41,25 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
+#include "liblinphone_gitversion.h"
+#else
+#ifndef LIBLINPHONE_GIT_VERSION
+#define LIBLINPHONE_GIT_VERSION "unknown"
+#endif
 #endif
 
+
 /*#define UNSTANDART_GSM_11K 1*/
 
 #define ROOT_CA_FILE PACKAGE_DATA_DIR "/linphone/rootca.pem"
 
-static const char *liblinphone_version=LIBLINPHONE_VERSION;
+static const char *liblinphone_version=
+#ifdef LIBLINPHONE_GIT_VERSION
+       LIBLINPHONE_GIT_VERSION
+#else
+       LIBLINPHONE_VERSION
+#endif
+;
 static void set_network_reachable(LinphoneCore* lc,bool_t isReachable, time_t curtime);
 static void linphone_core_run_hooks(LinphoneCore *lc);
 static void linphone_core_free_hooks(LinphoneCore *lc);
@@ -413,7 +426,6 @@ static void sound_config_read(LinphoneCore *lc)
        int tmp;
        const char *tmpbuf;
        const char *devid;
-       float gain=0;
 #ifdef __linux
        /*alsadev let the user use custom alsa device within linphone*/
        devid=lp_config_get_string(lc->config,"sound","alsadev",NULL);
@@ -485,8 +497,8 @@ static void sound_config_read(LinphoneCore *lc)
        linphone_core_enable_agc(lc,
                lp_config_get_int(lc->config,"sound","agc",0));
 
-       gain=lp_config_get_float(lc->config,"sound","playback_gain_db",0);
-       linphone_core_set_playback_gain_db (lc,gain);
+       linphone_core_set_playback_gain_db (lc,lp_config_get_float(lc->config,"sound","playback_gain_db",0));
+       linphone_core_set_mic_gain_db (lc,lp_config_get_float(lc->config,"sound","mic_gain_db",0));
 
        linphone_core_set_remote_ringback_tone (lc,lp_config_get_string(lc->config,"sound","ringback_tone",NULL));
 
@@ -515,7 +527,7 @@ static void sip_config_read(LinphoneCore *lc)
        sal_reuse_authorization(lc->sal, lp_config_get_int(lc->config,"sip","reuse_authorization",0));
        sal_expire_old_registration_contacts(lc->sal,lp_config_get_int(lc->config,"sip","expire_old_registration_contacts",0));
 
-       tmp=lp_config_get_int(lc->config,"sip","use_rfc2833",0);
+       tmp=lp_config_get_int(lc->config,"sip","use_rfc2833",1);
        linphone_core_set_use_rfc2833_for_dtmf(lc,tmp);
 
        ipv6=lp_config_get_int(lc->config,"sip","use_ipv6",-1);
@@ -554,6 +566,8 @@ static void sip_config_read(LinphoneCore *lc)
        sal_set_root_ca(lc->sal, lp_config_get_string(lc->config,"sip","root_ca", ROOT_CA_FILE));
 #endif
        linphone_core_verify_server_certificates(lc,lp_config_get_int(lc->config,"sip","verify_server_certs",TRUE));
+       /*setting the dscp must be done before starting the transports, otherwise it is not taken into effect*/
+       sal_set_dscp(lc->sal,linphone_core_get_sip_dscp(lc));
        /*start listening on ports*/
        linphone_core_set_sip_transports(lc,&tr);
 
@@ -583,6 +597,9 @@ static void sip_config_read(LinphoneCore *lc)
        tmp=lp_config_get_int(lc->config,"sip","inc_timeout",30);
        linphone_core_set_inc_timeout(lc,tmp);
 
+       tmp=lp_config_get_int(lc->config,"sip","in_call_timeout",0);
+       linphone_core_set_in_call_timeout(lc,tmp);
+
        /* get proxies config */
        for(i=0;; i++){
                LinphoneProxyConfig *cfg=linphone_proxy_config_new_from_config_file(lc->config,i);
@@ -619,7 +636,6 @@ static void sip_config_read(LinphoneCore *lc)
        sal_set_keepalive_period(lc->sal,lc->sip_conf.keepalive_period);
        sal_use_one_matching_codec_policy(lc->sal,lp_config_get_int(lc->config,"sip","only_one_codec",0));
        sal_use_double_registrations(lc->sal,lp_config_get_int(lc->config,"sip","use_double_registrations",1));
-       sal_set_dscp(lc->sal,linphone_core_get_sip_dscp(lc));
        sal_use_dates(lc->sal,lp_config_get_int(lc->config,"sip","put_date",0));
 }
 
@@ -1099,6 +1115,7 @@ static void misc_config_read (LinphoneCore *lc) {
 static void linphone_core_init (LinphoneCore * lc, const LinphoneCoreVTable *vtable, const char *config_path,
     const char *factory_config_path, void * userdata)
 {
+       ms_message("Initializing LinphoneCore %s", linphone_core_get_version());
        memset (lc, 0, sizeof (LinphoneCore));
        lc->data=userdata;
        lc->ringstream_autorelease=TRUE;
@@ -1183,6 +1200,9 @@ static void linphone_core_init (LinphoneCore * lc, const LinphoneCoreVTable *vta
        sal_set_user_pointer(lc->sal,lc);
        sal_set_callbacks(lc->sal,&linphone_sal_callbacks);
 
+        lc->network_last_check = 0;
+        lc->network_last_status = FALSE;
+
        sip_setup_register_all();
        sound_config_read(lc);
        net_config_read(lc);
@@ -1651,9 +1671,10 @@ static void apply_user_agent(LinphoneCore *lc){
  *
  * @ingroup misc
 **/
-void linphone_core_set_user_agent(const char *name, const char *ver){
+void linphone_core_set_user_agent(LinphoneCore *lc, const char *name, const char *ver){
        strncpy(_ua_name,name,sizeof(_ua_name)-1);
        strncpy(_ua_version,ver,sizeof(_ua_version));
+       apply_user_agent(lc);
 }
 
 const char *linphone_core_get_user_agent_name(void){
@@ -1794,24 +1815,22 @@ void linphone_core_enable_ipv6(LinphoneCore *lc, bool_t val){
 
 
 static void monitor_network_state(LinphoneCore *lc, time_t curtime){
-       static time_t last_check=0;
-       static bool_t last_status=FALSE;
        char result[LINPHONE_IPADDR_SIZE];
-       bool_t new_status=last_status;
+       bool_t new_status=lc->network_last_status;
 
        /* only do the network up checking every five seconds */
-       if (last_check==0 || (curtime-last_check)>=5){
+       if (lc->network_last_check==0 || (curtime-lc->network_last_check)>=5){
                linphone_core_get_local_ip_for(lc->sip_conf.ipv6_enabled ? AF_INET6 : AF_INET,NULL,result);
                if (strcmp(result,"::1")!=0 && strcmp(result,"127.0.0.1")!=0){
                        new_status=TRUE;
                }else new_status=FALSE;
-               last_check=curtime;
-               if (new_status!=last_status) {
+               lc->network_last_check=curtime;
+               if (new_status!=lc->network_last_status) {
                        if (new_status){
                                ms_message("New local ip address is %s",result);
                        }
                        set_network_reachable(lc,new_status, curtime);
-                       last_status=new_status;
+                       lc->network_last_status=new_status;
                }
        }
 }
@@ -1969,6 +1988,7 @@ void linphone_core_iterate(LinphoneCore *lc){
        calls= lc->calls;
        while(calls!= NULL){
                call = (LinphoneCall *)calls->data;
+               elapsed = curtime-call->start_time;
                 /* get immediately a reference to next one in case the one
                 we are going to examine is destroy and removed during
                 linphone_core_start_invite() */
@@ -1985,7 +2005,6 @@ void linphone_core_iterate(LinphoneCore *lc){
                        linphone_core_start_invite(lc,call);
                }
                if (call->state==LinphoneCallIncomingReceived){
-                       elapsed=curtime-call->start_time;
                        ms_message("incoming call ringing for %i seconds",elapsed);
                        if (elapsed>lc->sip_conf.inc_timeout){
                                ms_message("incoming call timeout (%i)",lc->sip_conf.inc_timeout);
@@ -1994,6 +2013,10 @@ void linphone_core_iterate(LinphoneCore *lc){
                                linphone_core_terminate_call(lc,call);
                        }
                }
+               if (lc->sip_conf.in_call_timeout > 0 && elapsed>lc->sip_conf.in_call_timeout) {
+                       ms_message("in call timeout (%i)",lc->sip_conf.in_call_timeout);
+                       linphone_core_terminate_call(lc,call);
+               }
        }
                
        if (linphone_core_video_preview_enabled(lc)){
@@ -2268,7 +2291,7 @@ int linphone_core_start_invite(LinphoneCore *lc, LinphoneCall *call){
        linphone_call_init_media_streams(call);
        if (lc->ringstream==NULL)
                audio_stream_prepare_sound(call->audiostream,lc->sound_conf.play_sndcard,lc->sound_conf.capt_sndcard);
-       call->localdesc=create_local_media_description(lc,call);
+       linphone_call_make_local_media_description(lc,call);
        if (!lc->sip_conf.sdp_200_ack){
                call->media_pending=TRUE;
                sal_call_set_local_media_description(call->op,call->localdesc);
@@ -2530,7 +2553,7 @@ void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call){
        bool_t propose_early_media=lp_config_get_int(lc->config,"sip","incoming_calls_early_media",FALSE);
        const char *ringback_tone=linphone_core_get_remote_ringback_tone (lc);
 
-       call->localdesc=create_local_media_description(lc,call);
+       linphone_call_make_local_media_description(lc,call);
        sal_call_set_local_media_description(call->op,call->localdesc);
        md=sal_call_get_final_media_description(call->op);
        if (md && sal_media_description_empty(md)){
@@ -2636,7 +2659,7 @@ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const Linpho
                        call->videostream->ice_check_list = NULL;
                }
                call->params = *params;
-               update_local_media_description(lc, call);
+               linphone_call_make_local_media_description(lc, call);
                if ((call->ice_session != NULL) && !has_video && call->params.has_video) {
                        /* Defer call update until the ICE candidates gathering process has finished. */
                        ms_message("Defer call update to gather ICE candidates");
@@ -2747,7 +2770,7 @@ int linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, const
        }
        call->params.has_video &= linphone_core_media_description_contains_video_stream(sal_call_get_remote_media_description(call->op));
        call->camera_active=call->params.has_video;
-       update_local_media_description(lc,call);
+       linphone_call_make_local_media_description(lc,call);
        if (call->ice_session != NULL) {
                linphone_core_update_ice_from_remote_media_description(call, sal_call_get_remote_media_description(call->op));
 #ifdef VIDEO_ENABLED
@@ -2860,10 +2883,13 @@ int linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call,
                sal_op_set_contact(call->op,contact);
 
        if (params){
+               const SalMediaDescription *md = sal_call_get_remote_media_description(call->op);
                call->params=*params;
-               call->params.has_video &= linphone_core_media_description_contains_video_stream(sal_call_get_remote_media_description(call->op));
+               // There might not be a md if the INVITE was lacking an SDP
+               // In this case we use the parameters as is.
+               if (md) call->params.has_video &= linphone_core_media_description_contains_video_stream(md);
                call->camera_active=call->params.has_video;
-               update_local_media_description(lc,call);
+               linphone_call_make_local_media_description(lc,call);
                sal_call_set_local_media_description(call->op,call->localdesc);
        }
        
@@ -2917,6 +2943,7 @@ static void terminate_call(LinphoneCore *lc, LinphoneCall *call){
        linphone_call_stop_media_streams(call);
        if (lc->vtable.display_status!=NULL)
                lc->vtable.display_status(lc,_("Call ended") );
+       linphone_call_set_state(call,LinphoneCallEnd,"Call terminated");
 }
 
 int linphone_core_redirect_call(LinphoneCore *lc, LinphoneCall *call, const char *redirect_uri){
@@ -2924,7 +2951,6 @@ int linphone_core_redirect_call(LinphoneCore *lc, LinphoneCall *call, const char
                sal_call_decline(call->op,SalReasonRedirect,redirect_uri);
                call->reason=LinphoneReasonDeclined;
                terminate_call(lc,call);
-               linphone_call_set_state(call,LinphoneCallEnd,"Call terminated");
        }else{
                ms_error("Bad state for call redirection.");
                return -1;
@@ -2958,8 +2984,35 @@ int linphone_core_terminate_call(LinphoneCore *lc, LinphoneCall *the_call)
        }
        sal_call_terminate(call->op);
        terminate_call(lc,call);
+       return 0;
+}
 
-       linphone_call_set_state(call,LinphoneCallEnd,"Call terminated");
+/**
+ * Decline a pending incoming call, with a reason.
+ * @param lc the linphone core
+ * @param call the LinphoneCall, must be in the IncomingReceived state.
+ * @param reason the reason for rejecting the call: LinphoneReasonDeclined or LinphoneReasonBusy
+**/
+int linphone_core_decline_call(LinphoneCore *lc, LinphoneCall * call, LinphoneReason reason){
+       SalReason sal_reason=SalReasonUnknown;
+       if (call->state!=LinphoneCallIncomingReceived && call->state!=LinphoneCallIncomingEarlyMedia){
+               ms_error("linphone_core_decline_call(): Cannot decline a call that is in state %s",linphone_call_state_to_string(call->state));
+               return -1;
+       }
+       switch(reason){
+               case LinphoneReasonDeclined:
+                       sal_reason=SalReasonDeclined;
+               break;
+               case LinphoneReasonBusy:
+                       sal_reason=SalReasonBusy;
+               break;
+               default:
+                       ms_error("linphone_core_decline_call(): unsupported reason %s",linphone_reason_to_string(reason));
+                       return -1;
+               break;
+       }
+       sal_call_decline(call->op,sal_reason,NULL);
+       terminate_call(lc,call);
        return 0;
 }
 
@@ -3026,7 +3079,7 @@ int linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *call)
                ms_warning("Cannot pause this call, it is not active.");
                return -1;
        }
-       update_local_media_description(lc,call);
+       linphone_call_make_local_media_description(lc,call);
        if (call->ice_session != NULL)
                linphone_core_update_local_media_description_from_ice(call->localdesc, call->ice_session);
        if (sal_media_description_has_dir(call->resultdesc,SalStreamSendRecv)){
@@ -3105,7 +3158,7 @@ int linphone_core_resume_call(LinphoneCore *lc, LinphoneCall *the_call)
         prevents the participants to hear it while the 200OK comes back.*/
        if (call->audiostream) audio_stream_play(call->audiostream, NULL);
 
-       update_local_media_description(lc,the_call);
+       linphone_call_make_local_media_description(lc,the_call);
        if (call->ice_session != NULL)
                linphone_core_update_local_media_description_from_ice(call->localdesc, call->ice_session);
        sal_call_set_local_media_description(call->op,call->localdesc);
@@ -3159,6 +3212,9 @@ int linphone_core_send_publish(LinphoneCore *lc,
 **/
 void linphone_core_set_inc_timeout(LinphoneCore *lc, int seconds){
        lc->sip_conf.inc_timeout=seconds;
+       if (linphone_core_ready(lc)){
+               lp_config_set_int(lc->config,"sip","inc_timeout",seconds);
+       }
 }
 
 /**
@@ -3171,6 +3227,26 @@ int linphone_core_get_inc_timeout(LinphoneCore *lc){
        return lc->sip_conf.inc_timeout;
 }
 
+/**
+ * Set the in call timeout in seconds.
+ *
+ * @ingroup call_control
+ * After this timeout period, the call is automatically hangup.
+**/
+void linphone_core_set_in_call_timeout(LinphoneCore *lc, int seconds){
+       lc->sip_conf.in_call_timeout=seconds;
+}
+
+/**
+ * Returns the in call timeout
+ *
+ * @ingroup call_control
+ * See linphone_core_set_in_call_timeout() for details.
+**/
+int linphone_core_get_in_call_timeout(LinphoneCore *lc){
+       return lc->sip_conf.in_call_timeout;
+}
+
 void linphone_core_set_presence_info(LinphoneCore *lc,int minutes_away,
                                                                                                        const char *contact,
                                                                                                        LinphoneOnlineStatus presence_mode)
@@ -3239,6 +3315,40 @@ void linphone_core_set_ring_level(LinphoneCore *lc, int level){
        if (sndcard) ms_snd_card_set_level(sndcard,MS_SND_CARD_PLAYBACK,level);
 }
 
+/**
+ * Allow to control microphone level:  gain in db
+ *
+ * @ingroup media_parameters
+**/
+void linphone_core_set_mic_gain_db (LinphoneCore *lc, float gaindb){
+       float gain=gaindb;
+       LinphoneCall *call=linphone_core_get_current_call (lc);
+       AudioStream *st;
+
+       lc->sound_conf.soft_mic_lev=gaindb;
+
+       if (linphone_core_ready(lc)){
+               lp_config_set_float(lc->config,"sound","mic_gain_db",lc->sound_conf.soft_mic_lev);
+       }
+
+       if (call==NULL || (st=call->audiostream)==NULL){
+               ms_message("linphone_core_set_mic_gain_db(): no active call.");
+               return;
+       }
+       if (st->volrecv){
+               ms_filter_call_method(st->volsend,MS_VOLUME_SET_DB_GAIN,&gain);
+       }else ms_warning("Could not apply gain: gain control wasn't activated.");
+}
+
+/**
+ * Get microphone gain in db.
+ *
+ * @ingroup media_parameters
+**/
+float linphone_core_get_mic_gain_db(LinphoneCore *lc) {
+       return lc->sound_conf.soft_mic_lev;
+}
+
 /**
  * Allow to control play level before entering sound card:  gain in db
  *
@@ -3250,6 +3360,9 @@ void linphone_core_set_playback_gain_db (LinphoneCore *lc, float gaindb){
        AudioStream *st;
 
        lc->sound_conf.soft_play_lev=gaindb;
+       if (linphone_core_ready(lc)){
+               lp_config_set_float(lc->config,"sound","playback_gain_db",lc->sound_conf.soft_play_lev);
+       }
 
        if (call==NULL || (st=call->audiostream)==NULL){
                ms_message("linphone_core_set_playback_gain_db(): no active call.");
@@ -3550,6 +3663,17 @@ void linphone_core_set_root_ca(LinphoneCore *lc,const char *path){
        sal_set_root_ca(lc->sal, path);
 }
 
+/**
+ * Gets the path to a file or folder containing trusted root CAs (PEM format)
+ *
+ * @param lc The LinphoneCore object
+ *
+ * @ingroup media_parameters
+**/
+const char *linphone_core_get_root_ca(LinphoneCore *lc){
+       return sal_get_root_ca(lc->sal);
+}
+
 /**
  * Specify whether the tls server certificate must be verified when connecting to a SIP/TLS server.
 **/
@@ -3650,7 +3774,7 @@ void linphone_core_mute_mic(LinphoneCore *lc, bool_t val){
        }
        if (st!=NULL){
                audio_stream_set_mic_gain(st,
-                       (val==TRUE) ? 0 : lp_config_get_float(lc->config,"sound","mic_gain",1));
+                       (val==TRUE) ? 0 : pow(10,lc->sound_conf.soft_mic_lev/10));
                if ( linphone_core_get_rtp_no_xmit_on_audio_mute(lc) ){
                        audio_stream_mute_rtp(st,val);
                }
@@ -4014,7 +4138,7 @@ int linphone_core_set_video_device(LinphoneCore *lc, const char *id){
        if (id!=NULL){
                lc->video_conf.device=ms_web_cam_manager_get_cam(ms_web_cam_manager_get(),id);
                if (lc->video_conf.device==NULL){
-                       ms_warning("Could not found video device %s",id);
+                       ms_warning("Could not find video device %s",id);
                }
        }
        if (lc->video_conf.device==NULL)
@@ -4080,6 +4204,16 @@ int linphone_core_set_static_picture(LinphoneCore *lc, const char *path) {
        return 0;
 }
 
+const char *linphone_core_get_static_picture(LinphoneCore *lc) {
+       const char *path=NULL;
+#ifdef VIDEO_ENABLED
+       path=ms_static_image_get_default_image();       
+#else
+       ms_warning("Video support not compiled.");
+#endif
+       return path;
+}
+
 int linphone_core_set_static_picture_fps(LinphoneCore *lc, float fps) {
 #ifdef VIDEO_ENABLED
        VideoStream *vs = NULL;
@@ -4567,6 +4701,7 @@ void sip_config_uninit(LinphoneCore *lc)
        lp_config_set_int(lc->config,"sip","guess_hostname",config->guess_hostname);
        lp_config_set_string(lc->config,"sip","contact",config->contact);
        lp_config_set_int(lc->config,"sip","inc_timeout",config->inc_timeout);
+       lp_config_set_int(lc->config,"sip","in_call_timeout",config->in_call_timeout);
        lp_config_set_int(lc->config,"sip","use_info",config->use_info);
        lp_config_set_int(lc->config,"sip","use_rfc2833",config->use_rfc2833);
        lp_config_set_int(lc->config,"sip","use_ipv6",config->ipv6_enabled);
@@ -4635,6 +4770,8 @@ static void sound_config_uninit(LinphoneCore *lc)
        ms_free(config->cards);
 
        lp_config_set_string(lc->config,"sound","remote_ring",config->remote_ring);
+       lp_config_set_float(lc->config,"sound","playback_gain_db",config->soft_play_lev);
+       lp_config_set_float(lc->config,"sound","mic_gain_db",config->soft_mic_lev);
 
        if (config->local_ring) ms_free(config->local_ring);
        if (config->remote_ring) ms_free(config->remote_ring);
@@ -4754,6 +4891,9 @@ static void linphone_core_uninit(LinphoneCore *lc)
 
        ms_list_for_each(lc->call_logs,(void (*)(void*))linphone_call_log_destroy);
        lc->call_logs=ms_list_free(lc->call_logs);
+       
+       ms_list_for_each(lc->last_recv_msg_ids,ms_free);
+       lc->last_recv_msg_ids=ms_list_free(lc->last_recv_msg_ids);
 
        linphone_core_free_payload_types(lc);
        ortp_exit();
@@ -4975,6 +5115,8 @@ const char *linphone_reason_to_string(LinphoneReason err){
                        return "User not found";
                case LinphoneReasonNotAnswered:
                        return "Not answered";
+               case LinphoneReasonBusy:
+                       return "Busy";
        }
        return "unknown error";
 }
@@ -5068,6 +5210,10 @@ void linphone_core_set_zrtp_secrets_file(LinphoneCore *lc, const char* file){
        lc->zrtp_secrets_cache=file ? ms_strdup(file) : NULL;
 }
 
+const char *linphone_core_get_zrtp_secrets_file(LinphoneCore *lc){
+       return lc->zrtp_secrets_cache;
+}
+
 const LinphoneCall* linphone_core_find_call_from_uri(LinphoneCore *lc, const char *uri) {
        if (uri == NULL) return NULL;
        MSList *calls=lc->calls;
@@ -5200,8 +5346,10 @@ const char*  linphone_core_get_device_identifier(const LinphoneCore *lc) {
 **/
 void linphone_core_set_sip_dscp(LinphoneCore *lc, int dscp){
        sal_set_dscp(lc->sal,dscp);
-       if (linphone_core_ready(lc))
+       if (linphone_core_ready(lc)){
                lp_config_set_int_hex(lc->config,"sip","dscp",dscp);
+               apply_transports(lc);
+       }
 }
 
 /**
index ad52c559f4955079f0276743ec6e1eb7b3daf843..f1a9174c8e3ad0c03447d8a01ad6e053e7676359 100644 (file)
@@ -204,14 +204,9 @@ bool_t linphone_call_params_early_media_sending_enabled(const LinphoneCallParams
 bool_t linphone_call_params_local_conference_mode(const LinphoneCallParams *cp);
 void linphone_call_params_set_audio_bandwidth_limit(LinphoneCallParams *cp, int bw);
 void linphone_call_params_destroy(LinphoneCallParams *cp);
-/**
- * @ingroup call_control
- * Use to know if this call has been configured in low bandwidth mode.
- * This mode can be automatically discovered thanks to a stun server when activate_edge_workarounds=1 in section [net] of configuration file
- * <br> When enabled, this param may transform a call request with video in audio only mode.
- * @return TRUE if low bandwidth has been configured/detected
- */
 bool_t linphone_call_params_low_bandwidth_enabled(const LinphoneCallParams *cp);
+void linphone_call_params_enable_low_bandwidth(LinphoneCallParams *cp, bool_t enabled);
+
 /**
  * Enum describing failure reasons.
  * @ingroup initializing
@@ -222,7 +217,8 @@ enum _LinphoneReason{
        LinphoneReasonBadCredentials, /**<Authentication failed due to bad or missing credentials*/
        LinphoneReasonDeclined, /**<The call has been declined*/
        LinphoneReasonNotFound, /**<Destination of the calls was not found.*/
-       LinphoneReasonNotAnswered
+       LinphoneReasonNotAnswered, /**<The call was not answered in time*/
+       LinphoneReasonBusy /**<Phone line was busy */
 };
 
 /**
@@ -662,13 +658,13 @@ const LinphoneAddress* linphone_chat_room_get_peer_address(LinphoneChatRoom *cr)
  */
 void linphone_chat_room_send_message(LinphoneChatRoom *cr, const char *msg);
 /**
- *LinphoneChatMessageStatus used to notify if message has been succesfully delivered or not
+ *LinphoneChatMessageState is used to notify if messages have been succesfully delivered or not.
  */
 typedef enum _LinphoneChatMessageStates {
-       LinphoneChatMessageStateIdle, /** initial state*/
-       LinphoneChatMessageStateInProgress, /*delivery in progress**/
-       LinphoneChatMessageStateDelivered, /** message succesffully delivered an acknoleged by remote end point*/
-       LinphoneChatMessageStateNotDelivered /** message was not delivered*/
+       LinphoneChatMessageStateIdle, /**<initial state*/
+       LinphoneChatMessageStateInProgress, /**<delivery in progress**/
+       LinphoneChatMessageStateDelivered, /**<message succesffully delivered an acknoleged by remote end point*/
+       LinphoneChatMessageStateNotDelivered /**<message was not delivered*/
 }LinphoneChatMessageState;
 
        
@@ -678,20 +674,20 @@ typedef enum _LinphoneChatMessageStates {
 const char* linphone_chat_message_state_to_string(const LinphoneChatMessageState state);
 
 /**
- * clone a chat message 
+ * Clone a chat message 
  *@param message #LinphoneChatMessage obj
  *@return #LinphoneChatMessage
  */
 LinphoneChatMessage* linphone_chat_message_clone(const LinphoneChatMessage* message);
 /**
- * set origine of the message
+ * Set origin of the message
  *@param message #LinphoneChatMessage obj
  *@param from #LinphoneAddress origin of this message (copied)
  */
 void linphone_chat_message_set_from(LinphoneChatMessage* message, const LinphoneAddress* from);
 
 /**
- * get origine of the message 
+ * Get origin of the message 
  *@param message #LinphoneChatMessage obj
  *@return #LinphoneAddress
  */
@@ -700,21 +696,21 @@ LinphoneAddress* linphone_chat_message_get_from(const LinphoneChatMessage* messa
 /**
  * Linphone message can carry external body as defined by rfc2017
  * @param message #LinphoneChatMessage
- * @return return external body url null if not present.
+ * @return external body url or NULL if not present.
  */
 const char* linphone_chat_message_get_external_body_url(const LinphoneChatMessage* message);
        
 /**
  * Linphone message can carry external body as defined by rfc2017
  * 
- * @param  #LinphoneChatMessage  
+ * @param message a LinphoneChatMessage  
  * @param url ex: access-type=URL; URL="http://www.foo.com/file"
  */
 void linphone_chat_message_set_external_body_url(LinphoneChatMessage* message,const char* url);
 
 /**
- * get text part of this message
- *@return text or NULL if no text.
+ * Get text part of this message
+ * @return text or NULL if no text.
  */
 const char * linphone_chat_message_get_text(const LinphoneChatMessage* message);       
 /**
@@ -730,15 +726,15 @@ void linphone_chat_message_set_user_data(LinphoneChatMessage* message,void*);
 /**
  * Call back used to notify message delivery status
  *@param msg #LinphoneChatMessage object
- *@param status #LinphoneChatMessageStatus
- *@param ud us user data
+ *@param status LinphoneChatMessageState
+ *@param ud application user data
  */
 typedef void (*LinphoneChatMessageStateChangeCb)(LinphoneChatMessage* msg,LinphoneChatMessageState state,void* ud);
 /**
  * send a message to peer member of this chat room.
  * @param cr #LinphoneChatRoom object
  * @param msg #LinphoneChatMessage message to be sent
- * @param status_cb #LinphoneChatMessageStatus status call back invoked when to message is delivered or not. May be NULL
+ * @param status_cb LinphoneChatMessageStateChangeCb status callback invoked when message is delivered or could not be delivered. May be NULL
  * @param ud user data for the status cb.
  */
 void linphone_chat_room_send_message2(LinphoneChatRoom *cr, LinphoneChatMessage* msg,LinphoneChatMessageStateChangeCb status_cb,void* ud);
@@ -905,8 +901,6 @@ typedef void * (*LinphoneWaitingCallback)(struct _LinphoneCore *lc, void *contex
 void linphone_core_enable_logs(FILE *file);
 void linphone_core_enable_logs_with_cb(OrtpLogFunc logfunc);
 void linphone_core_disable_logs(void);
-/*sets the user-agent string in sip messages, must be set before linphone_core_new() or linphone_core_init() */
-void linphone_core_set_user_agent(const char *ua_name, const char *version);
 const char *linphone_core_get_version(void);
 const char *linphone_core_get_user_agent_name(void);
 const char *linphone_core_get_user_agent_version(void);
@@ -936,6 +930,9 @@ const char*  linphone_core_get_device_identifier(const LinphoneCore *lc);
 
 #endif
 
+/*sets the user-agent string in sip messages, ideally called just after linphone_core_new() or linphone_core_init() */
+void linphone_core_set_user_agent(LinphoneCore *lc, const char *ua_name, const char *version);
+
 LinphoneAddress * linphone_core_interpret_url(LinphoneCore *lc, const char *url);
 
 LinphoneCall * linphone_core_invite(LinphoneCore *lc, const char *url);
@@ -964,6 +961,8 @@ int linphone_core_terminate_call(LinphoneCore *lc, LinphoneCall *call);
 
 int linphone_core_redirect_call(LinphoneCore *lc, LinphoneCall *call, const char *redirect_uri);
 
+int linphone_core_decline_call(LinphoneCore *lc, LinphoneCall * call, LinphoneReason reason);
+
 int linphone_core_terminate_all_calls(LinphoneCore *lc);
 
 int linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *call);
@@ -1052,8 +1051,8 @@ int linphone_core_enable_payload_type(LinphoneCore *lc, PayloadType *pt, bool_t
  * This function searches in audio and video codecs for the given payload type name and clockrate.
  * @param lc #LinphoneCore object
  * @param type payload mime type (I.E SPEEX, PCMU, VP8)
- * @param rate, can be #LINPHONE_FIND_PAYLOAD_IGNORE_RATE
- * @param channels, number of channels, can be #LINPHONE_FIND_PAYLOAD_IGNORE_CHANNELS
+ * @param rate can be #LINPHONE_FIND_PAYLOAD_IGNORE_RATE
+ * @param channels  number of channels, can be #LINPHONE_FIND_PAYLOAD_IGNORE_CHANNELS
  * @return Returns NULL if not found.
  */    
 PayloadType* linphone_core_find_payload_type(LinphoneCore* lc, const char* type, int rate, int channels) ;
@@ -1161,6 +1160,10 @@ void linphone_core_set_inc_timeout(LinphoneCore *lc, int seconds);
 
 int linphone_core_get_inc_timeout(LinphoneCore *lc);
 
+void linphone_core_set_in_call_timeout(LinphoneCore *lc, int seconds);
+
+int linphone_core_get_in_call_timeout(LinphoneCore *lc);
+
 void linphone_core_set_stun_server(LinphoneCore *lc, const char *server);
 
 const char * linphone_core_get_stun_server(const LinphoneCore *lc);
@@ -1189,9 +1192,11 @@ int linphone_core_get_rec_level(LinphoneCore *lc);
 void linphone_core_set_ring_level(LinphoneCore *lc, int level);
 void linphone_core_set_play_level(LinphoneCore *lc, int level);
 
+void linphone_core_set_mic_gain_db(LinphoneCore *lc, float level);
+float linphone_core_get_mic_gain_db(LinphoneCore *lc);
 void linphone_core_set_playback_gain_db(LinphoneCore *lc, float level);
-
 float linphone_core_get_playback_gain_db(LinphoneCore *lc);
+
 void linphone_core_set_rec_level(LinphoneCore *lc, int level);
 const char * linphone_core_get_ringer_device(LinphoneCore *lc);
 const char * linphone_core_get_playback_device(LinphoneCore *lc);
@@ -1205,6 +1210,7 @@ void linphone_core_set_ring(LinphoneCore *lc, const char *path);
 const char *linphone_core_get_ring(const LinphoneCore *lc);
 void linphone_core_verify_server_certificates(LinphoneCore *lc, bool_t yesno);
 void linphone_core_set_root_ca(LinphoneCore *lc, const char *path);
+const char *linphone_core_get_root_ca(LinphoneCore *lc);
 void linphone_core_set_ringback(LinphoneCore *lc, const char *path);
 const char * linphone_core_get_ringback(const LinphoneCore *lc);
 
@@ -1229,7 +1235,6 @@ void linphone_core_mute_mic(LinphoneCore *lc, bool_t muted);
 **/
 bool_t linphone_core_is_mic_muted(LinphoneCore *lc);
 
-bool_t linphone_core_is_audio_muted(LinphoneCore *lc);
 bool_t linphone_core_is_rtp_muted(LinphoneCore *lc);
 
 bool_t linphone_core_get_rtp_no_xmit_on_audio_mute(const LinphoneCore *lc);
@@ -1273,8 +1278,9 @@ const char**  linphone_core_get_video_devices(const LinphoneCore *lc);
 int linphone_core_set_video_device(LinphoneCore *lc, const char *id);
 const char *linphone_core_get_video_device(const LinphoneCore *lc);
 
-/* Set static picture to be used when "Static picture" is the video device */
+/* Set and get static picture to be used when "Static picture" is the video device */
 int linphone_core_set_static_picture(LinphoneCore *lc, const char *path);
+const char *linphone_core_get_static_picture(LinphoneCore *lc);
 
 /* Set and get frame rate for static picture */
 int linphone_core_set_static_picture_fps(LinphoneCore *lc, float fps);
@@ -1378,7 +1384,7 @@ void linphone_core_refresh_registers(LinphoneCore* lc);
 
 /* Path to the file storing secrets cache */
 void linphone_core_set_zrtp_secrets_file(LinphoneCore *lc, const char* file);
-
+const char *linphone_core_get_zrtp_secrets_file(LinphoneCore *lc);
 
 const LinphoneCall* linphone_core_find_call_from_uri(LinphoneCore *lc, const char *uri);
 
index 080c8b0091293c5776119d784afea2376ad439aa..63d94411ec0e8440e48f756b0c533e9c4c2402c9 100644 (file)
@@ -17,6 +17,9 @@ along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 #include <jni.h>
+#ifdef USE_JAVAH
+#include "linphonecore_jni.h"
+#endif
 #include "linphonecore_utils.h"
 #include <ortp/zrtp.h>
 
@@ -539,6 +542,22 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_delete(JNIEnv*  env
        delete lcData;
 }
 
+extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setPrimaryContact(JNIEnv* env, jobject  thiz, jlong lc, jstring jdisplayname, jstring jusername) {
+       const char* displayname = env->GetStringUTFChars(jdisplayname, NULL);
+       const char* username = env->GetStringUTFChars(jusername, NULL);
+
+       LinphoneAddress *parsed = linphone_core_get_primary_contact_parsed((LinphoneCore*)lc);
+    if (parsed != NULL) {
+        linphone_address_set_display_name(parsed, displayname);
+        linphone_address_set_username(parsed, username);
+        char *contact = linphone_address_as_string(parsed);
+               linphone_core_set_primary_contact((LinphoneCore*)lc, contact);
+       }
+
+       env->ReleaseStringUTFChars(jdisplayname, displayname);
+       env->ReleaseStringUTFChars(jusername, username);
+}
+
 extern "C" void Java_org_linphone_core_LinphoneCoreImpl_clearProxyConfigs(JNIEnv* env, jobject thiz,jlong lc) {
        linphone_core_clear_proxy_config((LinphoneCore*)lc);
 }
@@ -700,6 +719,13 @@ extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_isNetworkStateReacha
                return (jboolean)linphone_core_is_network_reachable((LinphoneCore*)lc);
 }
 
+extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setMicrophoneGain(JNIEnv*  env
+               ,jobject  thiz
+               ,jlong lc
+               ,jfloat gain) {
+               linphone_core_set_mic_gain_db((LinphoneCore*)lc,gain);
+}
+
 extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setPlaybackGain(       JNIEnv*  env
                ,jobject  thiz
                ,jlong lc
@@ -1268,6 +1294,11 @@ extern "C" jstring Java_org_linphone_core_LinphoneCallLogImpl_getStartDate(JNIEn
        jstring jvalue =env->NewStringUTF(((LinphoneCallLog*)ptr)->start_date);
        return jvalue;
 }
+extern "C" jlong Java_org_linphone_core_LinphoneCallLogImpl_getTimestamp(JNIEnv*  env
+                                                                                                                                               ,jobject  thiz
+                                                                                                                                               ,jlong ptr) {
+       return static_cast<long> (((LinphoneCallLog*)ptr)->start_date_time);
+}
 extern "C" jint Java_org_linphone_core_LinphoneCallLogImpl_getCallDuration(JNIEnv*  env
                                                                                                                                                ,jobject  thiz
                                                                                                                                                ,jlong ptr) {
@@ -1346,6 +1377,8 @@ extern "C" jfloat Java_org_linphone_core_LinphoneCallStatsImpl_getSenderInterarr
                pt = linphone_call_params_get_used_audio_codec(params);
        else
                pt = linphone_call_params_get_used_video_codec(params);
+       if (!pt || (pt->clock_rate == 0))
+               return (jfloat)0.0;
        return (jfloat)((float)report_block_get_interarrival_jitter(srb) / (float)pt->clock_rate);
 }
 extern "C" jfloat Java_org_linphone_core_LinphoneCallStatsImpl_getReceiverInterarrivalJitter(JNIEnv *env, jobject thiz, jlong stats_ptr, jlong call_ptr) {
@@ -1373,6 +1406,8 @@ extern "C" jfloat Java_org_linphone_core_LinphoneCallStatsImpl_getReceiverIntera
                pt = linphone_call_params_get_used_audio_codec(params);
        else
                pt = linphone_call_params_get_used_video_codec(params);
+       if (!pt || (pt->clock_rate == 0))
+               return (jfloat)0.0;
        return (jfloat)((float)report_block_get_interarrival_jitter(rrb) / (float)pt->clock_rate);
 }
 extern "C" jfloat Java_org_linphone_core_LinphoneCallStatsImpl_getRoundTripDelay(JNIEnv *env, jobject thiz, jlong stats_ptr) {
@@ -1458,6 +1493,12 @@ extern "C" jlong Java_org_linphone_core_LinphoneCallImpl_getRemoteAddress(       JNIEn
        return (jlong)linphone_call_get_remote_address((LinphoneCall*)ptr);
 }
 
+extern "C" jstring Java_org_linphone_core_LinphoneCallImpl_getRemoteUserAgent(JNIEnv *env, jobject thiz, jlong ptr) {
+       LinphoneCall *call = (LinphoneCall *)ptr;
+       jstring jvalue = env->NewStringUTF(linphone_call_get_remote_user_agent(call));
+       return jvalue;
+}
+
 extern "C" jint Java_org_linphone_core_LinphoneCallImpl_getState(      JNIEnv*  env
                                                                                                                                                ,jobject  thiz
                                                                                                                                                ,jlong ptr) {
@@ -1738,6 +1779,10 @@ extern "C" jstring Java_org_linphone_core_LinphoneCoreImpl_getStunServer(JNIEnv
 
 //CallParams
 
+extern "C" void Java_org_linphone_core_LinphoneCallImpl_enableLowBandwidth(JNIEnv *env, jobject thiz, jlong cp, jboolean enable) {
+       linphone_call_params_enable_low_bandwidth((LinphoneCallParams *)cp, enable);
+}
+
 extern "C" jlong Java_org_linphone_core_LinphoneCallParamsImpl_getUsedAudioCodec(JNIEnv *env, jobject thiz, jlong cp) {
        return (jlong)linphone_call_params_get_used_audio_codec((LinphoneCallParams *)cp);
 }
@@ -1815,7 +1860,6 @@ extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_updateCall(JNIEnv *env,
        return (jint) linphone_core_update_call((LinphoneCore *)lc, (LinphoneCall *)call, (const LinphoneCallParams *)params);
 }
 
-
 extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setPreferredVideoSize(JNIEnv *env, jobject thiz, jlong lc, jint width, jint height){
        MSVideoSize vsize;
        vsize.width = (int)width;
@@ -1839,6 +1883,14 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setUploadBandwidth(JNIEn
        linphone_core_set_upload_bandwidth((LinphoneCore *)lc, (int) bw);
 }
 
+extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setUseSipInfoForDtmfs(JNIEnv *env, jobject thiz, jlong lc, jboolean use){
+       linphone_core_set_use_info_for_dtmf((LinphoneCore *)lc, (bool) use);
+}
+
+extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setUseRfc2833ForDtmfs(JNIEnv *env, jobject thiz, jlong lc, jboolean use){
+       linphone_core_set_use_rfc2833_for_dtmf((LinphoneCore *)lc, (bool) use);
+}
+
 extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setDownloadPtime(JNIEnv *env, jobject thiz, jlong lc, jint ptime){
        linphone_core_set_download_ptime((LinphoneCore *)lc, (int) ptime);
 }
@@ -2035,10 +2087,13 @@ extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_soundResourcesLocked
 
 // Needed by Galaxy S (can't switch to/from speaker while playing and still keep mic working)
 // Implemented directly in msandroid.cpp (sound filters for Android).
-extern "C" void msandroid_hack_speaker_state(bool speakerOn);
-
-extern "C" void Java_org_linphone_LinphoneManager_hackSpeakerState(JNIEnv*  env,jobject thiz,jboolean speakerOn){
-       msandroid_hack_speaker_state(speakerOn);
+extern "C" void Java_org_linphone_core_LinphoneCoreImpl_forceSpeakerState(JNIEnv *env, jobject thiz, jlong ptr, jboolean speakerOn) {
+       LinphoneCore *lc = (LinphoneCore *)ptr;
+       LinphoneCall *call = linphone_core_get_current_call(lc);
+       if (call && call->audiostream && call->audiostream->soundread) {
+               bool_t on = speakerOn;
+               ms_filter_call_method(call->audiostream->soundread, MS_AUDIO_CAPTURE_FORCE_SPEAKER_STATE, &on);
+       }
 }
 // End Galaxy S hack functions
 
@@ -2094,7 +2149,7 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_tunnelEnable(JNIEnv *env
 extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setUserAgent(JNIEnv *env,jobject thiz,jlong pCore, jstring name, jstring version){
        const char* cname=env->GetStringUTFChars(name, NULL);
        const char* cversion=env->GetStringUTFChars(version, NULL);
-       linphone_core_set_user_agent(cname,cversion);
+       linphone_core_set_user_agent((LinphoneCore *)pCore,cname,cversion);
        env->ReleaseStringUTFChars(name, cname);
        env->ReleaseStringUTFChars(version, cversion);
 }
@@ -2134,6 +2189,10 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setIncomingTimeout(JNIEn
        linphone_core_set_inc_timeout((LinphoneCore *)lc, timeout);
 }
 
+extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setInCallTimeout(JNIEnv *env, jobject thiz, jlong lc, jint timeout) {
+       linphone_core_set_in_call_timeout((LinphoneCore *)lc, timeout);
+}
+
 extern "C" jstring Java_org_linphone_core_LinphoneCoreImpl_getVersion(JNIEnv*  env,jobject  thiz,jlong ptr) {
        jstring jvalue =env->NewStringUTF(linphone_core_get_version());
        return jvalue;
index fadfc1a3608bb25cf559c39927ecba02b488ac61..cc0a6f692ad420071682b4505c443d26348dd6d2 100644 (file)
@@ -94,8 +94,14 @@ void linphone_core_remove_iterate_hook(LinphoneCore *lc, LinphoneCoreIterateHook
  *@return call country code or -1 if not found
  */
 int linphone_dial_plan_lookup_ccc_from_iso(const char* iso); 
-       
-       
+/**
+ * @ingroup misc
+ *Function to get  call country code from  an e164 number, ex: +33952650121 will return 33
+ *@param e164 phone number
+ *@return call country code or -1 if not found
+ */
+int linphone_dial_plan_lookup_ccc_from_e164(const char* e164);
+
 #ifdef __cplusplus
 }
 #endif
index 8f3cae0a11bcbbd11bf401052ed4d6227bfb9dda..8e6f921283ea96c0a47d6d664973c7c6acd0babb 100644 (file)
@@ -25,6 +25,8 @@
 #ifndef LPCONFIG_H
 #define LPCONFIG_H
 
+#include <ortp/port.h>
+
 /**
  * The LpConfig object is used to manipulate a configuration file.
  * 
index b9176ebd4ab65ef0f3ca5a7277411f9027b318a2..d7572213825b45c809c241e711b42649a6ca3c53 100644 (file)
@@ -574,21 +574,31 @@ int linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call){
        return -1;
 }
 
+int linphone_core_get_edge_bw(LinphoneCore *lc){
+       int edge_bw=lp_config_get_int(lc->config,"net","edge_bw",20);
+       return edge_bw;
+}
+
+int linphone_core_get_edge_ptime(LinphoneCore *lc){
+       int edge_ptime=lp_config_get_int(lc->config,"net","edge_ptime",100);
+       return edge_ptime;
+}
+
 void linphone_core_adapt_to_network(LinphoneCore *lc, int ping_time_ms, LinphoneCallParams *params){
-       if (lp_config_get_int(lc->config,"net","activate_edge_workarounds",0)==1){
+       if (ping_time_ms>0 && lp_config_get_int(lc->config,"net","activate_edge_workarounds",0)==1){
                ms_message("Stun server ping time is %i ms",ping_time_ms);
                int threshold=lp_config_get_int(lc->config,"net","edge_ping_time",500);
                
                if (ping_time_ms>threshold){
-                       int edge_ptime=lp_config_get_int(lc->config,"net","edge_ptime",100);
-                       int edge_bw=lp_config_get_int(lc->config,"net","edge_bw",20);
-                       /* we are in a 2G network*/
-                       params->up_bw=params->down_bw=edge_bw;
-                       params->up_ptime=params->down_ptime=edge_ptime;
-                       params->has_video=FALSE;
+                       /* we might be in a 2G network*/
                        params->low_bandwidth=TRUE;
                }/*else use default settings */
        }
+       if (params->low_bandwidth){
+               params->up_bw=params->down_bw=linphone_core_get_edge_bw(lc);
+               params->up_ptime=params->down_ptime=linphone_core_get_edge_ptime(lc);
+               params->has_video=FALSE;
+       }
 }
 
 
index 27ce12578bd01d132220dccb6b9b45d0b6a09a63..d43666e56592019acfe5860de447a640ed8f5c43 100644 (file)
@@ -1,10 +1,8 @@
 SUBDIRS=src
 
-
-
-INSTALLDIR=$(shell cd $(top_builddir) && pwd)/$(PACKAGE)-install
+INSTALLDIR=$(abs_top_builddir)/$(PACKAGE)-install
 INSTALLDIR_WITH_PREFIX=$(INSTALLDIR)/$(prefix)
-ZIPFILE=$(shell cd $(top_builddir) && pwd)/$(PACKAGE)-win32-$(VERSION).zip
+ZIPFILE=$(abs_top_builddir)/$(PACKAGE)-win32-$(VERSION).zip
 ZIP_EXCLUDED=include 
 PLUGIN_DEPS_PREFIX=/usr/bin
 PLUGIN_DEPS=   libsoup-2.4-1.dll \
@@ -20,9 +18,9 @@ PLUGIN_DEPS=  libsoup-2.4-1.dll \
 zip:
        rm -f $(ZIPFILE)
        rm -rf $(INSTALLDIR)
-       mkdir -p $(INSTALLDIR)
+       $(MKDIR_P) $(INSTALLDIR)
        make install DESTDIR=$(INSTALLDIR)
-       mkdir -p $(INSTALLDIR_WITH_PREFIX)/bin
+       $(MKDIR_P) $(INSTALLDIR_WITH_PREFIX)/bin
        cd $(PLUGIN_DEPS_PREFIX) && \
                cp -f $(PLUGIN_DEPS) $(INSTALLDIR_WITH_PREFIX)/bin/.
        cd $(INSTALLDIR)/$(prefix) && rm -rf $(ZIP_EXCLUDED) && \
index 07fd1c689189766bd999982326ba06b9742de5e6..925a303605a1b8b99c9c48f0e2cb48c3aad602ce 100644 (file)
@@ -382,6 +382,7 @@ typedef struct sip_config
        MSList *proxies;
        MSList *deleted_proxies;
        int inc_timeout;        /*timeout after an un-answered incoming call is rejected*/
+       int in_call_timeout;    /*timeout after a call is hangup */
        unsigned int keepalive_period; /* interval in ms between keep alive messages sent to the proxy server*/
        LCSipTransports transports;
        bool_t use_info;
@@ -436,6 +437,7 @@ typedef struct sound_config
        const char **cards;
        int latency;    /* latency in samples of the current used sound device */
        float soft_play_lev; /*playback gain in db.*/
+       float soft_mic_lev; /*mic gain in db.*/
        char rec_lev;
        char play_lev;
        char ring_lev;
@@ -556,12 +558,16 @@ struct _LinphoneCore
        bool_t network_reachable;
        bool_t use_preview_window;
        
+        time_t network_last_check;
+        bool_t network_last_status;
+
        bool_t ringstream_autorelease;
        bool_t pad[3];
        int device_rotation;
        int max_calls;
        LinphoneTunnel *tunnel;
        char* device_id;
+       MSList *last_recv_msg_ids;
 };
 
 LinphoneTunnel *linphone_core_tunnel_new(LinphoneCore *lc);
@@ -576,10 +582,7 @@ int linphone_core_set_as_current_call(LinphoneCore *lc, LinphoneCall *call);
 int linphone_core_get_calls_nb(const LinphoneCore *lc);
 
 void linphone_core_set_state(LinphoneCore *lc, LinphoneGlobalState gstate, const char *message);
-
-SalMediaDescription *create_local_media_description(LinphoneCore *lc, LinphoneCall *call);
-void update_local_media_description(LinphoneCore *lc, LinphoneCall *call);
-
+void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *call);
 void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMediaDescription *new_md);
 
 bool_t linphone_core_is_payload_type_usable_for_bandwidth(LinphoneCore *lc, PayloadType *pt,  int bandwidth_limit);
@@ -636,7 +639,8 @@ void _linphone_core_codec_config_write(LinphoneCore *lc);
 #endif
 void call_logs_write_to_config_file(LinphoneCore *lc);
 
-
+int linphone_core_get_edge_bw(LinphoneCore *lc);
+int linphone_core_get_edge_ptime(LinphoneCore *lc);
 
 #ifdef __cplusplus
 }
index 718f7b0f5efcce4570a321cb91912f44900cf269..3b47af42ce0ec2232811abfcbfc08f414fc32c13 100644 (file)
@@ -119,7 +119,7 @@ int linphone_proxy_config_set_server_addr(LinphoneProxyConfig *obj, const char *
                if (addr==NULL)
                        addr=linphone_address_new(server_addr);
                if (addr){
-                       obj->reg_proxy=linphone_address_as_string_uri_only(addr);
+                       obj->reg_proxy=linphone_address_as_string(addr);
                        linphone_address_destroy(addr);
                }else{
                        ms_warning("Could not parse %s",server_addr);
@@ -378,16 +378,261 @@ typedef struct dial_plan{
 }dial_plan_t;
 
 /* TODO: fill with information for all countries over the world*/
+
 static dial_plan_t const dial_plans[]={
-       {"France"                       ,"FR"           , "33"  , 9             , "00"  },
-       {"United States"        ,"US"           , "1"   , 10    , "011" },
-       {"Turkey"                       ,"TR"           , "90"  , 10    , "00"  },
-       {"Switzerland"          ,"XK"           , "41"  , 9             , "00"  },
-       {NULL           ,NULL,""        , 0     , NULL  }
+       {"Afghanistan"                  ,"AF"           , "93"      , 9         , "00"  },
+       {"Albania"                      ,"AL"           , "355"     , 9         , "00"  },
+       {"Algeria"                      ,"DZ"           , "213"     , 9         , "00"  },
+       {"American Samoa"               ,"AS"           , "1"       , 10        , "011" },
+       {"Andorra"                      ,"AD"           , "376"     , 6         , "00"  },
+       {"Angola"                       ,"AO"           , "244"     , 9         , "00"  },
+       {"Anguilla"                     ,"AI"           , "1"       , 10        , "011" },
+       {"Antigua and Barbuda"          ,"AG"           , "1"       , 10        , "011" },
+       {"Argentina"                    ,"AR"           , "54"      , 10        , "00"  },
+       {"Armenia"                      ,"AM"           , "374"     , 8         , "00"  },
+       {"Aruba"                        ,"AW"           , "297"     , 7         , "011" },
+       {"Australia"                    ,"AU"           , "61"      , 9     , "0011"},
+       {"Austria"                      ,"AT"           , "43"      , 10        , "00"  },
+       {"Azerbaijan"                   ,"AZ"       , "994"     , 9             , "00"  },
+       {"Bahamas"                      ,"BS"           , "1"       , 10    , "011"     },
+       {"Bahrain"                      ,"BH"           , "973"     , 8     , "00"  },
+       {"Bangladesh"                   ,"BD"           , "880"     , 10    , "00"  },
+       {"Barbados"                     ,"BB"           , "1"       , 10    , "011"     },
+    {"Belarus"                      ,"BY"              , "375"     , 9     , "00"  },
+       {"Belgium"                      ,"BE"           , "32"      , 9     , "00"  },
+       {"Belize"                       ,"BZ"           , "501"     , 7     , "00"  },
+       {"Benin"                        ,"BJ"           , "229"     , 8     , "00"      },
+       {"Bermuda"                      ,"BM"           , "1"       , 10    , "011" },
+       {"Bhutan"                       ,"BT"           , "975"     , 8     , "00"  },
+       {"Bolivia"                      ,"BO"           , "591"     , 8     , "00"      },
+       {"Bosnia and Herzegovina"       ,"BA"           , "387"     , 8     , "00"  },
+       {"Botswana"                     ,"BW"           , "267"     , 8     , "00"  },
+    {"Brazil"                       ,"BR"              , "55"      , 10        , "00"  },
+       {"Brunei Darussalam"            ,"BN"           , "673"     , 7         , "00"  },
+       {"Bulgaria"                     ,"BG"           , "359"     , 9         , "00"  },
+       {"Burkina Faso"                 ,"BF"           , "226"     , 8         , "00"  },
+       {"Burundi"                      ,"BI"           , "257"     , 8     , "011" },
+    {"Cambodia"                     ,"KH"              , "855"     , 9         , "00"  },
+       {"Cameroon"                     ,"CM"           , "237"     , 8         , "00"  },
+       {"Canada"                       ,"CA"           , "1"       , 10        , "011" },
+       {"Cape Verde"                   ,"CV"           , "238"     , 7         , "00"  },
+       {"Cayman Islands"               ,"KY"           , "1"       , 10        , "011" },
+       {"Central African Republic"     ,"CF"           , "236"     , 8     , "00"  },
+       {"Chad"                         ,"TD"           , "235"     , 8         , "00"  },
+       {"Chile"                        ,"CL"           , "56"      , 9     , "00"  },
+       {"China"                        ,"CN"           , "86"      , 11        , "00"  },
+    {"Colombia"                     ,"CO"       , "57"      , 10       , "00"  },
+    {"Comoros"                      ,"KM"              , "269"     , 7     , "00"      },
+    {"Congo"                        ,"CG"              , "242"     , 9         , "00"  },
+    {"Congo Democratic Republic"       ,"CD"           , "243"     , 9         , "00"  },
+    {"Cook Islands"                 ,"CK"              , "682"     , 5         , "00"  },
+    {"Costa Rica"                   ,"CR"              , "506"     , 8     , "00"      },
+    {"C\99te d'Ivoire"               ,"AD"               , "225"     , 8     , "00"  },
+    {"Croatia"                      ,"HR"              , "385"     , 9         , "00"  },
+    {"Cuba"                         ,"CU"              , "53"      , 8     , "119" },
+    {"Cyprus"                       ,"CY"              , "357"     , 8     , "00"      },
+    {"Czech Republic"               ,"CZ"              , "420"     , 9     , "00"  },
+    {"Denmark"                      ,"DK"              , "45"      , 8         , "00"  },
+    {"Djibouti"                     ,"DJ"              , "253"     , 8         , "00"  },
+    {"Dominica"                     ,"DM"              , "1"       , 10        , "011" },
+    {"Dominican Republic"              ,"DO"           , "1"       , 10        , "011" },
+    {"Ecuador"                      ,"EC"       , "593"     , 9                , "00"  },
+    {"Egypt"                        ,"EG"              , "20"      , 10        , "00"  },
+    {"El Salvador"                  ,"SV"              , "503"     , 8         , "00"  },
+    {"Equatorial Guinea"            ,"GQ"              , "240"     , 9         , "00"  },
+    {"Eritrea"                      ,"ER"              , "291"     , 7         , "00"  },
+    {"Estonia"                      ,"EE"              , "372"     , 8     , "00"      },
+    {"Ethiopia"                     ,"ET"              , "251"     , 9     , "00"  },
+    {"Falkland Islands"                    ,"FK"               , "500"     , 5         , "00"  },
+    {"Faroe Islands"               ,"FO"               , "298"     , 6     , "00"  },
+    {"Fiji"                         ,"FJ"              , "679"     , 7     , "00"      },
+    {"Finland"                      ,"FI"              , "358"     , 9     , "00"  },
+    {"France"                       ,"FR"              , "33"      , 9         , "00"  },
+    {"French Guiana"                           ,"GF"           , "594"     , 9         , "00"  },
+    {"French Polynesia"             ,"PF"              , "689"     , 6     , "00"  },
+    {"Gabon"                        ,"GA"              , "241"     , 8     , "00"  },
+    {"Gambia"                       ,"GM"       , "220"     , 7                , "00"  },
+    {"Georgia"                      ,"GE"              , "995"     , 9     , "00"      },
+    {"Germany"                      ,"DE"              , "49"      , 11        , "00"  },
+    {"Ghana"                        ,"GH"              , "233"     , 9         , "00"  },
+    {"Gibraltar"                    ,"GI"              , "350"     , 8         , "00"  },
+    {"Greece"                       ,"GR"              , "30"      ,10     , "00"      },
+    {"Greenland"                    ,"GL"              , "299"     , 6         , "00"  },
+    {"Grenada"                      ,"GD"              , "1"       , 10        , "011" },
+    {"Guadeloupe"                   ,"GP"              , "590"     , 9     , "00"  },
+    {"Guam"                         ,"GU"              , "1"       , 10        , "011" },
+    {"Guatemala"                    ,"GT"              , "502"     , 8     , "00"  },
+    {"Guinea"                       ,"GN"              , "224"     , 8         , "00"  },
+    {"Guinea-Bissau"                           ,"GW"           , "245"     , 7         , "00"  },
+    {"Guyana"                       ,"GY"              , "592"     , 7     , "001" },
+    {"Haiti"                        ,"HT"              , "509"     , 8     , "00"  },
+    {"Honduras"                     ,"HN"       , "504"     , 8                , "00"  },
+    {"Hong Kong"                    ,"HK"              , "852"     , 8     , "001"     },
+    {"Hungary"                      ,"HU"              , "36"      , 9     , "00"  },
+    {"Iceland"                      ,"IS"              , "354"     , 9     , "00"  },
+    {"India"                        ,"IN"              , "91"      , 10    , "00"  },
+    {"Indonesia"                    ,"ID"              , "62"      , 10        , "001" },
+    {"Iran"                         ,"IR"              , "98"      , 10        , "00"  },
+    {"Iraq"                         ,"IQ"              , "964"     , 10        , "00"  },
+    {"Ireland"                      ,"IE"              , "353"     , 9         , "00"  },
+    {"Israel"                       ,"IL"              , "972"     , 9     , "00"      },
+    {"Italy"                        ,"IT"              , "39"      , 10        , "00"  },
+    {"Jamaica"                      ,"JM"              , "1"       , 10        , "011" },
+    {"Japan"                        ,"JP"              , "81"      , 10        , "010" },
+    {"Jordan"                       ,"JO"              , "962"     , 9     , "00"      },
+    {"Kazakhstan"                   ,"KZ"              , "7"       , 10    , "00"  },
+    {"Kenya"                        ,"KE"              , "254"     , 9         , "000" },
+    {"Kiribati"                     ,"KI"              , "686"     , 5         , "00"  },
+    {"Korea, North"                 ,"KP"              , "850"     , 12        , "99"  },
+    {"Korea, South"                 ,"KR"       , "82"      , 12       , "001" },
+    {"Kuwait"                       ,"KW"              , "965"     , 8     , "00"      },
+    {"Kyrgyzstan"                   ,"KG"              , "996"     , 9     , "00"  },
+    {"Laos"                         ,"LA"              , "856"     , 10    , "00"  },
+    {"Latvia"                       ,"LV"              , "371"     , 8     , "00"      },
+    {"Lebanon"                      ,"LB"              , "961"     , 7     , "00"      },
+    {"Lesotho"                      ,"LS"              , "266"     , 8         , "00"  },
+    {"Liberia"                      ,"LR"              , "231"     , 8         , "00"  },
+    {"Libya"                        ,"LY"              , "218"     , 8         , "00"  },
+    {"Liechtenstein"                ,"LI"              , "423"     , 7     , "00"      },
+    {"Lithuania"                    ,"LT"              , "370"     , 8         , "00"  },
+    {"Luxembourg"                   ,"LU"              , "352"     , 9         , "00"  },
+    {"Macau"                        ,"MO"              , "853"     , 8     , "00"  },
+    {"Macedonia"                    ,"MK"              , "389"     , 8     , "00"      },
+    {"Madagascar"                   ,"MG"              , "261"     , 9     , "00"  },
+    {"Malawi"                       ,"MW"              , "265"     , 9         , "00"  },
+    {"Malaysia"                     ,"MY"              , "60"      , 9         , "00"  },
+    {"Maldives"                     ,"MV"              , "960"     , 7     , "00"  },
+    {"Mali"                         ,"ML"              , "223"     , 8     , "00"  },
+    {"Malta"                        ,"MT"       , "356"     , 8                , "00"  },
+    {"Marshall Islands"                                ,"MH"           , "692"     , 7     , "011"     },
+    {"Martinique"                   ,"MQ"              , "596"     , 9     , "00"  },
+    {"Mauritania"                   ,"MR"              , "222"     , 8     , "00"  },
+    {"Mauritius"                    ,"MU"              , "230"     , 7     , "00"      },
+    {"Mayotte Island"               ,"YT"              , "262"     , 9     , "00"      },
+    {"Mexico"                       ,"MX"              , "52"      , 10        , "00"  },
+    {"Micronesia"                   ,"FM"              , "691"     , 7         , "011" },
+    {"Moldova"                      ,"MD"              , "373"     , 8         , "00"  },
+    {"Monaco"                       ,"MC"              , "377"     , 8     , "00"      },
+    {"Mongolia"                     ,"MN"              , "976"     , 8     , "001" },
+    {"Montenegro"                   ,"ME"              , "382"     , 8         , "00"  },
+    {"Montserrat"                   ,"MS"              , "664"     , 10        , "011" },
+    {"Morocco"                      ,"MA"              , "212"     , 9     , "00"      },
+    {"Mozambique"                   ,"MZ"              , "258"     , 9     , "00"  },
+    {"Myanmar"                      ,"MM"              , "95"      , 8         , "00"  },
+    {"Namibia"                      ,"NA"              , "264"     , 9         , "00"  },
+    {"Nauru"                        ,"NR"              , "674"     , 7     , "00"  },
+    {"Nepal"                        ,"NP"              , "43"      , 10        , "00"  },
+    {"Netherlands"                  ,"NL"       , "31"      , 9                , "00"  },
+    {"New Caledonia"                           ,"NC"           , "687"     , 6     , "00"      },
+    {"New Zealand"                  ,"NZ"              , "64"      , 10        , "00"  },
+    {"Nicaragua"                    ,"NI"              , "505"     , 8     , "00"  },
+    {"Niger"                        ,"NE"              , "227"     , 8     , "00"      },
+    {"Nigeria"                      ,"NG"              , "234"     , 10        , "009" },
+    {"Niue"                         ,"NU"              , "683"     , 4         , "00"  },
+    {"Norfolk Island"              ,"NF"               , "672"     , 5         , "00"  },
+    {"Northern Mariana Islands"            ,"MP"               , "1"       , 10        , "011" },
+    {"Norway"                       ,"NO"              , "47"      , 8     , "00"      },
+    {"Oman"                         ,"OM"              , "968"     , 8         , "00"  },
+    {"Pakistan"                     ,"PK"              , "92"      , 10        , "00"  },
+    {"Palau"                        ,"PW"              , "680"     , 7     , "011" },
+    {"Palestine"                    ,"PS"              , "970"     , 9     , "00"      },
+    {"Panama"                       ,"PA"              , "507"     , 8     , "00"  },
+    {"Papua New Guinea"                    ,"PG"               , "675"     , 8         , "00"  },
+    {"Paraguay"                     ,"PY"              , "595"     , 9         , "00"  },
+    {"Peru"                         ,"PE"              , "51"      , 9     , "00"  },
+    {"Philippines"                  ,"PH"              , "63"      , 10        , "00"  },
+    {"Poland"                       ,"PL"       , "48"      , 9                , "00"  },
+    {"Portugal"                     ,"PT"              , "351"     , 9     , "00"      },
+    {"Puerto Rico"                  ,"PR"              , "1"       , 10        , "011" },
+    {"Qatar"                        ,"QA"              , "974"     , 8     , "00"  },
+    {"R\8eunion Island"                          ,"RE"           , "262"     , 9     , "011"     },
+    {"Romania"                      ,"RO"              , "40"      , 9     , "00"      },
+    {"Russian Federation"           ,"RU"              , "7"       , 10        , "8"   },
+    {"Rwanda"                       ,"RW"              , "250"     , 9         , "00"  },
+    {"Saint Helena"                 ,"SH"              , "290"     , 4         , "00"  },
+    {"Saint Kitts and Nevis"           ,"KN"           , "1"       , 10        , "011" },
+    {"Saint Lucia"                  ,"LC"              , "1"       , 10        , "011" },
+    {"Saint Pierre and Miquelon"    ,"PM"              , "508"     , 6         , "00"  },
+    {"Saint Vincent and the Grenadines","VC"   , "1"       , 10        , "011" },
+    {"Samoa"                        ,"WS"              , "685"     , 7     , "0"       },
+    {"San Marino"                   ,"SM"              , "378"     , 10        , "00"  },
+    {"S\8bo Tom\8e and Pr\92ncipe"        ,"ST"              , "239"     , 7         , "00"  },
+    {"Saudi Arabia"                 ,"SA"              , "966"     , 9         , "00"  },
+    {"Senegal"                      ,"SN"              , "221"     , 9     , "00"  },
+    {"Serbia"                       ,"RS"              , "381"     , 9     , "00"  },
+    {"Seychelles"                   ,"SC"       , "248"     , 7                , "00"  },
+    {"Sierra Leone"                 ,"SL"              , "232"     , 8     , "00"      },
+    {"Singapore"                    ,"SG"              , "65"      , 8     , "001" },
+    {"Slovakia"                     ,"SK"              , "421"     , 9     , "00"  },
+    {"Slovenia"                     ,"SI"              , "386"     , 8     , "00"      },
+    {"Solomon Islands"              ,"SB"              , "677"     , 7     , "00"      },
+    {"Somalia"                      ,"SO"              , "252"     , 8         , "00"  },
+    {"South Africa"                 ,"ZA"              , "27"      , 9         , "00"  },
+    {"Spain"                        ,"ES"              , "34"      , 9         , "00"  },
+    {"Sri Lanka"                    ,"LK"              , "94"      , 9     , "00"      },
+    {"Sudan"                        ,"SD"              , "249"     , 9         , "00"  },
+    {"Suriname"                     ,"SR"              , "597"     , 7         , "00"  },
+    {"Swaziland"                    ,"SZ"              , "268"     , 8     , "00"  },
+    {"Sweden"                       ,"SE"              , "1"       , 9     , "00"      },
+    {"Switzerland"                  ,"XK"              , "41"      , 9         , "00"  },
+    {"Syria"                        ,"SY"              , "963"     , 9         , "00"  },
+    {"Taiwan"                       ,"TW"              , "886"     , 9         , "810" },
+    {"Tajikistan"                   ,"TJ"              , "992"     , 9     , "002" },
+    {"Tanzania"                     ,"TZ"              , "255"     , 9     , "000" },
+    {"Thailand"                     ,"TH"       , "66"      , 9                , "001" },
+    {"Togo"                         ,"TG"              , "228"     , 8     , "00"      },
+    {"Tokelau"                      ,"TK"              , "690"     , 4     , "00"  },
+    {"Tonga"                        ,"TO"              , "676"     , 5     , "00"  },
+    {"Trinidad and Tobago"                     ,"TT"           , "1"       , 10    , "011"     },
+    {"Tunisia"                      ,"TN"              , "216"     , 8     , "00"      },
+    {"Turkey"                       ,"TR"              , "90"      , 10        , "00"  },
+    {"Turkmenistan"                 ,"TM"              , "993"     , 8         , "00"  },
+    {"Turks and Caicos Islands"            ,"TC"               , "1"       , 7         , "0"   },
+    {"Tuvalu"                       ,"TV"              , "688"     , 5     , "00"      },
+    {"Uganda"                       ,"UG"              , "256"     , 9     , "000" },
+    {"Ukraine"                      ,"UA"              , "380"     , 9         , "00"  },
+    {"United Arab Emirates"            ,"AE"           , "971"     , 9     , "00"  },
+    {"United Kingdom"               ,"UK"              , "44"      , 10        , "00"  },
+    {"United States"                ,"US"              , "1"       , 10        , "011" },
+    {"Uruguay"                      ,"UY"              , "598"     , 8         , "00"  },
+    {"Uzbekistan"                   ,"UZ"              , "998"     , 9         , "8"   },
+    {"Vanuatu"                      ,"VU"              , "678"     , 7     , "00"  },
+    {"Venezuela"                    ,"VE"              , "58"      , 10        , "00"  },
+    {"Vietnam"                      ,"VN"              , "84"      , 9     , "00"  },
+    {"Wallis and Futuna"               ,"WF"           , "681"     , 5         , "00"  },
+    {"Yemen"                        ,"YE"              , "967"     , 9     , "00"  },
+    {"Zambia"                       ,"ZM"              , "260"     , 9     , "00"      },
+    {"Zimbabwe"                     ,"ZW"              , "263"     , 9     , "00"  },
+       {NULL                           ,NULL       ,  ""       , 0     , NULL  }
 };
-
 static dial_plan_t most_common_dialplan={ "generic" ,"", "", 10, "00"};
 
+int linphone_dial_plan_lookup_ccc_from_e164(const char* e164) {
+       dial_plan_t* dial_plan;
+       dial_plan_t* elected_dial_plan=NULL;
+       unsigned int found;
+       unsigned int i=0;
+       if (e164[1]=='1') {
+               /*USA case*/
+               return 1;
+       }
+       do {
+               found=0;
+               i++;
+               for (dial_plan=(dial_plan_t*)dial_plans; dial_plan->country!=NULL; dial_plan++) {
+                       if (strncmp(dial_plan->ccc,&e164[1],i) == 0) {
+                               elected_dial_plan=dial_plan;
+                               found++;
+                       }
+               }
+       } while (found>1 || found==0);
+       if (found==1) {
+               return atoi(elected_dial_plan->ccc);
+       } else {
+               return -1; /*not found */
+       }
+
+}
 int linphone_dial_plan_lookup_ccc_from_iso(const char* iso) {
        dial_plan_t* dial_plan;
        for (dial_plan=(dial_plan_t*)dial_plans; dial_plan->country!=NULL; dial_plan++) {
index b349ad0a4e4efd002dbd701d607415a88c843fff..f46d9a556c9b3f4b78be57fe10cf939ed173f868 100644 (file)
@@ -162,6 +162,10 @@ static bool_t payload_type_equals(const PayloadType *p1, const PayloadType *p2){
        return TRUE;
 }
 
+static bool_t is_recv_only(PayloadType *p){
+       return (p->flags & PAYLOAD_TYPE_FLAG_CAN_RECV) && ! (p->flags & PAYLOAD_TYPE_FLAG_CAN_SEND);
+}
+
 static bool_t payload_list_equals(const MSList *l1, const MSList *l2){
        const MSList *e1,*e2;
        for(e1=l1,e2=l2;e1!=NULL && e2!=NULL; e1=e1->next,e2=e2->next){
@@ -170,6 +174,12 @@ static bool_t payload_list_equals(const MSList *l1, const MSList *l2){
                if (!payload_type_equals(p1,p2))
                        return FALSE;
        }
+       if (e1!=NULL){
+               /*skip possible recv-only payloads*/
+               for(;e1!=NULL && is_recv_only((PayloadType*)e1->data);e1=e1->next){
+                       ms_message("Skipping recv-only payload type...");
+               }
+       }
        if (e1!=NULL || e2!=NULL){
                /*means one list is longer than the other*/
                return FALSE;
@@ -177,32 +187,40 @@ static bool_t payload_list_equals(const MSList *l1, const MSList *l2){
        return TRUE;
 }
 
-bool_t sal_stream_description_equals(const SalStreamDescription *sd1, const SalStreamDescription *sd2){
-       if (sd1->proto!=sd2->proto) return FALSE;
-       if (sd1->type!=sd2->type) return FALSE;
-       if (strcmp(sd1->rtp_addr,sd2->rtp_addr)!=0) return FALSE;
-       if (sd1->rtp_port!=sd2->rtp_port) return FALSE;
-       if (strcmp(sd1->rtcp_addr,sd2->rtcp_addr)!=0) return FALSE;
-       if (sd1->rtcp_port!=sd2->rtcp_port) return FALSE;
-       if (!payload_list_equals(sd1->payloads,sd2->payloads)) return FALSE;
-       if (sd1->bandwidth!=sd2->bandwidth) return FALSE;
-       if (sd1->ptime!=sd2->ptime) return FALSE;
-       /* compare candidates: TODO */
-       if (sd1->dir!=sd2->dir) return FALSE;
-       return TRUE;
+int sal_stream_description_equals(const SalStreamDescription *sd1, const SalStreamDescription *sd2) {
+       int result = SAL_MEDIA_DESCRIPTION_UNCHANGED;
+
+       /* A different proto should result in SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED but the encryption change
+          needs a stream restart for now, so use SAL_MEDIA_DESCRIPTION_CODEC_CHANGED */
+       if (sd1->proto != sd2->proto) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED;
+
+       if (sd1->type != sd2->type) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED;
+       if (strcmp(sd1->rtp_addr, sd2->rtp_addr) != 0) result |= SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED;
+       if (sd1->rtp_port != sd2->rtp_port) {
+               if ((sd1->rtp_port == 0) || (sd2->rtp_port == 0)) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED;
+               else result |= SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED;
+       }
+       if (strcmp(sd1->rtcp_addr, sd2->rtcp_addr) != 0) result |= SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED;
+       if (sd1->rtcp_port != sd2->rtcp_port) result |= SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED;
+       if (!payload_list_equals(sd1->payloads, sd2->payloads)) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED;
+       if (sd1->bandwidth != sd2->bandwidth) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED;
+       if (sd1->ptime != sd2->ptime) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED;
+       if (sd1->dir != sd2->dir) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED;
+
+       return result;
 }
 
-bool_t sal_media_description_equals(const SalMediaDescription *md1, const SalMediaDescription *md2){
+int sal_media_description_equals(const SalMediaDescription *md1, const SalMediaDescription *md2) {
+       int result = SAL_MEDIA_DESCRIPTION_UNCHANGED;
        int i;
-       
-       if (strcmp(md1->addr,md2->addr)!=0) return FALSE;
-       if (md1->nstreams!=md2->nstreams) return FALSE;
-       if (md1->bandwidth!=md2->bandwidth) return FALSE;
-       for(i=0;i<md1->nstreams;++i){
-               if (!sal_stream_description_equals(&md1->streams[i],&md2->streams[i]))
-                       return FALSE;
+
+       if (strcmp(md1->addr, md2->addr) != 0) result |= SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED;
+       if (md1->nstreams != md2->nstreams) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED;
+       if (md1->bandwidth != md2->bandwidth) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED;
+       for(i = 0; i < md1->nstreams; ++i){
+               result |= sal_stream_description_equals(&md1->streams[i], &md2->streams[i]);
        }
-       return TRUE;
+       return result;
 }
 
 static void assign_string(char **str, const char *arg){
index 2913096caf5270b64e97eacf544dc25974f5fb7d..daa59217a28bfc75c592a1c8b2fc0a6500606da1 100644 (file)
@@ -53,6 +53,11 @@ typedef enum {
        SalTransportDTLS /*DTLS*/
 }SalTransport;
 
+#define SAL_MEDIA_DESCRIPTION_UNCHANGED                0x00
+#define SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED  0x01
+#define SAL_MEDIA_DESCRIPTION_CODEC_CHANGED    0x02
+#define SAL_MEDIA_DESCRIPTION_CHANGED          (SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED | SAL_MEDIA_DESCRIPTION_CODEC_CHANGED)
+
 const char* sal_transport_to_string(SalTransport transport);
 SalTransport sal_transport_parse(const char*);
 /* Address manipulation API*/
@@ -183,13 +188,20 @@ typedef struct SalMediaDescription{
        bool_t ice_completed;
 } SalMediaDescription;
 
+typedef struct SalMessage{
+       const char *from;
+       const char *text;
+       const char *url;
+       const char *message_id;
+}SalMessage;
+
 #define SAL_MEDIA_DESCRIPTION_MAX_MESSAGE_ATTRIBUTES 5
 
 SalMediaDescription *sal_media_description_new();
 void sal_media_description_ref(SalMediaDescription *md);
 void sal_media_description_unref(SalMediaDescription *md);
 bool_t sal_media_description_empty(const SalMediaDescription *md);
-bool_t sal_media_description_equals(const SalMediaDescription *md1, const SalMediaDescription *md2);
+int sal_media_description_equals(const SalMediaDescription *md1, const SalMediaDescription *md2);
 bool_t sal_media_description_has_dir(const SalMediaDescription *md, SalStreamDir dir);
 SalStreamDescription *sal_media_description_find_stream(SalMediaDescription *md,
     SalMediaProto proto, SalStreamType type);
@@ -275,8 +287,7 @@ typedef void (*SalOnRegisterFailure)(SalOp *op, SalError error, SalReason reason
 typedef void (*SalOnVfuRequest)(SalOp *op);
 typedef void (*SalOnDtmfReceived)(SalOp *op, char dtmf);
 typedef void (*SalOnRefer)(Sal *sal, SalOp *op, const char *referto);
-typedef void (*SalOnTextReceived)(Sal *sal, const char *from, const char *msg);
-typedef void (*SalOnMessageExternalBodyReceived)(Sal *sal, const char *from, const char *url);
+typedef void (*SalOnTextReceived)(Sal *sal, const SalMessage *msg);
 typedef void (*SalOnTextDeliveryUpdate)(SalOp *op, SalTextDeliveryStatus status);
 typedef void (*SalOnNotify)(SalOp *op, const char *from, const char *event);
 typedef void (*SalOnNotifyRefer)(SalOp *op, SalReferStatus state);
@@ -302,7 +313,6 @@ typedef struct SalCallbacks{
        SalOnDtmfReceived dtmf_received;
        SalOnRefer refer_received;
        SalOnTextReceived text_received;
-       SalOnMessageExternalBodyReceived message_external_body;
        SalOnTextDeliveryUpdate text_delivery_update;
        SalOnNotify notify;
        SalOnNotifyPresence notify_presence;
@@ -346,6 +356,7 @@ void sal_use_one_matching_codec_policy(Sal *ctx, bool_t one_matching_codec);
 void sal_use_rport(Sal *ctx, bool_t use_rports);
 void sal_use_101(Sal *ctx, bool_t use_101);
 void sal_set_root_ca(Sal* ctx, const char* rootCa);
+const char *sal_get_root_ca(Sal* ctx);
 void sal_verify_server_certificates(Sal *ctx, bool_t verify);
 
 int sal_iterate(Sal *sal);
index b5f6cc10f6fbe5b250e8b03f6107a37478cb2285..325e495d33c2abb0b5329d38bb8dade9cc4d7d0d 100644 (file)
@@ -343,8 +343,6 @@ void sal_set_callbacks(Sal *ctx, const SalCallbacks *cbs){
                ctx->callbacks.text_received=(SalOnTextReceived)unimplemented_stub;
        if (ctx->callbacks.ping_reply==NULL)
                ctx->callbacks.ping_reply=(SalOnPingReply)unimplemented_stub;
-       if (ctx->callbacks.message_external_body==NULL)
-               ctx->callbacks.message_external_body=(SalOnMessageExternalBodyReceived)unimplemented_stub;
 }
 
 int sal_unlisten_ports(Sal *ctx){
@@ -415,6 +413,7 @@ int sal_listen_port(Sal *ctx, const char *addr, int port, SalTransport tr, int i
        int dont_use_101 = !ctx->use_101; // Copy char to int to avoid bad alignment
        eXosip_set_option(EXOSIP_OPT_DONT_SEND_101,&dont_use_101);
        sal_set_dscp(ctx,ctx->dscp);
+       sal_use_dates(ctx,ctx->add_dates);
 
        ipv6=strchr(addr,':')!=NULL;
        eXosip_enable_ipv6(ipv6);
@@ -487,6 +486,10 @@ void sal_set_root_ca(Sal* ctx, const char* rootCa) {
        set_tls_options(ctx);
 }
 
+const char *sal_get_root_ca(Sal* ctx) {
+       return ctx->rootCa;
+}
+
 void sal_verify_server_certificates(Sal *ctx, bool_t verify){
        ctx->verify_server_certs=verify;
 #ifdef HAVE_EXOSIP_TLS_VERIFY_CERTIFICATE
@@ -1727,11 +1730,13 @@ static bool_t comes_from_local_if(osip_message_t *msg){
 
 static void text_received(Sal *sal, eXosip_event_t *ev){
        osip_body_t *body=NULL;
-       char *from=NULL,*msg;
+       char *from=NULL,*msg=NULL;
        osip_content_type_t* content_type;
        osip_uri_param_t* external_body_url; 
        char unquoted_external_body_url [256];
        int external_body_size=0;
+       SalMessage salmsg;
+       char message_id[256]={0};
        
        content_type= osip_message_get_content_type(ev->request);
        if (!content_type) {
@@ -1743,14 +1748,14 @@ static void text_received(Sal *sal, eXosip_event_t *ev){
                && strcmp(content_type->type, "text")==0 
                && content_type->subtype
                && strcmp(content_type->subtype, "plain")==0 ) {
-       osip_message_get_body(ev->request,0,&body);
-       if (body==NULL){
-               ms_error("Could not get text message from SIP body");
-               return;
-       }
-       msg=body->body;
-       sal->callbacks.text_received(sal,from,msg);
-       } if (content_type->type 
+               osip_message_get_body(ev->request,0,&body);
+               if (body==NULL){
+                       ms_error("Could not get text message from SIP body");
+                       osip_free(from);
+                       return;
+               }
+               msg=body->body;
+       }else if (content_type->type 
                  && strcmp(content_type->type, "message")==0 
                  && content_type->subtype
                  && strcmp(content_type->subtype, "external-body")==0 ) {
@@ -1761,11 +1766,18 @@ static void text_received(Sal *sal, eXosip_event_t *ev){
                                ,&external_body_url->gvalue[1]
                                ,external_body_size=MIN(strlen(external_body_url->gvalue)-1,sizeof(unquoted_external_body_url)));
                unquoted_external_body_url[external_body_size-1]='\0';
-               sal->callbacks.message_external_body(sal,from,unquoted_external_body_url);
-               
        } else {
                ms_warning("Unsupported content type [%s/%s]",content_type->type,content_type->subtype);
+               osip_free(from);
+               return;
        }
+       snprintf(message_id,sizeof(message_id)-1,"%s%s",ev->request->call_id->number,ev->request->cseq->number);
+       
+       salmsg.from=from;
+       salmsg.text=msg;
+       salmsg.url=external_body_size>0 ? unquoted_external_body_url : NULL;
+       salmsg.message_id=message_id;
+       sal->callbacks.text_received(sal,&salmsg);
        osip_free(from);
 }
 
@@ -1789,7 +1801,7 @@ static void other_request(Sal *sal, eXosip_event_t *ev){
                }else ms_warning("Ignored REFER not coming from this local loopback interface.");
        }else if (strncmp(ev->request->sip_method, "UPDATE", 6) == 0){
                inc_update(sal,ev);
-    }else {
+       }else {
                char *tmp=NULL;
                size_t msglen=0;
                osip_message_to_str(ev->request,&tmp,&msglen);
@@ -2221,11 +2233,21 @@ static void register_set_contact(osip_message_t *msg, const char *contact){
 }
 
 static void sal_register_add_route(osip_message_t *msg, const char *proxy){
-       char tmp[256]={0};
-       snprintf(tmp,sizeof(tmp)-1,"<%s;lr>",proxy);
-       
+       osip_route_t *route;
+
        osip_list_special_free(&msg->routes,(void (*)(void*))osip_route_free);
-       osip_message_set_route(msg,tmp);
+       
+       osip_route_init(&route);
+       if (osip_route_parse(route,proxy)==0){
+               osip_uri_param_t *lr_param = NULL;
+               osip_uri_uparam_get_byname(route->url, "lr", &lr_param);
+               if (lr_param == NULL){
+                       osip_uri_uparam_add(route->url,osip_strdup("lr"),NULL);
+               }
+               osip_list_add(&msg->routes,route,0);
+               return;
+       }
+       osip_route_free(route);
 }
 
 
index 8cf4fb7928a6ab242744005932026d3a0b8b58be..da1f22b6f60187e27d3c11838f0eefce630756a3 100644 (file)
@@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 
 #include "linphonecore.h"
+#include "linphonecore_utils.h"
 
 int main(int argc , char *argv[]){
        LinphoneProxyConfig *cfg;
@@ -35,6 +36,13 @@ int main(int argc , char *argv[]){
        if (argc>3 && strcmp(argv[3],"--escape-plus")==0)
                linphone_proxy_config_set_dial_escape_plus(cfg,TRUE);
        linphone_proxy_config_normalize_number(cfg,argv[1],normalized_number,sizeof(normalized_number));
+
        printf("Normalized number is %s\n",normalized_number);
+       /*check extracted ccc*/
+       if (linphone_dial_plan_lookup_ccc_from_e164(normalized_number) != atoi(linphone_proxy_config_get_dial_prefix(cfg))) {
+               printf("Error ccc [%i] not correctly parsed\n",linphone_dial_plan_lookup_ccc_from_e164(normalized_number));
+       } else {
+               printf("Extracted ccc is [%i] \n",linphone_dial_plan_lookup_ccc_from_e164(normalized_number));
+       }
        return 0;
 }
index 1216b6106a37bad2d90471e73a84c90742a1a0ff..973f7afe66f7268f8ed9c3a5a225ed56136f7641 100644 (file)
@@ -237,8 +237,8 @@ static void linphone_gtk_init_liblinphone(const char *config_file,
        vtable.call_encryption_changed=linphone_gtk_call_encryption_changed;
        vtable.transfer_state_changed=linphone_gtk_transfer_state_changed;
 
-       linphone_core_set_user_agent("Linphone", LINPHONE_VERSION);
        the_core=linphone_core_new(&vtable,config_file,factory_config_file,NULL);
+       linphone_core_set_user_agent(the_core,"Linphone", LINPHONE_VERSION);
        linphone_core_set_waiting_callback(the_core,linphone_gtk_wait,NULL);
        linphone_core_set_zrtp_secrets_file(the_core,secrets_file);
        g_free(secrets_file);
index 61d357da87eb076eeb72be4795761ef5dcbdfc4f..53a6447960fee9b1f094d4ca6349977d2e47c1a6 100644 (file)
     <property name="step_increment">1</property>
     <property name="page_increment">9.9999999995529656</property>
   </object>
-  <object class="GtkAdjustment" id="adjustment_audio_port">
+  <object class="GtkAdjustment" id="adjustment_max_audio_port">
     <property name="upper">65535</property>
     <property name="step_increment">2</property>
     <property name="page_increment">10</property>
   </object>
-  <object class="GtkAdjustment" id="adjustment_tcp_port">
+  <object class="GtkAdjustment" id="adjustment_max_video_port">
     <property name="upper">65535</property>
-    <property name="value">1</property>
-    <property name="step_increment">1</property>
+    <property name="step_increment">2</property>
     <property name="page_increment">10</property>
   </object>
-  <object class="GtkAdjustment" id="adjustment_video_port">
+  <object class="GtkAdjustment" id="adjustment_min_audio_port">
     <property name="upper">65535</property>
     <property name="step_increment">2</property>
     <property name="page_increment">10</property>
   </object>
+  <object class="GtkAdjustment" id="adjustment_min_video_port">
+    <property name="upper">65535</property>
+    <property name="step_increment">2</property>
+    <property name="page_increment">10</property>
+  </object>
+  <object class="GtkAdjustment" id="adjustment_tcp_port">
+    <property name="upper">65535</property>
+    <property name="value">1</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">10</property>
+  </object>
   <object class="GtkListStore" id="liststore1"/>
   <object class="GtkListStore" id="model1">
     <columns>
                                 <child>
                                   <object class="GtkCheckButton" id="mtu_set">
                                     <property name="label" translatable="yes">Set Maximum Transmission Unit:</property>
+                                    <property name="use_action_appearance">False</property>
                                     <property name="visible">True</property>
                                     <property name="can_focus">True</property>
                                     <property name="receives_default">False</property>
-                                    <property name="use_action_appearance">False</property>
                                     <property name="draw_indicator">True</property>
                                     <signal name="toggled" handler="linphone_gtk_mtu_set" swapped="no"/>
                                   </object>
                             <child>
                               <object class="GtkCheckButton" id="dtmf_sipinfo">
                                 <property name="label" translatable="yes">Send DTMFs as SIP info</property>
+                                <property name="use_action_appearance">False</property>
                                 <property name="visible">True</property>
                                 <property name="can_focus">True</property>
                                 <property name="receives_default">False</property>
-                                <property name="use_action_appearance">False</property>
                                 <property name="draw_indicator">True</property>
                                 <signal name="toggled" handler="linphone_gtk_use_sip_info_dtmf_toggled" swapped="no"/>
                               </object>
                             <child>
                               <object class="GtkCheckButton" id="ipv6_enabled">
                                 <property name="label" translatable="yes">Use IPv6 instead of IPv4</property>
+                                <property name="use_action_appearance">False</property>
                                 <property name="visible">True</property>
                                 <property name="can_focus">True</property>
                                 <property name="receives_default">False</property>
                                 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                                <property name="use_action_appearance">False</property>
                                 <property name="draw_indicator">True</property>
                                 <signal name="toggled" handler="linphone_gtk_ipv6_toggled" swapped="no"/>
                               </object>
                             <child>
                               <object class="GtkButton" id="tunnel_edit_button">
                                 <property name="label">gtk-edit</property>
+                                <property name="use_action_appearance">False</property>
                                 <property name="can_focus">True</property>
                                 <property name="receives_default">True</property>
-                                <property name="use_action_appearance">False</property>
                                 <property name="use_stock">True</property>
                                 <signal name="clicked" handler="linphone_gtk_edit_tunnel" swapped="no"/>
                               </object>
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkSpinButton" id="audio_rtp_port">
+                              <object class="GtkLabel" id="label13">
                                 <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="invisible_char">•</property>
-                                <property name="primary_icon_activatable">False</property>
-                                <property name="secondary_icon_activatable">False</property>
-                                <property name="primary_icon_sensitive">True</property>
-                                <property name="secondary_icon_sensitive">True</property>
-                                <property name="adjustment">adjustment_audio_port</property>
-                                <property name="numeric">True</property>
-                                <signal name="value-changed" handler="linphone_gtk_audio_port_changed" swapped="no"/>
+                                <property name="can_focus">False</property>
+                                <property name="label" translatable="yes">DSCP fields</property>
                               </object>
                               <packing>
-                                <property name="left_attach">1</property>
-                                <property name="right_attach">2</property>
-                                <property name="top_attach">1</property>
-                                <property name="bottom_attach">2</property>
+                                <property name="top_attach">4</property>
+                                <property name="bottom_attach">5</property>
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkSpinButton" id="video_rtp_port">
+                              <object class="GtkButton" id="dscp_edit_button">
+                                <property name="label">gtk-edit</property>
+                                <property name="use_action_appearance">False</property>
                                 <property name="visible">True</property>
                                 <property name="can_focus">True</property>
-                                <property name="invisible_char">•</property>
-                                <property name="primary_icon_activatable">False</property>
-                                <property name="secondary_icon_activatable">False</property>
-                                <property name="primary_icon_sensitive">True</property>
-                                <property name="secondary_icon_sensitive">True</property>
-                                <property name="adjustment">adjustment_video_port</property>
-                                <property name="numeric">True</property>
-                                <signal name="value-changed" handler="linphone_gtk_video_port_changed" swapped="no"/>
+                                <property name="receives_default">True</property>
+                                <property name="use_stock">True</property>
+                                <signal name="clicked" handler="linphone_gtk_dscp_edit" swapped="no"/>
                               </object>
                               <packing>
                                 <property name="left_attach">1</property>
                                 <property name="right_attach">2</property>
-                                <property name="top_attach">2</property>
-                                <property name="bottom_attach">3</property>
+                                <property name="top_attach">4</property>
+                                <property name="bottom_attach">5</property>
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkLabel" id="label13">
+                              <object class="GtkHBox" id="hbox6">
                                 <property name="visible">True</property>
                                 <property name="can_focus">False</property>
-                                <property name="label" translatable="yes">DSCP fields</property>
+                                <child>
+                                  <object class="GtkSpinButton" id="audio_min_rtp_port">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="invisible_char">•</property>
+                                    <property name="primary_icon_activatable">False</property>
+                                    <property name="secondary_icon_activatable">False</property>
+                                    <property name="primary_icon_sensitive">True</property>
+                                    <property name="secondary_icon_sensitive">True</property>
+                                    <property name="adjustment">adjustment_min_audio_port</property>
+                                    <property name="numeric">True</property>
+                                    <signal name="value-changed" handler="linphone_gtk_min_audio_port_changed" swapped="no"/>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">True</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkSpinButton" id="audio_max_rtp_port">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="invisible_char">•</property>
+                                    <property name="invisible_char_set">True</property>
+                                    <property name="primary_icon_activatable">False</property>
+                                    <property name="secondary_icon_activatable">False</property>
+                                    <property name="primary_icon_sensitive">True</property>
+                                    <property name="secondary_icon_sensitive">True</property>
+                                    <property name="adjustment">adjustment_max_audio_port</property>
+                                    <property name="numeric">True</property>
+                                    <signal name="value-changed" handler="linphone_gtk_max_audio_port_changed" swapped="no"/>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">True</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkCheckButton" id="fixed_audio_port">
+                                    <property name="label" translatable="yes">Fixed</property>
+                                    <property name="use_action_appearance">False</property>
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="receives_default">False</property>
+                                    <property name="draw_indicator">True</property>
+                                    <signal name="toggled" handler="linphone_gtk_fixed_audio_port_toggle" swapped="no"/>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">True</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">2</property>
+                                  </packing>
+                                </child>
                               </object>
                               <packing>
-                                <property name="top_attach">4</property>
-                                <property name="bottom_attach">5</property>
+                                <property name="left_attach">1</property>
+                                <property name="right_attach">2</property>
+                                <property name="top_attach">1</property>
+                                <property name="bottom_attach">2</property>
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkButton" id="dscp_edit_button">
-                                <property name="label">gtk-edit</property>
+                              <object class="GtkHBox" id="hbox17">
                                 <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="receives_default">True</property>
-                                <property name="use_action_appearance">False</property>
-                                <property name="use_stock">True</property>
-                                <signal name="clicked" handler="linphone_gtk_dscp_edit" swapped="no"/>
+                                <property name="can_focus">False</property>
+                                <child>
+                                  <object class="GtkSpinButton" id="video_min_rtp_port">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="invisible_char">•</property>
+                                    <property name="primary_icon_activatable">False</property>
+                                    <property name="secondary_icon_activatable">False</property>
+                                    <property name="primary_icon_sensitive">True</property>
+                                    <property name="secondary_icon_sensitive">True</property>
+                                    <property name="adjustment">adjustment_min_video_port</property>
+                                    <property name="numeric">True</property>
+                                    <signal name="value-changed" handler="linphone_gtk_min_video_port_changed" swapped="no"/>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">True</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkSpinButton" id="video_max_rtp_port">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="invisible_char">•</property>
+                                    <property name="invisible_char_set">True</property>
+                                    <property name="primary_icon_activatable">False</property>
+                                    <property name="secondary_icon_activatable">False</property>
+                                    <property name="primary_icon_sensitive">True</property>
+                                    <property name="secondary_icon_sensitive">True</property>
+                                    <property name="adjustment">adjustment_max_video_port</property>
+                                    <property name="numeric">True</property>
+                                    <signal name="value-changed" handler="linphone_gtk_max_video_port_changed" swapped="no"/>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">True</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkCheckButton" id="fixed_video_port">
+                                    <property name="label" translatable="yes">Fixed</property>
+                                    <property name="use_action_appearance">False</property>
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="receives_default">False</property>
+                                    <property name="draw_indicator">True</property>
+                                    <signal name="toggled" handler="linphone_gtk_fixed_video_port_toggle" swapped="no"/>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">True</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">2</property>
+                                  </packing>
+                                </child>
                               </object>
                               <packing>
                                 <property name="left_attach">1</property>
                                 <property name="right_attach">2</property>
-                                <property name="top_attach">4</property>
-                                <property name="bottom_attach">5</property>
+                                <property name="top_attach">2</property>
+                                <property name="bottom_attach">3</property>
                               </packing>
                             </child>
                           </object>
                         <child>
                           <object class="GtkRadioButton" id="no_nat">
                             <property name="label" translatable="yes">Direct connection to the Internet</property>
+                            <property name="use_action_appearance">False</property>
                             <property name="visible">True</property>
                             <property name="can_focus">True</property>
                             <property name="receives_default">False</property>
-                            <property name="use_action_appearance">False</property>
                             <property name="active">True</property>
                             <property name="draw_indicator">True</property>
                             <signal name="toggled" handler="linphone_gtk_no_firewall_toggled" swapped="no"/>
                             <child>
                               <object class="GtkRadioButton" id="use_nat_address">
                                 <property name="label" translatable="yes">Behind NAT / Firewall (specify gateway IP below)</property>
+                                <property name="use_action_appearance">False</property>
                                 <property name="visible">True</property>
                                 <property name="can_focus">True</property>
                                 <property name="receives_default">False</property>
-                                <property name="use_action_appearance">False</property>
                                 <property name="active">True</property>
                                 <property name="draw_indicator">True</property>
                                 <property name="group">no_nat</property>
                         <child>
                           <object class="GtkRadioButton" id="use_stun">
                             <property name="label" translatable="yes">Behind NAT / Firewall (use STUN to resolve)</property>
+                            <property name="use_action_appearance">False</property>
                             <property name="visible">True</property>
                             <property name="can_focus">True</property>
                             <property name="receives_default">False</property>
-                            <property name="use_action_appearance">False</property>
                             <property name="draw_indicator">True</property>
                             <property name="group">no_nat</property>
                             <signal name="toggled" handler="linphone_gtk_use_stun_toggled" swapped="no"/>
                         <child>
                           <object class="GtkRadioButton" id="use_ice">
                             <property name="label" translatable="yes">Behind NAT / Firewall (use ICE)</property>
+                            <property name="use_action_appearance">False</property>
                             <property name="visible">True</property>
                             <property name="can_focus">True</property>
                             <property name="receives_default">False</property>
-                            <property name="use_action_appearance">False</property>
                             <property name="draw_indicator">True</property>
                             <property name="group">no_nat</property>
                             <signal name="toggled" handler="linphone_gtk_use_ice_toggled" swapped="no"/>
                             <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                             <property name="n_rows">6</property>
                             <property name="n_columns">2</property>
+                            <child>
+                              <placeholder/>
+                            </child>
                             <child>
                               <object class="GtkHBox" id="ring_sound_box">
                                 <property name="visible">True</property>
                                 <child>
                                   <object class="GtkButton" id="play_ring">
                                     <property name="label">gtk-media-play</property>
+                                    <property name="use_action_appearance">False</property>
                                     <property name="visible">True</property>
                                     <property name="can_focus">True</property>
                                     <property name="receives_default">True</property>
                                     <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                                    <property name="use_action_appearance">False</property>
                                     <property name="use_stock">True</property>
                                     <signal name="clicked" handler="linphone_gtk_play_ring_file" swapped="no"/>
                                   </object>
                             <child>
                               <object class="GtkCheckButton" id="echo_cancelation">
                                 <property name="label" translatable="yes">Enable echo cancellation</property>
+                                <property name="use_action_appearance">False</property>
                                 <property name="visible">True</property>
                                 <property name="can_focus">True</property>
                                 <property name="receives_default">False</property>
-                                <property name="use_action_appearance">False</property>
                                 <property name="draw_indicator">True</property>
                                 <signal name="toggled" handler="linphone_gtk_echo_cancelation_toggled" swapped="no"/>
                               </object>
                                 <property name="bottom_attach">6</property>
                               </packing>
                             </child>
-                            <child>
-                              <placeholder/>
-                            </child>
                           </object>
                         </child>
                       </object>
                                 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                                 <child>
                                   <object class="GtkButton" id="wizard">
+                                    <property name="use_action_appearance">False</property>
                                     <property name="visible">True</property>
                                     <property name="can_focus">True</property>
                                     <property name="receives_default">True</property>
-                                    <property name="use_action_appearance">False</property>
                                     <signal name="clicked" handler="linphone_gtk_display_wizard" swapped="no"/>
                                     <child>
                                       <object class="GtkHBox" id="hbox5">
                                 </child>
                                 <child>
                                   <object class="GtkButton" id="add_proxy">
+                                    <property name="use_action_appearance">False</property>
                                     <property name="visible">True</property>
                                     <property name="can_focus">True</property>
                                     <property name="receives_default">True</property>
                                     <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                                    <property name="use_action_appearance">False</property>
                                     <signal name="clicked" handler="linphone_gtk_add_proxy" swapped="no"/>
                                     <child>
                                       <object class="GtkHBox" id="hbox14">
                                 </child>
                                 <child>
                                   <object class="GtkButton" id="edit_proxy">
+                                    <property name="use_action_appearance">False</property>
                                     <property name="visible">True</property>
                                     <property name="can_focus">True</property>
                                     <property name="receives_default">True</property>
                                     <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                                    <property name="use_action_appearance">False</property>
                                     <signal name="clicked" handler="linphone_gtk_edit_proxy" swapped="no"/>
                                     <child>
                                       <object class="GtkHBox" id="hbox16">
                                 </child>
                                 <child>
                                   <object class="GtkButton" id="remove_proxy">
+                                    <property name="use_action_appearance">False</property>
                                     <property name="visible">True</property>
                                     <property name="can_focus">True</property>
                                     <property name="receives_default">True</property>
                                     <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                                    <property name="use_action_appearance">False</property>
                                     <signal name="clicked" handler="linphone_gtk_remove_proxy" swapped="no"/>
                                     <child>
                                       <object class="GtkHBox" id="hbox7">
                             <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                             <child>
                               <object class="GtkButton" id="erase_passwords">
+                                <property name="use_action_appearance">False</property>
                                 <property name="visible">True</property>
                                 <property name="can_focus">True</property>
                                 <property name="receives_default">True</property>
                                 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                                <property name="use_action_appearance">False</property>
                                 <signal name="clicked" handler="linphone_gtk_clear_passwords" swapped="no"/>
                                 <child>
                                   <object class="GtkHBox" id="hbox18">
                                     <child>
                                       <object class="GtkButton" id="button4">
                                         <property name="label">gtk-go-up</property>
+                                        <property name="use_action_appearance">False</property>
                                         <property name="visible">True</property>
                                         <property name="can_focus">True</property>
                                         <property name="receives_default">True</property>
                                         <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                                        <property name="use_action_appearance">False</property>
                                         <property name="use_stock">True</property>
                                         <signal name="clicked" handler="linphone_gtk_codec_up" swapped="no"/>
                                       </object>
                                     <child>
                                       <object class="GtkButton" id="up_codec">
                                         <property name="label">gtk-go-down</property>
+                                        <property name="use_action_appearance">False</property>
                                         <property name="visible">True</property>
                                         <property name="can_focus">True</property>
                                         <property name="receives_default">True</property>
                                         <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                                        <property name="use_action_appearance">False</property>
                                         <property name="use_stock">True</property>
                                         <signal name="clicked" handler="linphone_gtk_codec_down" swapped="no"/>
                                       </object>
                                     </child>
                                     <child>
                                       <object class="GtkButton" id="enable_codec">
+                                        <property name="use_action_appearance">False</property>
                                         <property name="visible">True</property>
                                         <property name="can_focus">True</property>
                                         <property name="receives_default">True</property>
                                         <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                                        <property name="use_action_appearance">False</property>
                                         <signal name="clicked" handler="linphone_gtk_codec_enable" swapped="no"/>
                                         <child>
                                           <object class="GtkHBox" id="hbox8">
                                     </child>
                                     <child>
                                       <object class="GtkButton" id="disable_codec">
+                                        <property name="use_action_appearance">False</property>
                                         <property name="visible">True</property>
                                         <property name="can_focus">True</property>
                                         <property name="receives_default">True</property>
                                         <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                                        <property name="use_action_appearance">False</property>
                                         <signal name="clicked" handler="linphone_gtk_codec_disable" swapped="no"/>
                                         <child>
                                           <object class="GtkHBox" id="hbox9">
                             <child>
                               <object class="GtkCheckButton" id="adaptive_rate_control">
                                 <property name="label" translatable="yes">Enable adaptive rate control</property>
+                                <property name="use_action_appearance">False</property>
                                 <property name="visible">True</property>
                                 <property name="can_focus">True</property>
                                 <property name="receives_default">False</property>
-                                <property name="use_action_appearance">False</property>
                                 <property name="xalign">0</property>
                                 <property name="draw_indicator">True</property>
                                 <signal name="toggled" handler="linphone_gtk_adaptive_rate_control_toggled" swapped="no"/>
                                 <property name="top_attach">2</property>
                                 <property name="bottom_attach">3</property>
                                 <property name="x_options">GTK_FILL</property>
-                                <property name="y_options"></property>
+                                <property name="y_options"/>
                               </packing>
                             </child>
                           </object>
                         <child>
                           <object class="GtkCheckButton" id="ui_level">
                             <property name="label" translatable="yes">Show advanced settings</property>
+                            <property name="use_action_appearance">False</property>
                             <property name="visible">True</property>
                             <property name="can_focus">True</property>
                             <property name="receives_default">False</property>
-                            <property name="use_action_appearance">False</property>
                             <property name="draw_indicator">True</property>
                             <signal name="toggled" handler="linphone_gtk_ui_level_toggled" swapped="no"/>
                           </object>
             <property name="layout_style">end</property>
             <child>
               <object class="GtkButton" id="button5">
+                <property name="use_action_appearance">False</property>
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
                 <property name="receives_default">True</property>
                 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="use_action_appearance">False</property>
                 <signal name="clicked" handler="linphone_gtk_parameters_closed" swapped="no"/>
                 <child>
                   <object class="GtkHBox" id="hbox3">
index 31c76f93b216b64bd52e5b97472d17cb2ea48ef7..03092a0a5a732e8f3e61bdcf8f2365fbdf3e2913 100644 (file)
@@ -146,14 +146,74 @@ void linphone_gtk_ipv6_toggled(GtkWidget *w){
                                gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)));
 }
 
-void linphone_gtk_audio_port_changed(GtkWidget *w){
-       linphone_core_set_audio_port(linphone_gtk_get_core(),
-                       (gint)gtk_spin_button_get_value(GTK_SPIN_BUTTON(w)));
+void linphone_gtk_min_audio_port_changed(GtkWidget *w){
+       GtkWidget *mw = linphone_gtk_get_main_window();
+       GtkWidget *pb = (GtkWidget *) g_object_get_data(G_OBJECT(mw), "parameters");
+       GtkSpinButton *min_button = GTK_SPIN_BUTTON(w);
+       GtkSpinButton *max_button = GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb, "audio_max_rtp_port"));
+       gboolean fixed = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb, "fixed_audio_port")));
+
+       if (fixed) {
+               linphone_core_set_audio_port(linphone_gtk_get_core(), (gint) gtk_spin_button_get_value(min_button));
+               gtk_spin_button_set_value(max_button, gtk_spin_button_get_value(min_button));
+       } else {
+               gint min_port = gtk_spin_button_get_value(min_button);
+               gint max_port = gtk_spin_button_get_value(max_button);
+               if (min_port > max_port) {
+                       gtk_spin_button_set_value(max_button, min_port);
+                       max_port = min_port;
+               }
+               linphone_core_set_audio_port_range(linphone_gtk_get_core(), min_port, max_port);
+       }
 }
 
-void linphone_gtk_video_port_changed(GtkWidget *w){
-       linphone_core_set_video_port(linphone_gtk_get_core(),
-                       (gint)gtk_spin_button_get_value(GTK_SPIN_BUTTON(w)));
+void linphone_gtk_max_audio_port_changed(GtkWidget *w){
+       GtkWidget *mw = linphone_gtk_get_main_window();
+       GtkWidget *pb = (GtkWidget *) g_object_get_data(G_OBJECT(mw), "parameters");
+       GtkSpinButton *min_button = GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb, "audio_min_rtp_port"));
+       GtkSpinButton *max_button = GTK_SPIN_BUTTON(w);
+       gint min_port = gtk_spin_button_get_value(min_button);
+       gint max_port = gtk_spin_button_get_value(max_button);
+       if (max_port < min_port) {
+               gtk_spin_button_set_value(min_button, max_port);
+               min_port = max_port;
+       }
+       linphone_core_set_audio_port_range(linphone_gtk_get_core(), min_port, max_port);
+}
+
+void linphone_gtk_min_video_port_changed(GtkWidget *w){
+       GtkWidget *mw = linphone_gtk_get_main_window();
+       GtkWidget *pb = (GtkWidget *) g_object_get_data(G_OBJECT(mw), "parameters");
+       GtkSpinButton *min_button = GTK_SPIN_BUTTON(w);
+       GtkSpinButton *max_button = GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb, "video_max_rtp_port"));
+       gboolean fixed = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb, "fixed_video_port")));
+
+       if (fixed) {
+               linphone_core_set_video_port(linphone_gtk_get_core(), (gint) gtk_spin_button_get_value(min_button));
+               gtk_spin_button_set_value(max_button, gtk_spin_button_get_value(min_button));
+       } else {
+               gint min_port = gtk_spin_button_get_value(min_button);
+               gint max_port = gtk_spin_button_get_value(max_button);
+               if (min_port > max_port) {
+                       gtk_spin_button_set_value(max_button, min_port);
+                       max_port = min_port;
+               }
+               linphone_core_set_video_port_range(linphone_gtk_get_core(), min_port, max_port);
+       }
+}
+
+void linphone_gtk_max_video_port_changed(GtkWidget *w){
+       GtkWidget *mw = linphone_gtk_get_main_window();
+       GtkWidget *pb = (GtkWidget *) g_object_get_data(G_OBJECT(mw), "parameters");
+       GtkSpinButton *min_button = GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb, "video_min_rtp_port"));
+       GtkSpinButton *max_button = GTK_SPIN_BUTTON(w);
+       gint min_port = gtk_spin_button_get_value(min_button);
+       gint max_port = gtk_spin_button_get_value(max_button);
+       if (max_port < min_port) {
+               gtk_spin_button_set_value(min_button, max_port);
+               min_port = max_port;
+       }
+       linphone_core_set_video_port_range(linphone_gtk_get_core(), min_port, max_port);
 }
 
 void linphone_gtk_no_firewall_toggled(GtkWidget *w){
@@ -877,6 +937,7 @@ static void linphone_gtk_show_media_encryption(GtkWidget *pb){
 
 void linphone_gtk_parameters_destroyed(GtkWidget *pb){
        GtkWidget *mw=linphone_gtk_get_main_window();
+       ms_error("linphone_gtk_paramters_destroyed");
        g_object_set_data(G_OBJECT(mw),"parameters",NULL);
 }
 
@@ -908,12 +969,15 @@ void linphone_gtk_show_parameters(void){
        int mtu;
        int ui_advanced;
        LCSipTransports tr;
+       int min_port = 0, max_port = 0;
 
        if (pb==NULL) {
                pb=linphone_gtk_create_window("parameters");
                g_object_set_data(G_OBJECT(mw),"parameters",pb);
+               ms_error("linphone_gtk_show_paramters: create");
        }else {
                gtk_widget_show(pb);
+               ms_error("linphone_gtk_show_parameters: show");
                return;
        }
        codec_list=linphone_gtk_get_widget(pb,"codec_list");
@@ -939,10 +1003,20 @@ void linphone_gtk_show_parameters(void){
                                tr.udp_port);
     }
 
-       gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb,"audio_rtp_port")),
-                               linphone_core_get_audio_port(lc));
-       gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb,"video_rtp_port")),
-                               linphone_core_get_video_port(lc));
+       linphone_core_get_audio_port_range(lc, &min_port, &max_port);
+       gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb, "audio_min_rtp_port")), min_port);
+       gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb, "audio_max_rtp_port")), max_port);
+       if (min_port == max_port) {
+               gtk_widget_set_sensitive(GTK_WIDGET(linphone_gtk_get_widget(pb, "audio_max_rtp_port")), FALSE);
+               gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb, "fixed_audio_port")), TRUE);
+       }
+       linphone_core_get_video_port_range(lc, &min_port, &max_port);
+       gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb, "video_min_rtp_port")), min_port);
+       gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb, "video_max_rtp_port")), max_port);
+       if (min_port == max_port) {
+               gtk_widget_set_sensitive(GTK_WIDGET(linphone_gtk_get_widget(pb, "video_max_rtp_port")), FALSE);
+               gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb, "fixed_video_port")), TRUE);
+       }
 
        linphone_gtk_show_media_encryption(pb);
        
@@ -1032,6 +1106,36 @@ void linphone_gtk_show_parameters(void){
 }
 
 
+void linphone_gtk_fixed_audio_port_toggle(void) {
+       GtkWidget *mw = linphone_gtk_get_main_window();
+       GtkWidget *pb = (GtkWidget *) g_object_get_data(G_OBJECT(mw), "parameters");
+       gboolean fixed = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb, "fixed_audio_port")));
+       gint min_port = gtk_spin_button_get_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb, "audio_min_rtp_port")));
+       gint max_port = gtk_spin_button_get_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb, "audio_max_rtp_port")));
+       gtk_widget_set_sensitive(GTK_WIDGET(linphone_gtk_get_widget(pb, "audio_max_rtp_port")), !fixed);
+       if (fixed) {
+               linphone_core_set_audio_port(linphone_gtk_get_core(), min_port);
+       } else {
+               linphone_core_set_audio_port_range(linphone_gtk_get_core(), min_port, max_port);
+       }
+}
+
+
+void linphone_gtk_fixed_video_port_toggle(void) {
+       GtkWidget *mw = linphone_gtk_get_main_window();
+       GtkWidget *pb = (GtkWidget *) g_object_get_data(G_OBJECT(mw), "parameters");
+       gboolean fixed = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb, "fixed_video_port")));
+       gint min_port = gtk_spin_button_get_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb, "video_min_rtp_port")));
+       gint max_port = gtk_spin_button_get_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb, "video_max_rtp_port")));
+       gtk_widget_set_sensitive(GTK_WIDGET(linphone_gtk_get_widget(pb, "video_max_rtp_port")), !fixed);
+       if (fixed) {
+               linphone_core_set_video_port(linphone_gtk_get_core(), min_port);
+       } else {
+               linphone_core_set_video_port_range(linphone_gtk_get_core(), min_port, max_port);
+       }
+}
+
+
 void linphone_gtk_edit_tunnel_closed(GtkWidget *button){
         GtkWidget *pb=gtk_widget_get_toplevel(button);
         gtk_widget_destroy(pb);
index 35e173d5a802d1a454b827780f3aca081285e475..ac7b14d8de497885bfe3e8ad11e1ba2cdcbe994d 100644 (file)
@@ -32,7 +32,7 @@ public interface LinphoneCall {
         */
        static class State {
                
-               static private Vector values = new Vector();
+               static private Vector<State> values = new Vector<State>();
                private final int mValue;
                public final int value() {return mValue;}
                
@@ -268,6 +268,11 @@ public interface LinphoneCall {
        boolean isInConference();
        
        float getPlayVolume();
+
+       /**
+        * Obtain the remote user agent string. 
+        */
+       String getRemoteUserAgent();
        
        /**
         * Take a photo of currently received video and write it into a jpeg file.
index 1abdb7bed9acbcf3dbfb57d00b33942956276c92..2e839234fd2828c9ce79a07848486bdaa611364b 100644 (file)
@@ -32,13 +32,13 @@ public interface LinphoneCallLog {
         */
        static class CallStatus {
                
-               static private Vector values = new Vector();
+               static private Vector<CallStatus> values = new Vector<CallStatus>();
                private final int mValue;
                private final String mStringValue;
                /**
                 * Call success.
                 */
-               public final static CallStatus Sucess = new CallStatus(0,"Sucess");
+               public final static CallStatus Success = new CallStatus(0,"Sucess");
                /**
                 * Call aborted.
                 */
@@ -100,6 +100,11 @@ public interface LinphoneCallLog {
         */
        public String getStartDate();
        
+       /**
+        * @return a timestamp of the start date/time of the call in milliseconds since January 1st 1970
+        */
+       public long getTimestamp();
+       
        /**
         * @return the call duration, in seconds
         */
index 2dd497c9c346f4cf511a6d1448181ee24c3b0cdb..730a99dc2c8fe430d5ffef38eda721cb45fa8142 100644 (file)
@@ -57,4 +57,12 @@ public interface LinphoneCallParams {
         * @return PayloadType or null
         */
        PayloadType getUsedVideoCodec();
+       
+       /**
+        * Indicate low bandwith mode. 
+        * Configuring a call to low bandwidth mode will result in the core to activate several settings for the call in order to ensure that bitrate usage
+        * is lowered to the minimum possible. Typically, ptime (packetization time) will be increased, audio codec's output bitrate will be targetted to 20kbit/s provided
+        * that it is achievable by the codec selected after SDP handshake. Video is automatically disabled.
+       **/
+       void enableLowBandwidth(boolean enable);
 }
index 15b4cfb3462d593152f9de6e2ee28eda8ed835f5..f1248c445540e0ae070ef99ce153a7e5a9dd7ba1 100644 (file)
@@ -23,7 +23,7 @@ import java.util.Vector;
 
 public interface LinphoneCallStats {
        static public class MediaType {
-               static private Vector values = new Vector();
+               static private Vector<MediaType> values = new Vector<MediaType>();
                /**
                 * Audio
                 */
@@ -52,7 +52,7 @@ public interface LinphoneCallStats {
                }
        }
        static public class IceState {
-               static private Vector values = new Vector();
+               static private Vector<IceState> values = new Vector<IceState>();
                /**
                 * Not activated
                 */
index db75f91165ca5391f07076e1b8c5cee47ff87666..d403d94bdb0ddfb5b349bd376c8a616232a71b36 100644 (file)
@@ -7,9 +7,8 @@ public interface LinphoneChatMessage {
        interface StateListener{
                void onLinphoneChatMessageStateChanged(LinphoneChatMessage msg, State state);
        }
-       static class State {
-               @SuppressWarnings("rawtypes")
-               static private Vector values = new Vector();
+       public static class State {
+               static private Vector<State> values = new Vector<State>();
                private final int mValue;
                public final int value() {return mValue;}
                
@@ -31,7 +30,6 @@ public interface LinphoneChatMessage {
                 */
                public final static State NotDelivered = new State(3,"NotDelivered");
                
-               @SuppressWarnings("unchecked")
                private State(int value,String stringValue) {
                        mValue = value;
                        values.addElement(this);
index 562ae86cdf0884696955b7a76c6c2ddb99cd13d9..8815085d03d86f86321a35a07dcdb95188df2efb 100644 (file)
@@ -31,7 +31,7 @@ public interface LinphoneCore {
         */
        static public class GlobalState {
                
-               static private Vector values = new Vector();
+               static private Vector<GlobalState> values = new Vector<GlobalState>();
                /**
                 * Off
                 */
@@ -76,7 +76,7 @@ public interface LinphoneCore {
         */
        static public class RegistrationState {
                
-               private static Vector values = new Vector();
+               private static Vector<RegistrationState> values = new Vector<RegistrationState>();
                /**
                 * None
                 */
@@ -124,7 +124,7 @@ public interface LinphoneCore {
         */
        static public class FirewallPolicy {
                
-               static private Vector values = new Vector();
+               static private Vector<FirewallPolicy> values = new Vector<FirewallPolicy>();
                /**
                 * No firewall is assumed.
                 */
@@ -189,21 +189,21 @@ public interface LinphoneCore {
         * Media (RTP) encryption enum-like.
         *
         */
-       static public class MediaEncryption {
+       static public final class MediaEncryption {
                
-               static private Vector values = new Vector();
+               static private Vector<MediaEncryption> values = new Vector<MediaEncryption>();
                /**
                 * None
                 */
-               static public MediaEncryption None = new MediaEncryption(0,"None");       
+               static public final MediaEncryption None = new MediaEncryption(0,"None");       
                /**
                 * SRTP
                 */
-               static public MediaEncryption SRTP = new MediaEncryption(1,"SRTP");
+               static public final MediaEncryption SRTP = new MediaEncryption(1,"SRTP");
                /**
                 * ZRTP
                 */
-               static public MediaEncryption ZRTP = new MediaEncryption(2,"ZRTP");
+               static public final MediaEncryption ZRTP = new MediaEncryption(2,"ZRTP");
                protected final int mValue;
                private final String mStringValue;
 
@@ -230,7 +230,7 @@ public interface LinphoneCore {
         */
        static public class EcCalibratorStatus {
                
-               static private Vector values = new Vector();
+               static private Vector<EcCalibratorStatus> values = new Vector<EcCalibratorStatus>();
                /* Do not change the values of these constants or the strings associated with them to prevent breaking
                   the collection of echo canceller calibration results during the wizard! */
                public static final int IN_PROGRESS_STATUS=0;
@@ -278,6 +278,12 @@ public interface LinphoneCore {
                        return mValue;
                }
        }
+
+       /**
+        * Set the context of creation of the LinphoneCore.
+        */
+       public void setContext(Object context);
+
        /**
         * clear all added proxy configs
         */
@@ -417,7 +423,9 @@ public interface LinphoneCore {
         * @throws LinphoneCoreException 
         */
        public void deferCallUpdate(LinphoneCall aCall) throws LinphoneCoreException;
-       
+
+       public void startRinging();
+
        /**
         * @return a list of LinphoneCallLog 
         */
@@ -472,7 +480,7 @@ public interface LinphoneCore {
         * @return true is mic is muted
         */
        boolean isMicMuted();
-       
+
        /**
         * Initiate a dtmf signal if in call
         * @param number
@@ -524,7 +532,7 @@ public interface LinphoneCore {
         */
        boolean isEchoCancellationEnabled();
        /**
-        * Get echo limiter status (another method of doing echo suppressionn, more brute force)
+        * Get echo limiter status (another method of doing echo suppression, more brute force)
         * @return true if echo limiter is enabled
         */
        boolean isEchoLimiterEnabled();
@@ -537,13 +545,13 @@ public interface LinphoneCore {
         */
        Transports getSignalingTransportPorts();
        /**
-        * not implemented
+        * Activates or deactivates the speaker.
         * @param value
         */
        void enableSpeaker(boolean value);
        /**
-        * not implemented
-        * @return
+        * Tells whether the speaker is activated.
+        * @return true if speaker enabled, false otherwise
         */
        boolean isSpeakerEnabled();
        /**
@@ -843,4 +851,27 @@ public interface LinphoneCore {
         * automatically declined.
        **/
        void setIncomingTimeout(int timeout);
+       
+       /**
+        * Set the call timeout in seconds.
+        * Once this time is elapsed (ringing included), the call is automatically hung up.
+       **/
+       void setInCallTimeout(int timeout);
+       
+       void setMicrophoneGain(float gain);
+       
+       /**
+        * Set username and display name to use if no LinphoneProxyConfig configured
+        */
+       void setPrimaryContact(String displayName, String username);
+       
+       /**
+        * Enable/Disable the use of SIP INFO for DTMFs
+        */
+       void setUseSipInfoForDtmfs(boolean use);
+       
+       /**
+        * Enable/Disable the use of inband DTMFs
+        */
+       void setUseRfc2833ForDtmfs(boolean use);
 }
index fe35b257fde05a9449a1ee4a0cd7617aa104ebd3..04cef4aea24b3bf709e3aa5feef01e11b80fe6da 100644 (file)
@@ -40,7 +40,7 @@ abstract public class LinphoneCoreFactory {
        public static final synchronized LinphoneCoreFactory instance() {
                try {
                        if (theLinphoneCoreFactory == null) {
-                               Class lFactoryClass = Class.forName(factoryName);
+                               Class<?> lFactoryClass = Class.forName(factoryName);
                                theLinphoneCoreFactory = (LinphoneCoreFactory) lFactoryClass.newInstance();
                        }
                } catch (Exception e) {
index e070f69214154bb6297ce2e65f29b463e0d4cdb8..417c582d905f77d6529caa61261f489cb919606d 100644 (file)
@@ -37,7 +37,7 @@ public interface LinphoneFriend {
        static class SubscribePolicy {
 
                
-               static private Vector values = new Vector();
+               static private Vector<SubscribePolicy> values = new Vector<SubscribePolicy>();
                protected final int mValue;
                private final String mStringValue;
                /**
index a1b36ab37e0290cd54daca3e75d69beb7437fe1b..08108417114721bb2fadd07d3cf6262b90af43a0 100644 (file)
@@ -28,7 +28,7 @@ import java.util.Vector;
 
 public class OnlineStatus {
        
-       static private Vector values = new Vector();
+       static private Vector<OnlineStatus> values = new Vector<OnlineStatus>();
        /**
         * Offline
         */
index 952da57d2fe49bca6978b2d0ffa6114f0b06f493..648d774651e69cce992f232a050a0968554fa07d 100644 (file)
@@ -21,4 +21,6 @@ package org.linphone.core;
 public interface PayloadType {
 
        String getMime();
+       
+       int getRate();
 }
index 7e39cebc76663575642ae2de252421ffbf350b40..6a91438acf4ea8aaf80f3a4849fabae80bc8126d 100644 (file)
@@ -174,6 +174,11 @@ class LinphoneCallImpl implements LinphoneCall {
        public float getPlayVolume() {
                return getPlayVolume(nativePtr);
        }
+
+       private native String getRemoteUserAgent(long nativePtr);
+       public String getRemoteUserAgent() {
+               return getRemoteUserAgent(nativePtr);
+       }
        
        private native void takeSnapshot(long nativePtr, String path);
        public void takeSnapshot(String path) {
index 05468626ebc22a3f4cb80d282ae4b1baf2ea58ac..2419d74b3a50da0218e72846892b236202876348 100644 (file)
@@ -30,6 +30,7 @@ class LinphoneCallLogImpl implements LinphoneCallLog {
        private native String getStartDate(long nativePtr);
        private native int getCallDuration(long nativePtr);
        private native int getCallId(long nativePtr);
+       private native long getTimestamp(long nativePtr);
        
        LinphoneCallLogImpl(long aNativePtr)  {
                nativePtr = aNativePtr;
@@ -64,4 +65,8 @@ class LinphoneCallLogImpl implements LinphoneCallLog {
        public int getCallId() {
                return getCallId(nativePtr);
        }
+       
+       public long getTimestamp() {
+               return getTimestamp(nativePtr) * 1000;  // Need milliseconds, not seconds
+       }
 }
index 3c4514017b268ee8363d4e2cc746ed194efc47cf..be3495a8dda6cdfcd2afc1058013feb642d7fc49 100644 (file)
@@ -35,7 +35,7 @@ public class LinphoneCallParamsImpl implements LinphoneCallParams {
        private native long getUsedAudioCodec(long nativePtr);
        private native long getUsedVideoCodec(long nativePtr);
        private native void destroy(long nativePtr);
-       
+       private native void enableLowBandwidth(long nativePtr, boolean enable);
        
        public boolean getVideoEnabled() {
                return getVideoEnabled(nativePtr);
@@ -79,4 +79,8 @@ public class LinphoneCallParamsImpl implements LinphoneCallParams {
        public boolean localConferenceMode() {
                return localConferenceMode(nativePtr);
        }
+       
+       public void enableLowBandwidth(boolean enable) {
+               enableLowBandwidth(nativePtr, enable);
+       }
 }
index 6059915eaf8ad0c2a88f1b074a2b1afdae91bba9..83f6d20d38062941efb25be4792760f9ec65fa33 100644 (file)
@@ -18,14 +18,25 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
 package org.linphone.core;
 
+import static android.media.AudioManager.MODE_IN_CALL;
+import static android.media.AudioManager.MODE_RINGTONE;
+import android.content.Context;
+import android.media.AudioManager;
+
 import java.io.File;
 import java.io.IOException;
 
+import org.linphone.core.LinphoneCall.State;
+import org.linphone.mediastream.video.capture.hwconf.Hacks;
+
 
 class LinphoneCoreImpl implements LinphoneCore {
 
        private final  LinphoneCoreListener mListener; //to make sure to keep a reference on this object
        private long nativePtr = 0;
+       private Context mContext = null;
+       private AudioManager mAudioManager = null;
+       private boolean mSpeakerEnabled = false;
        private native long newLinphoneCore(LinphoneCoreListener listener,String userConfig,String factoryConfig,Object  userdata);
        private native void iterate(long nativePtr);
        private native long getDefaultProxyConfig(long nativePtr);
@@ -115,6 +126,8 @@ class LinphoneCoreImpl implements LinphoneCore {
        private native void setAudioPortRange(long nativePtr, int minPort, int maxPort);
        private native void setVideoPortRange(long nativePtr, int minPort, int maxPort);
        private native void setIncomingTimeout(long nativePtr, int timeout);
+       private native void setInCallTimeout(long nativePtr, int timeout);
+       private native void setPrimaryContact(long nativePtr, String displayName, String username);
        
        LinphoneCoreImpl(LinphoneCoreListener listener, File userConfig,File factoryConfig,Object  userdata) throws IOException {
                mListener=listener;
@@ -128,14 +141,24 @@ class LinphoneCoreImpl implements LinphoneCore {
        protected void finalize() throws Throwable {
                
        }
-       
+
+       private boolean contextInitialized() {
+               if (mContext == null) {
+                       Log.e("Context of LinphoneCore has not been initialized, call setContext() after creating LinphoneCore.");
+                       return false;
+               }
+               return true;
+       }
+       public void setContext(Object context) {
+               mContext = (Context)context;
+               mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+       }
+
        public synchronized void addAuthInfo(LinphoneAuthInfo info) {
                isValid();
                addAuthInfo(nativePtr,((LinphoneAuthInfoImpl)info).nativePtr);
        }
 
-
-
        public synchronized LinphoneProxyConfig getDefaultProxyConfig() {
                isValid();
                long lNativePtr = getDefaultProxyConfig(nativePtr);
@@ -199,7 +222,6 @@ class LinphoneCoreImpl implements LinphoneCore {
        public synchronized void acceptCall(LinphoneCall aCall) {
                isValid();
                acceptCall(nativePtr,((LinphoneCallImpl)aCall).nativePtr);
-               
        }
        public synchronized LinphoneCallLog[] getCallLogs() {
                isValid();
@@ -233,6 +255,7 @@ class LinphoneCoreImpl implements LinphoneCore {
        public synchronized void muteMic(boolean isMuted) {
                muteMic(nativePtr,isMuted);
        }
+
        public synchronized LinphoneAddress interpretUrl(String destination) throws LinphoneCoreException {
                long lAddress = interpretUrl(nativePtr,destination);
                if (lAddress != 0) {
@@ -299,13 +322,37 @@ class LinphoneCoreImpl implements LinphoneCore {
                // TODO Auto-generated method stub
                
        }
+
+       private void applyAudioHacks() {
+               if (Hacks.needGalaxySAudioHack()) {
+                       /* The microphone gain is way too high on the Galaxy S so correct it here. */
+                       setMicrophoneGain(-9.0f);
+               }
+       }
+       private void setAudioModeIncallForGalaxyS() {
+               if (!contextInitialized()) return;
+               mAudioManager.setMode(MODE_IN_CALL);
+       }
+       public void routeAudioToSpeakerHelper(boolean speakerOn) {
+               if (!contextInitialized()) return;
+               if (Hacks.needGalaxySAudioHack())
+                       setAudioModeIncallForGalaxyS();
+               mAudioManager.setSpeakerphoneOn(speakerOn);
+       }
+       private native void forceSpeakerState(long nativePtr, boolean speakerOn);
        public void enableSpeaker(boolean value) {
-               // TODO Auto-generated method stub
-               
+               final LinphoneCall call = getCurrentCall();
+               mSpeakerEnabled = value;
+               applyAudioHacks();
+               if (call != null && call.getState() == State.StreamsRunning && Hacks.needGalaxySAudioHack()) {
+                       Log.d("Hack to have speaker=", value, " while on call");
+                       forceSpeakerState(nativePtr, value);
+               } else {
+                       routeAudioToSpeakerHelper(value);
+               }
        }
        public boolean isSpeakerEnabled() {
-               // TODO Auto-generated method stub
-               return false;
+               return mSpeakerEnabled;
        }
        public synchronized void playDtmf(char number, int duration) {
                playDtmf(nativePtr,number, duration);
@@ -695,6 +742,13 @@ class LinphoneCoreImpl implements LinphoneCore {
                        throws LinphoneCoreException {
                deferCallUpdate(nativePtr, getCallPtr(aCall));
        }
+
+       public synchronized void startRinging() {
+               if (!contextInitialized()) return;
+               if (Hacks.needGalaxySAudioHack()) {
+                       mAudioManager.setMode(MODE_RINGTONE);
+               }
+       }
        
        private native void setVideoPolicy(long nativePtr, boolean autoInitiate, boolean autoAccept);
        public synchronized void setVideoPolicy(boolean autoInitiate, boolean autoAccept) {
@@ -744,7 +798,7 @@ class LinphoneCoreImpl implements LinphoneCore {
        
        @Override
        public PayloadType findPayloadType(String mime, int clockRate) {
-               return null;
+               return findPayloadType(mime, clockRate, 1);
        }
        
        private native void removeFriend(long ptr, long lf);
@@ -782,4 +836,28 @@ class LinphoneCoreImpl implements LinphoneCore {
        public void setIncomingTimeout(int timeout) {
                setIncomingTimeout(nativePtr, timeout);
        }
+       
+       public void setInCallTimeout(int timeout)
+       {
+               setInCallTimeout(nativePtr, timeout);
+       }
+       
+       private native void setMicrophoneGain(long ptr, float gain);
+       public void setMicrophoneGain(float gain) {
+               setMicrophoneGain(nativePtr, gain);
+       }
+       
+       public void setPrimaryContact(String displayName, String username) {
+               setPrimaryContact(nativePtr, displayName, username);
+       }
+       
+       private native void setUseSipInfoForDtmfs(long ptr, boolean use);
+       public void setUseSipInfoForDtmfs(boolean use) {
+               setUseSipInfoForDtmfs(nativePtr, use);
+       }
+       
+       private native void setUseRfc2833ForDtmfs(long ptr, boolean use);
+       public void setUseRfc2833ForDtmfs(boolean use) {
+               setUseRfc2833ForDtmfs(nativePtr, use);
+       }
 }
index 562029e7ca05c02daed7a983915f6ca2bea4e2bc..804180768639712e06d3481edac7f6c78649f0af 100644 (file)
@@ -1,2 +1,41 @@
-EXTRA_DIST= $(shell cd $(srcdir) && ls *.m4)
-
+EXTRA_DIST=\
+       codeset.m4 \
+       exosip.m4  \
+       gettext.m4 \
+       glibc2.m4 \
+       glibc21.m4 \
+       iconv.m4 \
+       ilbc.m4 \
+       intdiv0.m4 \
+       intl.m4 \
+       intldir.m4 \
+       intmax.m4 \
+       inttypes-pri.m4 \
+       inttypes.m4 \
+       inttypes_h.m4 \
+       isc-posix.m4 \
+       lcmessage.m4 \
+       lib-ld.m4 \
+       lib-link.m4 \
+       lib-prefix.m4 \
+       lock.m4 \
+       longdouble.m4 \
+       longlong.m4 \
+       nls.m4 \
+       obsolete.m4 \
+       ortp.m4 \
+       osip.m4 \
+       po.m4 \
+       printf-posix.m4 \
+       progtest.m4 \
+       readline.m4 \
+       signed.m4 \
+       size_max.m4 \
+       stdint_h.m4 \
+       uintmax_t.m4 \
+       ulonglong.m4 \
+       video.m4 \
+       visibility.m4 \
+       wchar_t.m4 \
+       wint_t.m4 \
+       xsize.m4
index dcefb118c703176d135dba3e294cf1eb086e75f7..3906a1732a20bda648a0794072e341da5d230308 100644 (file)
@@ -25,7 +25,7 @@ dnl            USE_INCLUDED_LIBINTL, BUILD_INCLUDED_LIBINTL.
 AC_DEFUN([AM_INTL_SUBDIR],
 [
   AC_REQUIRE([AC_PROG_INSTALL])dnl
-  AC_REQUIRE([AM_PROG_MKDIR_P])dnl defined by automake
+  AC_REQUIRE([AC_PROG_MKDIR_P])dnl
   AC_REQUIRE([AC_PROG_CC])dnl
   AC_REQUIRE([AC_CANONICAL_HOST])dnl
   AC_REQUIRE([gt_GLIBC2])dnl
diff --git a/m4/obsolete.m4 b/m4/obsolete.m4
new file mode 100644 (file)
index 0000000..a5d2cbd
--- /dev/null
@@ -0,0 +1 @@
+AC_DEFUN([AM_PROG_MKDIR_P], [AC_PROG_MKDIR_P([$@])])
index 00133ef36f83c91ec47b1e2ca721d542fdabf9d4..d16320c561ea65c334c12f1a8f53944eb92c4059 100644 (file)
--- a/m4/po.m4
+++ b/m4/po.m4
@@ -24,7 +24,7 @@ AC_DEFUN([AM_PO_SUBDIRS],
 [
   AC_REQUIRE([AC_PROG_MAKE_SET])dnl
   AC_REQUIRE([AC_PROG_INSTALL])dnl
-  AC_REQUIRE([AM_PROG_MKDIR_P])dnl defined by automake
+  AC_REQUIRE([AC_PROG_MKDIR_P])dnl
   AC_REQUIRE([AM_NLS])dnl
 
   dnl Perform the following tests also if --disable-nls has been given,
index 23c75b19523c172c97ba89c76cf7672fc804b14a..bd15866cec3c7b74b359e7a22598c017baf7043e 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 23c75b19523c172c97ba89c76cf7672fc804b14a
+Subproject commit bd15866cec3c7b74b359e7a22598c017baf7043e
diff --git a/oRTP b/oRTP
index ddc4f7d041967305483761fc9c643d3bb290a5f1..59ff6bb7a0c5047526b802d264f6db4faa2bd5c2 160000 (submodule)
--- a/oRTP
+++ b/oRTP
@@ -1 +1 @@
-Subproject commit ddc4f7d041967305483761fc9c643d3bb290a5f1
+Subproject commit 59ff6bb7a0c5047526b802d264f6db4faa2bd5c2
index 2f551f53d4c371ecdd18d13ce851c37b508c3543..83c3a934e295d593c0dac9b0404ccef6de5760aa 100644 (file)
@@ -1,5 +1,5 @@
 
-SUBDIRS=C fr it ja cs
+SUBDIRS=C fr it ja cs xml
 
 LINPHONE_SOUNDS=ringback.wav hello8000.wav hello16000.wav
 LINPHONE_RINGS=rings/orig.wav \
index 47c01785f297a6ba8b88f76c73e0fedb75d41d8e..3bc5cf04de134a016c0027e71149d068f8b4fe56 100644 (file)
@@ -14,7 +14,7 @@ $(linphone_help)/manual.html:
        sgmltools $(srcdir)/manual.sgml
 
 install-data-local:
-                       $(mkdir_p) $(DESTDIR)$(linphone_manualdir)
+                       $(MKDIR_P) $(DESTDIR)$(linphone_manualdir)
                        -cp -f $(linphone_help)/*.html $(DESTDIR)/$(linphone_manualdir)/.
                        -cp -f $(linphone_help)/*.css $(DESTDIR)/$(linphone_manualdir)/.
 
diff --git a/share/xml/Makefile.am b/share/xml/Makefile.am
new file mode 100644 (file)
index 0000000..c553a5c
--- /dev/null
@@ -0,0 +1 @@
+EXTRA_DIST=lpconfig.xsd
diff --git a/share/xml/lpconfig.xsd b/share/xml/lpconfig.xsd
new file mode 100644 (file)
index 0000000..49bb561
--- /dev/null
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
+               targetNamespace="http://www.linphone.org/xsds/lpconfig.xsd" 
+               xmlns:tns="http://www.linphone.org/xsds/lpconfig.xsd" 
+               elementFormDefault="qualified">
+
+    <xs:element name="config" type="tns:LPConfig"></xs:element>
+
+    <xs:complexType name="LPConfig">
+       <xs:sequence>
+               <xs:element name="section" type="tns:LPSection" minOccurs="0" maxOccurs="unbounded"></xs:element>
+       </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="LPSection">
+       <xs:sequence>
+               <xs:element name="entry" type="tns:LPEntry" maxOccurs="unbounded" minOccurs="0">
+               </xs:element>
+       </xs:sequence>
+       <xs:attribute name="name" use="required">
+               <xs:simpleType>
+                       <xs:restriction base="xs:string">
+                               <xs:minLength value="1"></xs:minLength>
+                       </xs:restriction>
+               </xs:simpleType>
+       </xs:attribute>
+    </xs:complexType>
+
+    <xs:complexType name="LPEntry">
+       <xs:simpleContent>
+               <xs:extension base="xs:string">
+                       <xs:attribute name="overwrite" type="xs:boolean"
+                               use="optional" default="false">
+                       </xs:attribute>
+                       <xs:attribute name="name" use="required">
+                               <xs:simpleType>
+                                       <xs:restriction base="xs:string">
+                                               <xs:minLength value="1"></xs:minLength>
+                                       </xs:restriction>
+                               </xs:simpleType>
+                       </xs:attribute>
+               </xs:extension>
+       </xs:simpleContent>
+    </xs:complexType>
+</xs:schema>
diff --git a/tools/Makefile.am b/tools/Makefile.am
new file mode 100644 (file)
index 0000000..9e0c945
--- /dev/null
@@ -0,0 +1,40 @@
+## Process this file with automake to produce Makefile.in
+
+AM_CPPFLAGS=\
+       -I$(top_srcdir) \
+       -I$(top_srcdir)/coreapi \
+       -I$(top_srcdir)/exosip
+
+COMMON_CFLAGS=\
+       -DIN_LINPHONE \
+       $(LIBXML2_CFLAGS) \
+       $(ORTP_CFLAGS) \
+       $(STRICT_OPTIONS)
+
+if BUILD_TOOLS
+
+lib_LTLIBRARIES=libxml2lpc.la
+
+libxml2lpc_la_SOURCES=\
+       xml2lpc.c \
+       xml2lpc.h
+
+libxml2lpc_la_CFLAGS=$(COMMON_CFLAGS)
+libxml2lpc_la_LIBADD=\
+       $(LIBXML2_LIBS) \
+       $(top_builddir)/coreapi/liblinphone.la
+
+libxml2lpc_la_LDFLAGS=-no-undefined
+
+bin_PROGRAMS=xml2lpc_test
+
+xml2lpc_test_SOURCES=\
+       xml2lpc_test.c
+
+xml2lpc_test_CFLAGS=$(COMMON_CFLAGS)
+xml2lpc_test_LDADD=\
+       libxml2lpc.la
+
+endif
+
+
diff --git a/tools/xml2lpc.c b/tools/xml2lpc.c
new file mode 100644 (file)
index 0000000..d5e2160
--- /dev/null
@@ -0,0 +1,343 @@
+/*
+linphone
+Copyright (C) 2012 Belledonne Communications SARL
+Yann DIORCET (yann.diorcet@linphone.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 "xml2lpc.h"
+#include <string.h>
+#include <libxml/xmlreader.h>
+
+
+#define XML2LPC_BZ 2048
+
+struct _xml2lpc_context {
+       LpConfig *lpc;
+       xml2lpc_function cbf;
+       void *ctx;
+       
+       xmlDoc *doc;
+       xmlDoc *xsd;
+       char errorBuffer[XML2LPC_BZ];
+       char warningBuffer[XML2LPC_BZ];
+};
+
+
+xml2lpc_context* xml2lpc_context_new(xml2lpc_function cbf, void *ctx) {
+       xml2lpc_context *xmlCtx = (xml2lpc_context*)malloc(sizeof(xml2lpc_context));
+       if(xmlCtx != NULL) {
+               xmlCtx->lpc = NULL;
+               xmlCtx->cbf = cbf;
+               xmlCtx->ctx = ctx;
+               
+               xmlCtx->doc = NULL;
+               xmlCtx->xsd = NULL;
+               xmlCtx->errorBuffer[0]='\0';
+               xmlCtx->warningBuffer[0]='\0';
+       }
+       return xmlCtx;
+}
+
+void xml2lpc_context_destroy(xml2lpc_context *ctx) {
+       if(ctx->doc != NULL) {
+               xmlFreeDoc(ctx->doc);
+               ctx->doc = NULL;
+       }
+       if(ctx->xsd != NULL) {
+               xmlFreeDoc(ctx->xsd);
+               ctx->xsd = NULL;
+       }
+       free(ctx);
+}
+
+static void xml2lpc_context_clear_logs(xml2lpc_context *ctx) {
+       ctx->errorBuffer[0]='\0';
+       ctx->warningBuffer[0]='\0';
+}
+
+static void xml2lpc_log(xml2lpc_context *xmlCtx, int level, const char *fmt, ...) {
+       va_list args;   
+       va_start(args, fmt);    
+       if(xmlCtx->cbf != NULL) {
+               xmlCtx->cbf((xmlCtx)->ctx, level, fmt, args);
+       }
+       va_end(args);
+}
+
+static void xml2lpc_genericxml_error(void *ctx, const char *fmt, ...) {        
+       xml2lpc_context *xmlCtx = (xml2lpc_context *)ctx;
+       int sl = strlen(xmlCtx->errorBuffer);
+       va_list args;   
+       va_start(args, fmt);    
+       vsnprintf(xmlCtx->errorBuffer + sl, XML2LPC_BZ-sl, fmt, args);
+       va_end(args);
+}
+
+static void xml2lpc_genericxml_warning(void *ctx, const char *fmt, ...) {      
+       xml2lpc_context *xmlCtx = (xml2lpc_context *)ctx;
+       int sl = strlen(xmlCtx->warningBuffer);
+       va_list args;   
+       va_start(args, fmt);    
+       vsnprintf(xmlCtx->warningBuffer + sl, XML2LPC_BZ-sl, fmt, args);
+       va_end(args);
+}
+
+#if 0
+static void dumpNodes(int level, xmlNode * a_node, xml2lpc_context *ctx) {
+    xmlNode *cur_node = NULL;
+
+    for (cur_node = a_node; cur_node; cur_node = cur_node->next) {
+        if (cur_node->type == XML_ELEMENT_NODE) {
+               xml2lpc_log(ctx, XML2LPC_DEBUG, "node level: %d type: Element, name: %s", level, cur_node->name);
+        } else {
+               xml2lpc_log(ctx, XML2LPC_DEBUG, "node level: %d type: %d, name: %s", level, cur_node->type, cur_node->name);
+        }
+
+        dumpNodes(level + 1, cur_node->children, ctx);
+    }
+}
+#endif
+
+
+static void dumpNode(xmlNode *node, xml2lpc_context *ctx) {
+        xml2lpc_log(ctx, XML2LPC_DEBUG, "node type: %d, name: %s", node->type, node->name);
+}
+
+static void dumpAttr(xmlNode *node, xml2lpc_context *ctx) {
+        xml2lpc_log(ctx, XML2LPC_DEBUG, "attr name: %s value:%s", node->name, node->children->content);
+}
+
+static void dumpContent(xmlNode *node, xml2lpc_context *ctx) {
+        xml2lpc_log(ctx, XML2LPC_DEBUG, "content: %s", node->children->content);
+}
+
+static int processEntry(xmlElement *element, const char *sectionName, xml2lpc_context *ctx) {
+       xmlNode *cur_attr = NULL;
+       const char *name = NULL;
+       const char *value = NULL;
+       bool_t overwrite = FALSE;
+
+       for (cur_attr = (xmlNode *)element->attributes; cur_attr; cur_attr = cur_attr->next) {
+               dumpAttr(cur_attr, ctx);
+               if(strcmp((const char*)cur_attr->name, "name") == 0) {
+                       name = (const char*)cur_attr->children->content;
+               } else if(strcmp((const char*)cur_attr->name, "overwrite") == 0) {
+                       if(strcmp((const char*)cur_attr->children->content, "true") == 0) {
+                               overwrite = TRUE;
+                       }
+               }
+       }
+
+       value = (const char *)element->children->content;
+       dumpContent((xmlNode *)element, ctx);
+
+       if(name != NULL) {
+               const char *str = lp_config_get_string(ctx->lpc, sectionName, name, NULL);
+               if(str == NULL || overwrite) {
+                       xml2lpc_log(ctx, XML2LPC_MESSAGE, "Set %s|%s = %s",sectionName, name, value);
+                       lp_config_set_string(ctx->lpc, sectionName, name, value);
+               } else {
+                       xml2lpc_log(ctx, XML2LPC_MESSAGE, "Don't touch %s|%s = %s",sectionName, name, str);
+               }
+       } else {
+               xml2lpc_log(ctx, XML2LPC_WARNING, "ignored entry with no \"name\" attribute line:%d",xmlGetLineNo((xmlNode*)element));
+       }
+        return 0;
+}
+
+static int processSection(xmlElement *element, xml2lpc_context *ctx) {
+       xmlNode *cur_node = NULL;
+       xmlNode *cur_attr = NULL;
+       const char *name = NULL;
+
+       for (cur_attr = (xmlNode *)element->attributes; cur_attr; cur_attr = cur_attr->next) {
+               dumpAttr(cur_attr, ctx);
+               if(strcmp((const char*)cur_attr->name, "name") == 0) {
+                       name = (const char*)cur_attr->children->content;
+               }
+       }
+
+       if(name != NULL) {
+               for (cur_node = element->children; cur_node; cur_node = cur_node->next) {
+                       dumpNode(cur_node, ctx);
+                       if (cur_node->type == XML_ELEMENT_NODE) {
+                               if(strcmp((const char*)cur_node->name, "entry") == 0 ) {
+                                       processEntry((xmlElement*)cur_node, name, ctx);
+                               }
+                       }
+                       
+               }
+        } else {
+               xml2lpc_log(ctx, XML2LPC_WARNING, "ignored section with no \"name\" attribute, line:%d", xmlGetLineNo((xmlNode*)element));
+        }
+
+        return 0;
+}
+
+static int processConfig(xmlElement *element, xml2lpc_context *ctx) {
+       xmlNode *cur_node = NULL;
+
+       for (cur_node = element->children; cur_node; cur_node = cur_node->next) {
+               dumpNode(cur_node, ctx);
+               if (cur_node->type == XML_ELEMENT_NODE && 
+                       strcmp((const char*)cur_node->name, "section") == 0 ) {
+                       processSection((xmlElement*)cur_node, ctx);
+               }
+               
+        }
+       return 0;
+}
+
+static int processDoc(xmlNode *node, xml2lpc_context *ctx) {
+       dumpNode(node, ctx);
+       
+       if (node->type == XML_ELEMENT_NODE && 
+               strcmp((const char*)node->name, "config") == 0 ) {
+               processConfig((xmlElement*)node, ctx);
+       } else {
+               xml2lpc_log(ctx, XML2LPC_WARNING, "root element is not \"config\", line:%d", xmlGetLineNo(node));
+       }
+       return 0;
+}
+
+static int internal_convert_xml2lpc(xmlDoc *doc, xml2lpc_context *ctx) {
+       xml2lpc_log(ctx, XML2LPC_DEBUG, "Parse started");
+       xmlNode *rootNode = xmlDocGetRootElement(doc);
+       //dumpNodes(0, rootNode, cbf, ctx);
+        int ret = processDoc(rootNode, ctx);
+       xml2lpc_log(ctx, XML2LPC_DEBUG, "Parse ended ret:%d", ret);
+       return ret;
+}
+
+int xml2lpc_validate(xml2lpc_context *xmlCtx) {
+       xml2lpc_context_clear_logs(xmlCtx);
+       xmlSchemaValidCtxtPtr validCtx;
+       xmlSchemaParserCtxtPtr parserCtx = xmlSchemaNewDocParserCtxt(xmlCtx->xsd);
+       validCtx = xmlSchemaNewValidCtxt(xmlSchemaParse(parserCtx));
+       xmlSchemaSetValidErrors(validCtx, xml2lpc_genericxml_error, xml2lpc_genericxml_warning, xmlCtx);
+       int ret =  xmlSchemaValidateDoc(validCtx, xmlCtx->doc);
+       if(ret >0) {
+               xml2lpc_log(xmlCtx, XML2LPC_WARNING, "%s", xmlCtx->warningBuffer);
+               xml2lpc_log(xmlCtx, XML2LPC_ERROR, "%s", xmlCtx->errorBuffer);
+       } else {
+               xml2lpc_log(xmlCtx, XML2LPC_ERROR, "Internal error");
+       }
+       xmlSchemaFreeValidCtxt(validCtx);
+       return ret;
+}
+
+int xml2lpc_convert(xml2lpc_context *xmlCtx, LpConfig *lpc) {
+       xml2lpc_context_clear_logs(xmlCtx);
+       xmlCtx->lpc = lpc;
+       return internal_convert_xml2lpc(xmlCtx->doc, xmlCtx);
+}
+
+int xml2lpc_set_xml_file(xml2lpc_context* xmlCtx, const char *filename) {
+       xml2lpc_context_clear_logs(xmlCtx);
+       xmlSetGenericErrorFunc(xmlCtx, xml2lpc_genericxml_error);
+       if(xmlCtx->doc != NULL) {
+               xmlFreeDoc(xmlCtx->doc);
+               xmlCtx->doc = NULL;
+       }
+       xmlCtx->doc = xmlReadFile(filename, NULL, 0);
+       if(xmlCtx->doc == NULL) {
+               xml2lpc_log(xmlCtx, XML2LPC_ERROR, "Can't open/parse file \"%s\"", filename);
+               xml2lpc_log(xmlCtx, XML2LPC_ERROR, "%s", xmlCtx->errorBuffer);
+               return -1;
+       }
+       return 0;
+}
+
+int xml2lpc_set_xml_fd(xml2lpc_context* xmlCtx, int fd) {
+       xml2lpc_context_clear_logs(xmlCtx);
+       xmlSetGenericErrorFunc(xmlCtx, xml2lpc_genericxml_error);
+       if(xmlCtx->doc != NULL) {
+               xmlFreeDoc(xmlCtx->doc);
+               xmlCtx->doc = NULL;
+       }
+       xmlCtx->doc = xmlReadFd(fd, 0, NULL, 0);
+       if(xmlCtx->doc == NULL) {
+               xml2lpc_log(xmlCtx, XML2LPC_ERROR, "Can't open/parse fd \"%d\"", fd);
+               xml2lpc_log(xmlCtx, XML2LPC_ERROR, "%s", xmlCtx->errorBuffer);
+               return -1;
+       }
+       return 0;
+}
+
+int xml2lpc_set_xml_string(xml2lpc_context* xmlCtx, const char *content) {
+       xml2lpc_context_clear_logs(xmlCtx);
+       xmlSetGenericErrorFunc(xmlCtx, xml2lpc_genericxml_error);
+       if(xmlCtx->doc != NULL) {
+               xmlFreeDoc(xmlCtx->doc);
+               xmlCtx->doc = NULL;
+       }
+       xmlCtx->doc = xmlReadDoc((const unsigned char*)content, 0, NULL, 0);
+       if(xmlCtx->doc == NULL) {
+               xml2lpc_log(xmlCtx, XML2LPC_ERROR, "Can't parse string");
+               xml2lpc_log(xmlCtx, XML2LPC_ERROR, "%s", xmlCtx->errorBuffer);
+               return -1;
+       }
+       return 0;
+}
+
+int xml2lpc_set_xsd_file(xml2lpc_context* xmlCtx, const char *filename) {
+       xml2lpc_context_clear_logs(xmlCtx);
+       xmlSetGenericErrorFunc(xmlCtx, xml2lpc_genericxml_error);
+       if(xmlCtx->xsd != NULL) {
+               xmlFreeDoc(xmlCtx->xsd);
+               xmlCtx->xsd = NULL;
+       }
+       xmlCtx->xsd = xmlReadFile(filename, NULL, 0);
+       if(xmlCtx->xsd == NULL) {
+               xml2lpc_log(xmlCtx, XML2LPC_ERROR, "Can't open/parse file \"%s\"", filename);
+               xml2lpc_log(xmlCtx, XML2LPC_ERROR, "%s", xmlCtx->errorBuffer);
+               return -1;
+       }
+       return 0;
+}
+
+int xml2lpc_set_xsd_fd(xml2lpc_context* xmlCtx, int fd) {
+       xml2lpc_context_clear_logs(xmlCtx);
+       xmlSetGenericErrorFunc(xmlCtx, xml2lpc_genericxml_error);
+       if(xmlCtx->xsd != NULL) {
+               xmlFreeDoc(xmlCtx->xsd);
+               xmlCtx->xsd = NULL;
+       }
+       xmlCtx->xsd = xmlReadFd(fd, 0, NULL, 0);
+       if(xmlCtx->xsd == NULL) {
+               xml2lpc_log(xmlCtx, XML2LPC_ERROR, "Can't open/parse fd \"%d\"", fd);
+               xml2lpc_log(xmlCtx, XML2LPC_ERROR, "%s", xmlCtx->errorBuffer);
+               return -1;
+       }
+       return 0;
+}
+
+int xml2lpc_set_xsd_string(xml2lpc_context* xmlCtx, const char *content) {
+       xml2lpc_context_clear_logs(xmlCtx);
+       xmlSetGenericErrorFunc(xmlCtx, xml2lpc_genericxml_error);
+       if(xmlCtx->xsd != NULL) {
+               xmlFreeDoc(xmlCtx->xsd);
+               xmlCtx->xsd = NULL;
+       }
+       xmlCtx->xsd = xmlReadDoc((const unsigned char*)content, 0, NULL, 0);
+       if(xmlCtx->xsd == NULL) {
+               xml2lpc_log(xmlCtx, XML2LPC_ERROR, "Can't parse string");
+               xml2lpc_log(xmlCtx, XML2LPC_ERROR, "%s", xmlCtx->errorBuffer);
+               return -1;
+       }
+       return 0;
+}
diff --git a/tools/xml2lpc.h b/tools/xml2lpc.h
new file mode 100644 (file)
index 0000000..746fb02
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+linphone
+Copyright (C) 2012 Belledonne Communications SARL
+
+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 XML2LPC_H_
+#define XML2LPC_H_
+
+#include "lpconfig.h"
+
+typedef struct _xml2lpc_context xml2lpc_context;
+
+typedef enum _xml2lpc_log_level {
+       XML2LPC_DEBUG = 0,
+       XML2LPC_MESSAGE,
+       XML2LPC_WARNING,
+       XML2LPC_ERROR
+} xml2lpc_log_level;
+
+typedef void(*xml2lpc_function)(void *ctx, xml2lpc_log_level level, const char *fmt, va_list list);
+
+xml2lpc_context* xml2lpc_context_new(xml2lpc_function cbf, void *ctx);
+void xml2lpc_context_destroy(xml2lpc_context*);
+
+int xml2lpc_set_xml_file(xml2lpc_context* context, const char *filename);
+int xml2lpc_set_xml_fd(xml2lpc_context* context, int fd);
+int xml2lpc_set_xml_string(xml2lpc_context* context, const char *content);
+
+int xml2lpc_set_xsd_file(xml2lpc_context* context, const char *filename);
+int xml2lpc_set_xsd_fd(xml2lpc_context* context, int fd);
+int xml2lpc_set_xsd_string(xml2lpc_context* context, const char *content);
+
+int xml2lpc_validate(xml2lpc_context *context);
+int xml2lpc_convert(xml2lpc_context *context, LpConfig *lpc);
+
+
+
+#endif //XML2LPC_H_
diff --git a/tools/xml2lpc_test.c b/tools/xml2lpc_test.c
new file mode 100644 (file)
index 0000000..e99b90b
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+linphone
+Copyright (C) 2012 Belledonne Communications SARL
+
+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 "xml2lpc.h"
+
+void cb_function(void *ctx, xml2lpc_log_level level, const char *msg, va_list list) {
+       const char *header = "";
+       switch(level) {
+               case XML2LPC_DEBUG:
+                       header = "DEBUG";
+                       break;
+               case XML2LPC_MESSAGE:
+                       header = "MESSAGE";
+                       break;
+               case XML2LPC_WARNING:
+                       header = "WARNING";
+                       break;
+               case XML2LPC_ERROR:
+                       header = "ERROR";
+                       break;
+       }
+       fprintf(stdout, "%s - ", header);
+       vfprintf(stdout, msg, list);
+       fprintf(stdout, "\n");
+}
+
+void show_usage(int argc, char *argv[]) {
+       fprintf(stderr, "usage %s convert <xml_file> <lpc_file>\n"
+                       "      %s validate <xml_file> <xsd_file>\n", 
+                       argv[0], argv[0]);
+}
+
+int main(int argc, char *argv[]) {
+       if(argc != 4) {
+               show_usage(argc, argv);
+               return -1;
+       }
+       
+       xml2lpc_context *ctx = xml2lpc_context_new(cb_function, NULL);
+       xml2lpc_set_xml_file(ctx, argv[2]);
+       if(strcmp("convert", argv[1]) == 0) {
+               LpConfig *lpc = lp_config_new(argv[3]);
+               xml2lpc_convert(ctx, lpc);
+               lp_config_sync(lpc);
+               lp_config_destroy(lpc);
+       } else if(strcmp("validate", argv[1]) == 0) {
+               xml2lpc_set_xsd_file(ctx, argv[3]);
+               xml2lpc_validate(ctx);
+       } else {
+               show_usage(argc, argv);
+       }
+       xml2lpc_context_destroy(ctx);
+       return 0;
+}
+