Merge remote-tracking branch 'public/master' into belle-sip

Conflicts:
	configure.ac
	coreapi/sal.c
	coreapi/sal.h
This commit is contained in:
Jehan Monnier 2013-02-06 10:55:57 +01:00
commit 427ec85ce4
57 changed files with 3638 additions and 1197 deletions

View file

@ -21,7 +21,6 @@
LOCAL_PATH:= $(call my-dir)/../../coreapi
include $(CLEAR_VARS)
include $(linphone-root-dir)/submodules/linphone/build/android/common.mk
@ -39,3 +38,11 @@ LOCAL_MODULE := liblinphone
include $(BUILD_SHARED_LIBRARY)
$(call import-module,android/cpufeatures)
ifeq ($(BUILD_REMOTE_PROVISIONING),1)
include $(linphone-root-dir)/submodules/linphone/build/android/xml2lpc.mk
include $(linphone-root-dir)/submodules/linphone/build/android/lpc2xml.mk
endif

View file

@ -49,7 +49,7 @@ LOCAL_SRC_FILES := \
linphonecall.c \
conference.c \
ec-calibrator.c \
linphone_tunnel.cc
linphone_tunnel_config.c
ifndef LINPHONE_VERSION
LINPHONE_VERSION = "Devel"
@ -100,12 +100,14 @@ LOCAL_STATIC_LIBRARIES := \
ifeq ($(BUILD_TUNNEL),1)
LOCAL_CFLAGS +=-DTUNNEL_ENABLED
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../tunnel/include $(LOCAL_PATH)/../../tunnel/src
LOCAL_SRC_FILES += TunnelManager.cc
LOCAL_SRC_FILES += linphone_tunnel.cc TunnelManager.cc
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
LOCAL_SHARED_LIBRARIES += libtunnelclient
else
LOCAL_STATIC_LIBRARIES += libtunnelclient
endif
else
LOCAL_SRC_FILES += linphone_tunnel_stubs.c
endif

47
build/android/lpc2xml.mk Normal file
View file

@ -0,0 +1,47 @@
##
## Android.mk -Android build script-
##
##
## Copyright (C) 2013 Belledonne Communications, Grenoble, France
##
## 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.
##
LOCAL_PATH:= $(call my-dir)/../../tools
include $(CLEAR_VARS)
LOCAL_CPP_EXTENSION := .cc
LOCAL_SRC_FILES := \
lpc2xml.c \
lpc2xml_jni.cc \
LOCAL_CFLAGS += -DIN_LINPHONE
LOCAL_C_INCLUDES = \
$(LOCAL_PATH)/../coreapi \
$(LOCAL_PATH)/../oRTP/include \
$(LOCAL_PATH)/../mediastreamer2/include \
$(LOCAL_PATH)/../../externals/libxml2/include \
$(LOCAL_PATH)/../../externals/build/libxml2 \
LOCAL_SHARED_LIBRARIES = \
libxml2 \
liblinphone \
LOCAL_MODULE := liblpc2xml
include $(BUILD_SHARED_LIBRARY)

47
build/android/xml2lpc.mk Normal file
View file

@ -0,0 +1,47 @@
##
## Android.mk -Android build script-
##
##
## Copyright (C) 2013 Belledonne Communications, Grenoble, France
##
## 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.
##
LOCAL_PATH:= $(call my-dir)/../../tools
include $(CLEAR_VARS)
LOCAL_CPP_EXTENSION := .cc
LOCAL_SRC_FILES := \
xml2lpc.c \
xml2lpc_jni.cc \
LOCAL_CFLAGS += -DIN_LINPHONE
LOCAL_C_INCLUDES = \
$(LOCAL_PATH)/../coreapi \
$(LOCAL_PATH)/../oRTP/include \
$(LOCAL_PATH)/../mediastreamer2/include \
$(LOCAL_PATH)/../../externals/libxml2/include \
$(LOCAL_PATH)/../../externals/build/libxml2 \
LOCAL_SHARED_LIBRARIES = \
libxml2 \
liblinphone \
LOCAL_MODULE := libxml2lpc
include $(BUILD_SHARED_LIBRARY)

View file

@ -46,12 +46,12 @@ AM_CONDITIONAL(HAVE_MD5SUM,test -n $MD5SUM)
case $target in
*mingw32ce)
CFLAGS="$CFLAGS -D_WIN32_WCE -DORTP_STATIC -D_WIN32_WINNT=0x0501"
CXXFLAGS="$CXXFLAGS -DORTP_STATIC -D_WIN32_WINNT=0x0501"
LIBS="$LIBS -lws2 -liphlpapi"
CFLAGS="$CFLAGS -D_WIN32_WCE -DORTP_STATIC -D_WIN32_WINNT=0x0501"
CXXFLAGS="$CXXFLAGS -DORTP_STATIC -D_WIN32_WINNT=0x0501"
LIBS="$LIBS -lws2 -liphlpapi"
mingw_found=yes
mingwce_found=yes
;;
;;
*mingw*)
CFLAGS="$CFLAGS -DORTP_STATIC -D_WIN32_WINNT=0x0501 "
CXXFLAGS="$CXXFLAGS -DORTP_STATIC -D_WIN32_WINNT=0x0501"
@ -60,17 +60,17 @@ case $target in
CONSOLE_FLAGS="-mconsole"
mingw_found=yes
;;
armv6-apple-darwin|armv7-apple-darwin|i386-apple-darwin|armv7s-apple-darwin)
CFLAGS="$CFLAGS -DTARGET_OS_IPHONE "
build_tests=no
ios_found=yes
;;
x86_64-apple-darwin*|i686-apple-darwin*)
MSPLUGINS_CFLAGS=""
armv6-apple-darwin|armv7-apple-darwin|i386-apple-darwin|armv7s-apple-darwin)
CFLAGS="$CFLAGS -DTARGET_OS_IPHONE "
build_tests=no
ios_found=yes
;;
x86_64-apple-darwin*|i686-apple-darwin*)
MSPLUGINS_CFLAGS=""
dnl use macport installation
ACLOCAL_MACOS_FLAGS="-I /opt/local/share/aclocal"
build_macos=yes
;;
;;
esac
@ -82,30 +82,34 @@ dnl localization tools
IT_PROG_INTLTOOL([0.40], [no-xml])
AM_CONDITIONAL(BUILD_TESTS,test x$build_tests != xno)
dnl Initialize libtool
LT_INIT([win32-dll shared disable-static])
dnl Enable library dependencies linking
AC_ARG_ENABLE(deplibs-link,
[AS_HELP_STRING([--disable-deplibs-link ], [Disable library dependencies linking (might break builds)])],
[enable_deplibs_linking="$enableval"],
[enable_deplibs_linking="yes"])
[AS_HELP_STRING([--disable-deplibs-link ], [Disable library dependencies linking (might break builds)])],
[enable_deplibs_linking="$enableval"],
[enable_deplibs_linking="yes"]
)
AC_MSG_NOTICE([Enable library dependencies linking: $enable_interlib_deps])
if test "${enable_deplibs_linking}" == "yes"; then
link_all_deplibs=yes
link_all_deplibs_CXX=yes
link_all_deplibs=yes
link_all_deplibs_CXX=yes
else
link_all_deplibs=no
link_all_deplibs_CXX=no
link_all_deplibs=no
link_all_deplibs_CXX=no
fi
AC_CONFIG_COMMANDS([libtool-hacking],[
if test "$mingw_found" = "yes" ; then
echo "Hacking libtool to work with mingw..."
sed -e 's/\*\" \$a_deplib \"\*/\*/' < ./libtool > libtool.tmp
cp -f ./libtool.tmp ./libtool
rm -f ./libtool.tmp
fi
],[mingw_found=$mingw_found])
AC_CONFIG_COMMANDS([libtool-hacking],
[if test "$mingw_found" = "yes" ; then
echo "Hacking libtool to work with mingw..."
sed -e 's/\*\" \$a_deplib \"\*/\*/' < ./libtool > libtool.tmp
cp -f ./libtool.tmp ./libtool
rm -f ./libtool.tmp
fi],
[mingw_found=$mingw_found]
)
dnl Add the languages which your application supports here.
PKG_PROG_PKG_CONFIG
@ -136,57 +140,91 @@ dnl AC_CHECK_LIB(intl,libintl_gettext)
AC_CHECK_FUNCS([get_current_dir_name strndup stpcpy] )
AC_ARG_ENABLE(x11,
[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])
[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,
[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])
[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])
[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 for installed version of libupnp
AC_ARG_ENABLE(upnp,
[AS_HELP_STRING([--disable-upnp], [Disable uPnP support])],
[case "${enableval}" in
yes) build_upnp=true ;;
no) build_upnp=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --disable-upnp) ;;
esac],
[build_upnp=auto]
)
if test "$build_upnp" != "false" ; then
PKG_CHECK_MODULES([LIBUPNP], [libupnp], [build_upnp=true],
[if test "$build_upnp" == "true" ; then
AC_MSG_ERROR([libupnp not found.])
else
build_upnp=false
fi]
)
fi
AM_CONDITIONAL(BUILD_UPNP, test x$build_upnp != xfalse)
if test "$build_upnp" != "false" ; then
AC_DEFINE(BUILD_UPNP, 1, [Define if upnp enabled])
fi
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
[if test "$build_tools" = "true" ; then
AC_MSG_ERROR([Could not found libxml2, tools cannot be compiled.])
else
build_tools=false
fi
])
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] )
build_tools=true
AC_DEFINE(BUILD_TOOLS, 1, [Define if tools enabled] )
fi
dnl conditionnal build of gtk interface.
AC_ARG_ENABLE(gtk_ui,
[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 ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-gtk_ui) ;;
esac],[gtk_ui=true])
[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 ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-gtk_ui) ;;
esac],
[gtk_ui=true]
)
if test "$gtk_ui" = "true" ; then
PKG_CHECK_MODULES(LIBGTK, gtk+-2.0 >= 2.18.0 gthread-2.0)
@ -199,33 +237,35 @@ else
fi
AC_ARG_ENABLE(notify,
[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])
[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
if test "$notify" = "true"; then
PKG_CHECK_MODULES([NOTIFY4], [libnotify >= 0.7.0 ], [found_notify4=yes], foo=bar)
case "$found_notify4" in
yes)
yes)
AC_SUBST(NOTIFY4_CFLAGS)
AC_SUBST(NOTIFY4_LIBS)
AC_DEFINE([HAVE_NOTIFY4],[1],[NOTIFY4 support])
esac
PKG_CHECK_MODULES([NOTIFY1], [libnotify < 0.7.0], [found_notify1=yes], foo=bar)
case "$found_notify1" in
yes)
AC_SUBST(NOTIFY1_CFLAGS)
AC_SUBST(NOTIFY1_LIBS)
AC_DEFINE([HAVE_NOTIFY1],[1],[NOTIFY1 support])
esac
PKG_CHECK_MODULES([NOTIFY1], [libnotify < 0.7.0], [found_notify1=yes], foo=bar)
case "$found_notify1" in
yes)
AC_SUBST(NOTIFY1_CFLAGS)
AC_SUBST(NOTIFY1_LIBS)
AC_DEFINE([HAVE_NOTIFY1],[1],[NOTIFY1 support])
esac
else
NotifyNotification *n;
NotifyNotification *n;
echo "Libnotify support is disabled."
fi
fi
@ -234,37 +274,41 @@ dnl os-specific problems not handled by existing macros.
case "$host_os" in
*freebsd*)
LDFLAGS="$LDFLAGS -pthread"
;;
;;
esac
case "$host_cpu" in
*arm*)
AC_DEFINE(__ARM__,1,[Defined if we are compiling for arm processor])
use_arm_toolchain=yes
;;
;;
esac
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" ])
[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,
[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 ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-relativeprefix) ;;
esac],[relativeprefix=guess])
[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 ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-relativeprefix) ;;
esac],
[relativeprefix=guess]
)
AC_ARG_ENABLE(date,
[AS_HELP_STRING([--enable-date], [Use build date in internal version number])],
[case "${enableval}" in
yes) use_date=yes ;;
no) use_date=no ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-date) ;;
esac],[use_date=no])
[AS_HELP_STRING([--enable-date], [Use build date in internal version number])],
[case "${enableval}" in
yes) use_date=yes ;;
no) use_date=no ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-date) ;;
esac],
[use_date=no]
)
if test x$use_date = xyes ; then
AC_DEFINE(USE_BUILDDATE_VERSION,1,[Tell whether date_version.h must be used])
@ -273,12 +317,14 @@ fi
dnl enable ipv6 support
AC_ARG_ENABLE(ipv6,
[AS_HELP_STRING([--enable-ipv6], [Turn on ipv6 support])],
[case "${enableval}" in
yes) ipv6=true;;
no) ipv6=false;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-ipv6) ;;
esac],[ipv6=true])
[AS_HELP_STRING([--enable-ipv6], [Turn on ipv6 support])],
[case "${enableval}" in
yes) ipv6=true;;
no) ipv6=false;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-ipv6) ;;
esac],
[ipv6=true]
)
IPV6_CFLAGS=
if test x$ipv6 = xtrue ; then
IPV6_CFLAGS=-DINET6
@ -287,29 +333,35 @@ AC_SUBST(IPV6_CFLAGS)
dnl enable timestamp support
AC_ARG_ENABLE(ntp-timestamp,
[AS_HELP_STRING([--enable-ntp-timestamp], [Turn on NTP timestamping on received packet])],
[case "${enableval}" in
yes) ntptimestamp=true;;
no) ntptimestamp=false;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-ntp-timestamp) ;;
esac],[ntptimestamp=false])
[AS_HELP_STRING([--enable-ntp-timestamp], [Turn on NTP timestamping on received packet])],
[case "${enableval}" in
yes) ntptimestamp=true;;
no) ntptimestamp=false;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-ntp-timestamp) ;;
esac],
[ntptimestamp=false]
)
AC_ARG_ENABLE(debug,
[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])
[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,
[AS_HELP_STRING([--enable-truespeech], [Turn on TrueSpeech support (x86 only)])],
[case "${enableval}" in
yes) truespeech=true;;
no) truespeech=false;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-truespeech) ;;
esac],[truespeech=false])
[AS_HELP_STRING([--enable-truespeech], [Turn on TrueSpeech support (x86 only)])],
[case "${enableval}" in
yes) truespeech=true;;
no) truespeech=false;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-truespeech) ;;
esac],
[truespeech=false]
)
TRUESPEECH_CFLAGS=
if test x$truespeech = xtrue ; then
TRUESPEECH_CFLAGS=-DTRUESPEECH
@ -318,21 +370,24 @@ AC_SUBST(TRUESPEECH_CFLAGS)
AM_CONDITIONAL([BUILD_TRUESPEECH], [test x$truespeech = xtrue])
AC_ARG_ENABLE(nonstandard-gsm,
[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])
;;
no) exotic_gsm=no ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-nonstandard-gsm) ;;
esac],[exotic_gsm=no])
[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])
;;
no) exotic_gsm=no ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-nonstandard-gsm) ;;
esac],
[exotic_gsm=no]
)
dnl support for RSVP (by Vincent Maury)
AC_ARG_ENABLE(rsvp,
[AS_HELP_STRING([--enable-rsvp], [Enable support for QoS reservations.])],
AC_DEFINE(VINCENT_MAURY_RSVP,1,[Tell whether RSVP support
should be compiled.]) )
[AS_HELP_STRING([--enable-rsvp], [Enable support for QoS reservations.])],
AC_DEFINE(VINCENT_MAURY_RSVP,1,[Tell whether RSVP support should be compiled.])
)
if test "x${prefix}" = "xNONE"; then
package_prefix=${ac_default_prefix}
@ -369,12 +424,14 @@ LP_CHECK_OSIP2
dnl conditionnal build for ssl
AC_ARG_ENABLE(ssl,
[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])
[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)
@ -385,26 +442,30 @@ LP_SETUP_EXOSIP
dnl check exosip support of DSCP in exosip
AC_MSG_CHECKING([for DSCP support in exosip])
AC_TRY_COMPILE([#include <eXosip2/eXosip.h>],
[int dscp=0;eXosip_set_option(EXOSIP_OPT_SET_DSCP,&dscp);],
has_exosip_dscp=yes,has_exosip_dscp=no)
[int dscp=0;eXosip_set_option(EXOSIP_OPT_SET_DSCP,&dscp);],
has_exosip_dscp=yes,
has_exosip_dscp=no
)
AC_MSG_RESULT($has_exosip_dscp)
if test "$has_exosip_dscp" = "yes" ; then
AC_DEFINE( HAVE_EXOSIP_DSCP, 1, [Define if exosip dscp available] )
AC_DEFINE( HAVE_EXOSIP_DSCP, 1, [Define if exosip dscp available] )
fi
if test "$console_ui" = "true" ; then
dnl check gnu readline
LP_CHECK_READLINE
dnl check gnu readline
LP_CHECK_READLINE
else
echo "Console interface compilation is disabled."
echo "Console interface compilation is disabled."
fi
AC_WORDS_BIGENDIAN
AC_ARG_ENABLE([speex],
AS_HELP_STRING([--disable-speex], [Disable speex support]),
[], [enable_speex=yes])
AS_HELP_STRING([--disable-speex], [Disable speex support]),
[],
[enable_speex=yes]
)
if test "x$enable_speex" = "xyes"; then
dnl normaly this should only by done by mediastreamer2/configure.ac
dnl but to workaround bugs when cross-compiling for arm-linux,
@ -416,16 +477,20 @@ fi
dnl conditionnal build of video support
AC_ARG_ENABLE(video,
[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])
[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,
[AS_HELP_STRING([--with-ffmpeg], [Sets the installation prefix of ffmpeg, needed for video support. (default=/usr)])],
[ ffmpegdir=${withval}],[ ffmpegdir=/usr ])
AC_ARG_WITH(ffmpeg,
[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
@ -442,29 +507,35 @@ if test "$video" = "true"; then
fi
AC_ARG_ENABLE(alsa,
[AS_HELP_STRING([--enable-alsa], [Turn on alsa native support compiling])],
[case "${enableval}" in
yes) alsa=true ;;
no) alsa=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-alsa) ;;
esac],[alsa=true])
[AS_HELP_STRING([--enable-alsa], [Turn on alsa native support compiling])],
[case "${enableval}" in
yes) alsa=true ;;
no) alsa=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-alsa) ;;
esac],
[alsa=true]
)
AC_ARG_ENABLE(zrtp,
[AS_HELP_STRING([--enable-zrtp], [Turn on zrtp support])],
[case "${enableval}" in
yes) zrtp=true ;;
no) zrtp=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-zrtp) ;;
esac],[zrtp=false])
[AS_HELP_STRING([--enable-zrtp], [Turn on zrtp support])],
[case "${enableval}" in
yes) zrtp=true ;;
no) zrtp=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-zrtp) ;;
esac],
[zrtp=false]
)
AC_ARG_ENABLE(portaudio,
[AS_HELP_STRING([--enable-portaudio], [Turn on portaudio native support compiling])],
[case "${enableval}" in
yes) portaudio=true ;;
no) portaudio=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-portaudio) ;;
esac],[portaudio=false])
[AS_HELP_STRING([--enable-portaudio], [Turn on portaudio native support compiling])],
[case "${enableval}" in
yes) portaudio=true ;;
no) portaudio=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-portaudio) ;;
esac],
[portaudio=false]
)
dnl build console if required
AM_CONDITIONAL(BUILD_CONSOLE, test x$console_ui = xtrue)
@ -487,44 +558,44 @@ AC_TRY_COMPILE([#include <signal.h>],[sighandler_t *f;],
has_sighandler_t=yes,has_sighandler_t=no)
AC_MSG_RESULT($has_sighandler_t)
if test "$has_sighandler_t" = "yes" ; then
AC_DEFINE( HAVE_SIGHANDLER_T, 1, [Define if sighandler_t available] )
AC_DEFINE( HAVE_SIGHANDLER_T, 1, [Define if sighandler_t available] )
fi
AC_ARG_ENABLE(assistant,
[AS_HELP_STRING([--enable-assistant], [Turn on assistant compiling])],
[case "${enableval}" in
yes) build_wizard=true ;;
no) build_wizard=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-assistant) ;;
esac],[build_wizard=check])
[AS_HELP_STRING([--enable-assistant], [Turn on assistant compiling])],
[case "${enableval}" in
yes) build_wizard=true ;;
no) build_wizard=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-assistant) ;;
esac],
[build_wizard=check]
)
dnl check libsoup (needed for wizard)
if test "$build_wizard" != "false" ; then
PKG_CHECK_MODULES(LIBSOUP, [libsoup-2.4 >= 2.26],[],
[
if test "$build_wizard" = "true" ; then
[if test "$build_wizard" = "true" ; then
AC_MSG_ERROR([Could not found libsoup, assistant cannot be compiled.])
else
build_wizard=false
fi
])
fi]
)
fi
if test "$build_wizard" != "false" ; then
PKG_CHECK_MODULES(LIBGTKWIZARD, [gtk+-2.0 >= 2.22.0],[],
[
if test "$build_wizard" = "true" ; then
[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]
)
fi
AC_SUBST(LIBSOUP_CFLAGS)
AC_SUBST(LIBSOUP_LIBS)
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] )
build_wizard=true
AC_DEFINE(BUILD_WIZARD, 1, [Define if wizard enabled] )
fi
AC_CHECK_HEADERS(libudev.h)
@ -536,9 +607,9 @@ AC_CHECK_LIB(udev,udev_new)
AC_ARG_ENABLE(strict,
AC_HELP_STRING([--enable-strict],
[Build with stricter options (gcc only) @<:@yes@:>@]),[
strictness="${enableval}"],[strictness=yes]
AC_HELP_STRING([--enable-strict], [Build with stricter options (gcc only) @<:@yes@:>@]),
[strictness="${enableval}"],
[strictness=yes]
)
STRICT_OPTIONS="-Wall "
@ -553,26 +624,26 @@ AC_SUBST(STRICT_OPTIONS)
top_srcdir=`dirname $0`
AC_ARG_ENABLE([external-mediastreamer],
[AS_HELP_STRING([--enable-external-mediastreamer],[Use external mediastreamer library])],,
[enable_external_mediastreamer=no])
[AS_HELP_STRING([--enable-external-mediastreamer],[Use external mediastreamer library])],,
[enable_external_mediastreamer=no]
)
AS_CASE($enable_external_mediastreamer,
[yes],[
PKG_CHECK_MODULES([MEDIASTREAMER], [mediastreamer])
MS2_VERSION=`$PKG_CONFIG --modversion mediastreamer`
],
[no],[
AC_CONFIG_SUBDIRS( mediastreamer2 )
MEDIASTREAMER_DIR=${top_srcdir}/mediastreamer2
MEDIASTREAMER_CFLAGS="-I\$(top_srcdir)/mediastreamer2/include"
MEDIASTREAMER_LIBS="\$(top_builddir)/mediastreamer2/src/libmediastreamer_base.la \$(top_builddir)/mediastreamer2/src/libmediastreamer_voip.la"
[yes],
[PKG_CHECK_MODULES([MEDIASTREAMER], [mediastreamer])
MS2_VERSION=`$PKG_CONFIG --modversion mediastreamer`],
[no],
[AC_CONFIG_SUBDIRS( mediastreamer2 )
MEDIASTREAMER_DIR=${top_srcdir}/mediastreamer2
MEDIASTREAMER_CFLAGS="-I\$(top_srcdir)/mediastreamer2/include"
MEDIASTREAMER_LIBS="\$(top_builddir)/mediastreamer2/src/libmediastreamer_base.la \$(top_builddir)/mediastreamer2/src/libmediastreamer_voip.la"
dnl need to temporary change quotes to allow square brackets
changequote(<<, >>)
MS2_VERSION=`grep -e '^.C_INIT(' $MEDIASTREAMER_DIR/configure.ac | sed -e 's:\([^(]\+\)(\[mediastreamer\],\[\(.*\)\]):\2:g'`
changequote([, ])
MS2_DIR=mediastreamer2
],
[AC_MSG_ERROR([bad value '${enable_external_mediastreamer}' for --enable-external-mediastreamer])])
changequote(<<, >>)
MS2_VERSION=`grep -e '^.C_INIT(' $MEDIASTREAMER_DIR/configure.ac | sed -e 's:\([^(]\+\)(\[mediastreamer\],\[\(.*\)\]):\2:g'`
changequote([, ])
MS2_DIR=mediastreamer2],
[AC_MSG_ERROR([bad value '${enable_external_mediastreamer}' for --enable-external-mediastreamer])]
)
AC_SUBST(MEDIASTREAMER_CFLAGS)
AC_SUBST(MEDIASTREAMER_LIBS)
@ -582,18 +653,20 @@ AC_SUBST([MS2_DIR])
AC_ARG_ENABLE(tunnel,
[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 ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-tunnel) ;;
esac],[enable_tunnel=false])
[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 ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-tunnel) ;;
esac],
[enable_tunnel=false]
)
AM_CONDITIONAL(BUILD_TUNNEL, test x$enable_tunnel = xtrue)
if test x$enable_tunnel = xtrue; then
PKG_CHECK_MODULES(TUNNEL, tunnel >= 0.3.3)
TUNNEL_CFLAGS+="-DTUNNEL_ENABLED"
AC_SUBST(TUNNEL_CFLAGS)
AC_SUBST(TUNNEL_LIBS)
PKG_CHECK_MODULES(TUNNEL, tunnel >= 0.3.3)
TUNNEL_CFLAGS+="-DTUNNEL_ENABLED"
AC_SUBST(TUNNEL_CFLAGS)
AC_SUBST(TUNNEL_LIBS)
fi
SIPSTACK_CFLAGS=
@ -620,7 +693,7 @@ AC_SUBST(SIPSTACK_CFLAGS)
AC_SUBST(SIPSTACK_LIBS)
dnl check for db2html (docbook) to generate html user manual
AC_CHECK_PROG(have_sgmltools,sgmltools, yes, no)
AC_CHECK_PROG(have_sgmltools, sgmltools, yes, no)
AM_CONDITIONAL(ENABLE_MANUAL, test x$have_sgmltools$build_manual = xyesyes )
dnl for external use of linphone libs
@ -633,19 +706,21 @@ fi
AC_SUBST(LINPHONE_CFLAGS)
AC_SUBST(LINPHONE_LIBS)
AC_DEFINE_UNQUOTED(LINPHONE_VERSION,"$PACKAGE_VERSION",[Linphone's version number])
AC_DEFINE_UNQUOTED(LINPHONE_VERSION, "$PACKAGE_VERSION", [Linphone\'s version number])
AC_DEFINE_UNQUOTED(LINPHONE_PLUGINS_DIR, "${package_prefix}/lib/liblinphone/plugins" ,[path of liblinphone plugins, not mediastreamer2 plugins])
LINPHONE_PLUGINS_DIR="${package_prefix}/lib/liblinphone/plugins"
AC_SUBST(LINPHONE_PLUGINS_DIR)
AC_ARG_ENABLE(external-ortp,
[AS_HELP_STRING([--enable-external-ortp], [Use external oRTP library])],
[case "${enableval}" in
yes) external_ortp=true ;;
no) external_ortp=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-external-ortp) ;;
esac],[external_ortp=false])
[AS_HELP_STRING([--enable-external-ortp], [Use external oRTP library])],
[case "${enableval}" in
yes) external_ortp=true ;;
no) external_ortp=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-external-ortp) ;;
esac],
[external_ortp=false]
)
if test "$external_ortp" = 'true'; then
PKG_CHECK_MODULES([ORTP], [ortp])
@ -658,7 +733,7 @@ else
ORTP_CFLAGS="$ORTP_CFLAGS -DORTP_BIGENDIAN"
fi
if test x$ntptimestamp = xtrue ; then
ORTP_CFLAGS="$ORTP_CFLAGS -DORTP_TIMESTAMP"
ORTP_CFLAGS="$ORTP_CFLAGS -DORTP_TIMESTAMP"
fi
ORTP_DIR=oRTP
changequote(<<, >>)
@ -671,12 +746,14 @@ AC_SUBST([ORTP_VERSION])
AC_SUBST([ORTP_DIR])
AC_ARG_ENABLE(tests_enabled,
[AS_HELP_STRING([--disable-tests], [Disable compilation of tests])],
[case "${enableval}" in
yes) tests_enabled=true ;;
no) tests_enabled=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --disable-tests) ;;
esac],[tests_enabled=false])
[AS_HELP_STRING([--disable-tests], [Disable compilation of tests])],
[case "${enableval}" in
yes) tests_enabled=true ;;
no) tests_enabled=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --disable-tests) ;;
esac],
[tests_enabled=false]
)
AM_CONDITIONAL(ENABLE_TESTS, test x$tests_enabled = xyes)
PKG_CHECK_MODULES(CUNIT, cunit, [found_cunit=yes],[found_cunit=no])
@ -709,44 +786,44 @@ AM_CONDITIONAL(HAVE_DOXYGEN, test $DOXYGEN != false)
AC_CONFIG_FILES([
Makefile
build/Makefile
build/macos/Makefile
build/macos/Info-linphone.plist
m4/Makefile
po/Makefile.in
pixmaps/Makefile
coreapi/Makefile
tester/Makefile
coreapi/help/Makefile
coreapi/help/Doxyfile
gtk/Makefile
console/Makefile
share/Makefile
share/C/Makefile
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
Makefile
build/Makefile
build/macos/Makefile
build/macos/Info-linphone.plist
m4/Makefile
po/Makefile.in
pixmaps/Makefile
coreapi/Makefile
coreapi/help/Makefile
coreapi/help/Doxyfile
tester/Makefile
gtk/Makefile
console/Makefile
share/Makefile
share/C/Makefile
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
])
AC_OUTPUT
echo "Linphone build configuration ended."
echo "Summary of build options:"
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
printf "* %-30s %s\n" "Video support" $video
printf "* %-30s %s\n" "GTK interface" $gtk_ui
printf "* %-30s %s\n" "Account assistant" $build_wizard
printf "* %-30s %s\n" "Console interface" $console_ui
printf "* %-30s %s\n" "Tools" $build_tools
printf "* %-30s %s\n" "zRTP encryption (GPLv3)" $zrtp
if test "$enable_tunnel" = "true" ; then
printf "* Tunnel support\t\ttrue\n"

View file

@ -206,7 +206,7 @@ static LPC_COMMAND commands[] = {
{ "autoanswer", lpc_cmd_autoanswer, "Show/set auto-answer mode",
"'autoanswer' \t: show current autoanswer mode\n"
"'autoanswer enable'\t: enable autoanswer mode\n"
"'autoanswer disable'\t: disable autoanswer mode \n"},
"'autoanswer disable'\t: disable autoanswer mode<EFBFBD><EFBFBD>\n"},
{ "proxy", lpc_cmd_proxy, "Manage proxies",
"'proxy list' : list all proxy setups.\n"
"'proxy add' : add a new proxy setup.\n"
@ -896,6 +896,9 @@ lpc_cmd_firewall(LinphoneCore *lc, char *args)
case LinphonePolicyUseIce:
linphonec_out("Using ice with stun server %s to discover firewall address\n", setting ? setting : linphone_core_get_stun_server(lc));
break;
case LinphonePolicyUseUpnp:
linphonec_out("Using uPnP IGD protocol\n");
break;
}
return 1;
}

View file

@ -44,8 +44,11 @@ liblinphone_la_SOURCES=\
lsd.c linphonecore_utils.h \
ec-calibrator.c \
conference.c \
linphone_tunnel.cc \
$(GITVERSION_FILE)
if BUILD_UPNP
liblinphone_la_SOURCES+=upnp.c upnp.h
endif
if USE_BELLESIP
liblinphone_la_SOURCES+= bellesip_sal/sal_address_impl.c \
@ -65,8 +68,11 @@ if BUILD_WIZARD
liblinphone_la_SOURCES+=sipwizard.c
endif
liblinphone_la_SOURCES+=linphone_tunnel_config.c
if BUILD_TUNNEL
liblinphone_la_SOURCES+=TunnelManager.cc TunnelManager.hh
liblinphone_la_SOURCES+=linphone_tunnel.cc TunnelManager.cc TunnelManager.hh
else
liblinphone_la_SOURCES+=linphone_tunnel_stubs.c
endif

View file

@ -39,17 +39,15 @@ static void sdp_process(SalOp *h){
strcpy(h->result->addr,h->base.remote_media->addr);
h->result->bandwidth=h->base.remote_media->bandwidth;
for(i=0;i<h->result->nstreams;++i){
if (h->result->streams[i].rtp_port>0){
/*fixme add rtcp*/
strcpy(h->result->streams[i].rtp_addr,h->base.remote_media->streams[i].rtp_addr);
h->result->streams[i].ptime=h->base.remote_media->streams[i].ptime;
h->result->streams[i].bandwidth=h->base.remote_media->streams[i].bandwidth;
h->result->streams[i].rtp_port=h->base.remote_media->streams[i].rtp_port;
for(i=0;i<h->result->n_active_streams;++i){
/*fixme add rtcp*/
strcpy(h->result->streams[i].rtp_addr,h->base.remote_media->streams[i].rtp_addr);
h->result->streams[i].ptime=h->base.remote_media->streams[i].ptime;
h->result->streams[i].bandwidth=h->base.remote_media->streams[i].bandwidth;
h->result->streams[i].rtp_port=h->base.remote_media->streams[i].rtp_port;
if (h->result->streams[i].proto == SalProtoRtpSavp) {
h->result->streams[i].crypto[0] = h->base.remote_media->streams[i].crypto[0];
}
if (h->result->streams[i].proto == SalProtoRtpSavp) {
h->result->streams[i].crypto[0] = h->base.remote_media->streams[i].crypto[0];
}
}
}

View file

@ -65,7 +65,7 @@ belle_sdp_session_description_t * media_description_to_sdp(const SalMediaDescrip
belle_sdp_session_description_set_bandwidth(session_desc,"AS",desc->bandwidth);
}
for (i=0; i<desc->nstreams;i++) {
for (i=0; i<desc->n_total_streams;i++) {
media_desc = belle_sdp_media_description_create(sal_stream_type_to_string(desc->streams[i].type)
,desc->streams[i].rtp_port
,1
@ -168,7 +168,8 @@ int sdp_to_media_description(belle_sdp_session_description_t *session_desc, Sal
char tmp[256], tmp2[256];
int nb=0;
desc->nstreams=0;
desc->n_active_streams = 0;
desc->n_total_streams = 0;
if ((cnx=belle_sdp_session_description_get_connection(session_desc)) && belle_sdp_connection_get_address(cnx)) {
strncpy(desc->addr,belle_sdp_connection_get_address(cnx),sizeof(desc->addr));
@ -180,7 +181,7 @@ int sdp_to_media_description(belle_sdp_session_description_t *session_desc, Sal
;media_desc_it!=NULL
;media_desc_it=media_desc_it->next) {
media_desc=BELLE_SDP_MEDIA_DESCRIPTION(media_desc_it->data);
stream=&desc->streams[desc->nstreams];
stream=&desc->streams[desc->n_total_streams];
media=belle_sdp_media_description_get_media(media_desc);
memset(stream,0,sizeof(*stream));
@ -199,6 +200,8 @@ int sdp_to_media_description(belle_sdp_session_description_t *session_desc, Sal
}
stream->rtp_port=belle_sdp_media_get_media_port(media);
if (stream->rtp_port > 0)
desc->n_active_streams++;
mtype = belle_sdp_media_get_media_type(media);
if (strcasecmp("audio", mtype) == 0){
@ -288,7 +291,7 @@ int sdp_to_media_description(belle_sdp_session_description_t *session_desc, Sal
}
ms_message("Found: %d valid crypto lines", valid_count);
}
desc->nstreams++;
desc->n_total_streams++;
}
return 0;

View file

@ -41,14 +41,14 @@ void linphone_core_update_streams_destinations(LinphoneCore *lc, LinphoneCall *c
char *rtp_addr, *rtcp_addr;
int i;
for (i = 0; i < old_md->nstreams; i++) {
for (i = 0; i < old_md->n_active_streams; 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++) {
for (i = 0; i < new_md->n_active_streams; i++) {
if (new_md->streams[i].type == SalAudio) {
new_audiodesc = &new_md->streams[i];
} else if (new_md->streams[i].type == SalVideo) {
@ -261,6 +261,13 @@ static void call_received(SalOp *h){
ms_message("Defer ringing to gather ICE candidates");
return;
}
#ifdef BUILD_UPNP
if ((linphone_core_get_firewall_policy(lc) == LinphonePolicyUseUpnp) && (call->upnp_session != NULL)) {
/* Defer ringing until the end of the ICE candidates gathering process. */
ms_message("Defer ringing to gather uPnP candidates");
return;
}
#endif //BUILD_UPNP
linphone_core_notify_incoming_call(lc,call);
}
@ -334,6 +341,11 @@ static void call_accepted(SalOp *op){
if (call->ice_session != NULL) {
linphone_core_update_ice_from_remote_media_description(call, sal_call_get_remote_media_description(op));
}
#ifdef BUILD_UPNP
if (call->upnp_session != NULL) {
linphone_core_update_upnp_from_remote_media_description(call, sal_call_get_remote_media_description(op));
}
#endif //BUILD_UPNP
md=sal_call_get_final_media_description(op);
call->params.has_video &= linphone_core_media_description_contains_video_stream(md);
@ -426,6 +438,12 @@ static void call_accept_update(LinphoneCore *lc, LinphoneCall *call){
linphone_core_update_ice_from_remote_media_description(call,rmd);
linphone_core_update_local_media_description_from_ice(call->localdesc,call->ice_session);
}
#ifdef BUILD_UPNP
if(call->upnp_session != NULL) {
linphone_core_update_upnp_from_remote_media_description(call, rmd);
linphone_core_update_local_media_description_from_upnp(call->localdesc,call->upnp_session);
}
#endif //BUILD_UPNP
linphone_call_update_remote_session_id_and_ver(call);
sal_call_accept(call->op);
md=sal_call_get_final_media_description(call->op);
@ -522,6 +540,10 @@ static void call_terminated(SalOp *op, const char *from){
if (lc->vtable.display_status!=NULL)
lc->vtable.display_status(lc,_("Call terminated."));
#ifdef BUILD_UPNP
linphone_call_delete_upnp_session(call);
#endif //BUILD_UPNP
linphone_call_set_state(call, LinphoneCallEnd,"Call ended");
}
@ -591,7 +613,7 @@ static void call_failure(SalOp *op, SalError error, SalReason sr, const char *de
if (call->state==LinphoneCallOutgoingInit || call->state==LinphoneCallOutgoingProgress){
/* clear SRTP local params */
call->params.media_encryption = LinphoneMediaEncryptionNone;
for(i=0; i<call->localdesc->nstreams; i++) {
for(i=0; i<call->localdesc->n_active_streams; i++) {
call->localdesc->streams[i].proto = SalProtoRtpAvp;
memset(call->localdesc->streams[i].crypto, 0, sizeof(call->localdesc->streams[i].crypto));
}
@ -618,12 +640,20 @@ static void call_failure(SalOp *op, SalError error, SalReason sr, const char *de
/*resume to the call that send us the refer automatically*/
linphone_core_resume_call(lc,call->referer);
}
#ifdef BUILD_UPNP
linphone_call_delete_upnp_session(call);
#endif //BUILD_UPNP
if (sr == SalReasonDeclined) {
call->reason=LinphoneReasonDeclined;
linphone_call_set_state(call,LinphoneCallEnd,"Call declined.");
} else if (sr == SalReasonNotFound) {
call->reason=LinphoneReasonNotFound;
linphone_call_set_state(call,LinphoneCallError,"User not found.");
} else if (sr == SalReasonBusy) {
call->reason=LinphoneReasonBusy;
linphone_call_set_state(call,LinphoneCallError,"User is busy.");
} else {
linphone_call_set_state(call,LinphoneCallError,msg);
}
@ -815,7 +845,7 @@ static bool_t is_duplicate_msg(LinphoneCore *lc, const char *msg_id){
static void text_received(Sal *sal, const SalMessage *msg){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal);
if (is_duplicate_msg(lc,msg->message_id)==FALSE){
linphone_core_message_received(lc,msg->from,msg->text,msg->url);
linphone_core_message_received(lc,msg);
}
}

View file

@ -103,13 +103,13 @@ void linphone_chat_room_message_received(LinphoneChatRoom *cr, LinphoneCore *lc,
}
void linphone_core_message_received(LinphoneCore *lc, const char *from, const char *raw_msg,const char* external_url){
void linphone_core_message_received(LinphoneCore *lc, const SalMessage *sal_msg){
MSList *elem;
LinphoneChatRoom *cr=NULL;
LinphoneAddress *addr;
char *cleanfrom;
LinphoneChatMessage* msg;
addr=linphone_address_new(from);
addr=linphone_address_new(sal_msg->from);
linphone_address_clean(addr);
for(elem=lc->chatrooms;elem!=NULL;elem=ms_list_next(elem)){
cr=(LinphoneChatRoom*)elem->data;
@ -123,10 +123,12 @@ void linphone_core_message_received(LinphoneCore *lc, const char *from, const ch
/* create a new chat room */
cr=linphone_core_create_chat_room(lc,cleanfrom);
}
msg = linphone_chat_room_create_message(cr, raw_msg);
msg = linphone_chat_room_create_message(cr, sal_msg->text);
linphone_chat_message_set_from(msg, cr->peer_url);
if (external_url) {
linphone_chat_message_set_external_body_url(msg, external_url);
msg->time=sal_msg->time;
if (sal_msg->url) {
linphone_chat_message_set_external_body_url(msg, sal_msg->url);
}
linphone_address_destroy(addr);
linphone_chat_room_message_received(cr,lc,msg);
@ -221,6 +223,11 @@ void linphone_chat_message_set_from(LinphoneChatMessage* message, const Linphone
LinphoneAddress* linphone_chat_message_get_from(const LinphoneChatMessage* message) {
return message->from;
}
time_t linphone_chat_message_get_time(const LinphoneChatMessage* message) {
return message->time;
}
const char * linphone_chat_message_get_text(const LinphoneChatMessage* message) {
return message->message;
}

View file

@ -23,9 +23,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef TUNNEL_ENABLED
#include "TunnelManager.hh"
#endif
#include "linphone_tunnel.h"
#include "linphonecore.h"
#include "private.h"
@ -35,67 +33,6 @@ LinphoneTunnel* linphone_core_get_tunnel(LinphoneCore *lc){
return lc->tunnel;
}
struct _LinphoneTunnelConfig {
char *host;
int port;
int remote_udp_mirror_port;
int delay;
};
LinphoneTunnelConfig *linphone_tunnel_config_new() {
LinphoneTunnelConfig *ltc = ms_new0(LinphoneTunnelConfig,1);
ltc->remote_udp_mirror_port = 12345;
ltc->delay = 1000;
return ltc;
}
void linphone_tunnel_config_set_host(LinphoneTunnelConfig *tunnel, const char *host) {
if(tunnel->host != NULL) {
ms_free(tunnel->host);
tunnel->host = NULL;
}
if(host != NULL && strlen(host)) {
tunnel->host = ms_strdup(host);
}
}
const char *linphone_tunnel_config_get_host(LinphoneTunnelConfig *tunnel) {
return tunnel->host;
}
void linphone_tunnel_config_set_port(LinphoneTunnelConfig *tunnel, int port) {
tunnel->port = port;
}
int linphone_tunnel_config_get_port(LinphoneTunnelConfig *tunnel) {
return tunnel->port;
}
void linphone_tunnel_config_set_remote_udp_mirror_port(LinphoneTunnelConfig *tunnel, int remote_udp_mirror_port) {
tunnel->remote_udp_mirror_port = remote_udp_mirror_port;
}
int linphone_tunnel_config_get_remote_udp_mirror_port(LinphoneTunnelConfig *tunnel) {
return tunnel->remote_udp_mirror_port;
}
void linphone_tunnel_config_set_delay(LinphoneTunnelConfig *tunnel, int delay) {
tunnel->delay = delay;
}
int linphone_tunnel_config_get_delay(LinphoneTunnelConfig *tunnel) {
return tunnel->delay;
}
void linphone_tunnel_config_destroy(LinphoneTunnelConfig *tunnel) {
if(tunnel->host != NULL) {
ms_free(tunnel->host);
}
ms_free(tunnel);
}
#ifdef TUNNEL_ENABLED
struct _LinphoneTunnel {
belledonnecomm::TunnelManager *manager;
MSList *config_list;
@ -122,16 +59,16 @@ void linphone_tunnel_destroy(LinphoneTunnel *tunnel){
static char *linphone_tunnel_config_to_string(const LinphoneTunnelConfig *tunnel_config) {
char *str = NULL;
if(tunnel_config->remote_udp_mirror_port != -1) {
if(linphone_tunnel_config_get_remote_udp_mirror_port(tunnel_config) != -1) {
str = ms_strdup_printf("%s:%d:%d:%d",
tunnel_config->host,
tunnel_config->port,
tunnel_config->remote_udp_mirror_port,
tunnel_config->delay);
linphone_tunnel_config_get_host(tunnel_config),
linphone_tunnel_config_get_port(tunnel_config),
linphone_tunnel_config_get_remote_udp_mirror_port(tunnel_config),
linphone_tunnel_config_get_delay(tunnel_config));
} else {
str = ms_strdup_printf("%s:%d",
tunnel_config->host,
tunnel_config->port);
linphone_tunnel_config_get_host(tunnel_config),
linphone_tunnel_config_get_port(tunnel_config));
}
return str;
}
@ -209,11 +146,14 @@ static void linphone_tunnel_save_config(LinphoneTunnel *tunnel) {
static void linphone_tunnel_add_server_intern(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tunnel_config) {
if(tunnel_config->remote_udp_mirror_port == -1) {
bcTunnel(tunnel)->addServer(tunnel_config->host, tunnel_config->port);
if(linphone_tunnel_config_get_remote_udp_mirror_port(tunnel_config) == -1) {
bcTunnel(tunnel)->addServer(linphone_tunnel_config_get_host(tunnel_config),
linphone_tunnel_config_get_port(tunnel_config));
} else {
bcTunnel(tunnel)->addServer(tunnel_config->host, tunnel_config->port,
tunnel_config->remote_udp_mirror_port, tunnel_config->delay);
bcTunnel(tunnel)->addServer(linphone_tunnel_config_get_host(tunnel_config),
linphone_tunnel_config_get_port(tunnel_config),
linphone_tunnel_config_get_remote_udp_mirror_port(tunnel_config),
linphone_tunnel_config_get_delay(tunnel_config));
}
tunnel->config_list = ms_list_append(tunnel->config_list, tunnel_config);
}
@ -385,60 +325,3 @@ void linphone_tunnel_configure(LinphoneTunnel *tunnel){
linphone_tunnel_enable(tunnel, enabled);
}
#else
/*stubs to avoid to have #ifdef TUNNEL_ENABLED in upper layers*/
void linphone_tunnel_destroy(LinphoneTunnel *tunnel){
}
void linphone_tunnel_add_server(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tunnel_config){
}
void linphone_tunnel_remove_server(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tunnel_config){
}
const MSList *linphone_tunnel_get_servers(LinphoneTunnel *tunnel){
return NULL;
}
void linphone_tunnel_clean_servers(LinphoneTunnel *tunnel){
}
void linphone_tunnel_enable(LinphoneTunnel *tunnel, bool_t enabled){
}
bool_t linphone_tunnel_enabled(LinphoneTunnel *tunnel){
return FALSE;
}
void linphone_tunnel_enable_logs_with_handler(LinphoneTunnel *tunnel, bool_t enabled, OrtpLogFunc logHandler){
}
void linphone_tunnel_set_http_proxy_auth_info(LinphoneTunnel *tunnel, const char* username,const char* passwd){
}
void linphone_tunnel_set_http_proxy(LinphoneTunnel*tunnel, const char *host, int port, const char* username,const char* passwd){
}
void linphone_tunnel_get_http_proxy(LinphoneTunnel*tunnel,const char **host, int *port, const char **username, const char **passwd){
}
void linphone_tunnel_reconnect(LinphoneTunnel *tunnel){
}
void linphone_tunnel_auto_detect(LinphoneTunnel *tunnel){
}
void linphone_tunnel_configure(LinphoneTunnel *tunnel){
}
#endif

View file

@ -68,7 +68,7 @@ void linphone_tunnel_config_set_host(LinphoneTunnelConfig *tunnel, const char *h
*
* @param tunnel configuration object
*/
const char *linphone_tunnel_config_get_host(LinphoneTunnelConfig *tunnel);
const char *linphone_tunnel_config_get_host(const LinphoneTunnelConfig *tunnel);
/**
* Set tls port of server.
@ -83,7 +83,7 @@ void linphone_tunnel_config_set_port(LinphoneTunnelConfig *tunnel, int port);
*
* @param tunnel configuration object
*/
int linphone_tunnel_config_get_port(LinphoneTunnelConfig *tunnel);
int linphone_tunnel_config_get_port(const LinphoneTunnelConfig *tunnel);
/**
* Set the remote port on the tunnel server side used to test udp reachability.
@ -98,7 +98,7 @@ void linphone_tunnel_config_set_remote_udp_mirror_port(LinphoneTunnelConfig *tun
*
* @param tunnel configuration object
*/
int linphone_tunnel_config_get_remote_udp_mirror_port(LinphoneTunnelConfig *tunnel);
int linphone_tunnel_config_get_remote_udp_mirror_port(const LinphoneTunnelConfig *tunnel);
/**
* Set the udp packet round trip delay in ms for a tunnel configuration.
@ -113,7 +113,7 @@ void linphone_tunnel_config_set_delay(LinphoneTunnelConfig *tunnel, int delay);
*
* @param tunnel configuration object
*/
int linphone_tunnel_config_get_delay(LinphoneTunnelConfig *tunnel);
int linphone_tunnel_config_get_delay(const LinphoneTunnelConfig *tunnel);
/**
* Destroy a tunnel configuration

View file

@ -0,0 +1,83 @@
/***************************************************************************
* linphone_tunnel_config.c
*
* Copyright 2012 Belledonne Communications
****************************************************************************/
/*
* 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 "linphone_tunnel.h"
struct _LinphoneTunnelConfig {
char *host;
int port;
int remote_udp_mirror_port;
int delay;
};
LinphoneTunnelConfig *linphone_tunnel_config_new() {
LinphoneTunnelConfig *ltc = ms_new0(LinphoneTunnelConfig,1);
ltc->remote_udp_mirror_port = 12345;
ltc->delay = 1000;
return ltc;
}
void linphone_tunnel_config_set_host(LinphoneTunnelConfig *tunnel, const char *host) {
if(tunnel->host != NULL) {
ms_free(tunnel->host);
tunnel->host = NULL;
}
if(host != NULL && strlen(host)) {
tunnel->host = ms_strdup(host);
}
}
const char *linphone_tunnel_config_get_host(const LinphoneTunnelConfig *tunnel) {
return tunnel->host;
}
void linphone_tunnel_config_set_port(LinphoneTunnelConfig *tunnel, int port) {
tunnel->port = port;
}
int linphone_tunnel_config_get_port(const LinphoneTunnelConfig *tunnel) {
return tunnel->port;
}
void linphone_tunnel_config_set_remote_udp_mirror_port(LinphoneTunnelConfig *tunnel, int remote_udp_mirror_port) {
tunnel->remote_udp_mirror_port = remote_udp_mirror_port;
}
int linphone_tunnel_config_get_remote_udp_mirror_port(const LinphoneTunnelConfig *tunnel) {
return tunnel->remote_udp_mirror_port;
}
void linphone_tunnel_config_set_delay(LinphoneTunnelConfig *tunnel, int delay) {
tunnel->delay = delay;
}
int linphone_tunnel_config_get_delay(const LinphoneTunnelConfig *tunnel) {
return tunnel->delay;
}
void linphone_tunnel_config_destroy(LinphoneTunnelConfig *tunnel) {
if(tunnel->host != NULL) {
ms_free(tunnel->host);
}
ms_free(tunnel);
}

View file

@ -0,0 +1,83 @@
/***************************************************************************
* linphone_tunnel.cc
*
* Fri Dec 9, 2011
* Copyright 2011 Belledonne Communications
* Author: Guillaume Beraudo
* Email: guillaume dot beraudo at linphone dot 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 "linphone_tunnel.h"
#include "linphonecore.h"
#include "private.h"
#include "lpconfig.h"
LinphoneTunnel* linphone_core_get_tunnel(LinphoneCore *lc){
return lc->tunnel;
}
/*stubs to avoid to have #ifdef TUNNEL_ENABLED in upper layers*/
void linphone_tunnel_destroy(LinphoneTunnel *tunnel){
}
void linphone_tunnel_add_server(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tunnel_config){
}
void linphone_tunnel_remove_server(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tunnel_config){
}
const MSList *linphone_tunnel_get_servers(LinphoneTunnel *tunnel){
return NULL;
}
void linphone_tunnel_clean_servers(LinphoneTunnel *tunnel){
}
void linphone_tunnel_enable(LinphoneTunnel *tunnel, bool_t enabled){
}
bool_t linphone_tunnel_enabled(LinphoneTunnel *tunnel){
return FALSE;
}
void linphone_tunnel_enable_logs_with_handler(LinphoneTunnel *tunnel, bool_t enabled, OrtpLogFunc logHandler){
}
void linphone_tunnel_set_http_proxy_auth_info(LinphoneTunnel *tunnel, const char* username,const char* passwd){
}
void linphone_tunnel_set_http_proxy(LinphoneTunnel*tunnel, const char *host, int port, const char* username,const char* passwd){
}
void linphone_tunnel_get_http_proxy(LinphoneTunnel*tunnel,const char **host, int *port, const char **username, const char **passwd){
}
void linphone_tunnel_reconnect(LinphoneTunnel *tunnel){
}
void linphone_tunnel_auto_detect(LinphoneTunnel *tunnel){
}
void linphone_tunnel_configure(LinphoneTunnel *tunnel){
}

View file

@ -173,9 +173,10 @@ void linphone_call_set_authentication_token_verified(LinphoneCall *call, bool_t
propagate_encryption_changed(call);
}
static MSList *make_codec_list(LinphoneCore *lc, const MSList *codecs, int bandwidth_limit,int* max_sample_rate){
static MSList *make_codec_list(LinphoneCore *lc, const MSList *codecs, int bandwidth_limit,int* max_sample_rate, int nb_codecs_limit){
MSList *l=NULL;
const MSList *it;
int nb = 0;
if (max_sample_rate) *max_sample_rate=0;
for(it=codecs;it!=NULL;it=it->next){
PayloadType *pt=(PayloadType*)it->data;
@ -186,26 +187,30 @@ static MSList *make_codec_list(LinphoneCore *lc, const MSList *codecs, int bandw
}
if (linphone_core_check_payload_type_usability(lc,pt)){
l=ms_list_append(l,payload_type_clone(pt));
nb++;
if (max_sample_rate && payload_type_get_rate(pt)>*max_sample_rate) *max_sample_rate=payload_type_get_rate(pt);
}
}
if ((nb_codecs_limit > 0) && (nb >= nb_codecs_limit)) break;
}
return l;
}
static void update_media_description_from_stun(SalMediaDescription *md, const StunCandidate *ac, const StunCandidate *vc){
if (ac->port!=0){
strcpy(md->streams[0].rtp_addr,ac->addr);
md->streams[0].rtp_port=ac->port;
if ((ac->addr[0]!='\0' && vc->addr[0]!='\0' && strcmp(ac->addr,vc->addr)==0) || md->nstreams==1){
strcpy(md->addr,ac->addr);
int i;
for (i = 0; i < md->n_active_streams; i++) {
if ((md->streams[i].type == SalAudio) && (ac->port != 0)) {
strcpy(md->streams[0].rtp_addr,ac->addr);
md->streams[0].rtp_port=ac->port;
if ((ac->addr[0]!='\0' && vc->addr[0]!='\0' && strcmp(ac->addr,vc->addr)==0) || md->n_active_streams==1){
strcpy(md->addr,ac->addr);
}
}
if ((md->streams[i].type == SalVideo) && (vc->port != 0)) {
strcpy(md->streams[1].rtp_addr,vc->addr);
md->streams[1].rtp_port=vc->port;
}
}
if (vc->port!=0){
strcpy(md->streams[1].rtp_addr,vc->addr);
md->streams[1].rtp_port=vc->port;
}
}
void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *call){
@ -218,12 +223,13 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *
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);
linphone_core_adapt_to_network(lc,call->ping_time,&call->params);
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;
md->n_total_streams=(old_md ? old_md->n_total_streams : 1);
md->n_active_streams=1;
strncpy(md->addr,call->localip,sizeof(md->addr));
strncpy(md->username,username,sizeof(md->username));
@ -243,22 +249,35 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *
md->streams[0].ptime=call->params.down_ptime;
else
md->streams[0].ptime=linphone_core_get_download_ptime(lc);
l=make_codec_list(lc,lc->codecs_conf.audio_codecs,call->params.audio_bw,&md->streams[0].max_rate);
l=make_codec_list(lc,lc->codecs_conf.audio_codecs,call->params.audio_bw,&md->streams[0].max_rate,-1);
pt=payload_type_clone(rtp_profile_get_payload_from_mime(lc->default_profile,"telephone-event"));
l=ms_list_append(l,pt);
md->streams[0].payloads=l;
if (call->params.has_video){
md->nstreams++;
md->n_active_streams++;
md->streams[1].rtp_port=call->video_port;
md->streams[1].rtcp_port=call->video_port+1;
md->streams[1].proto=md->streams[0].proto;
md->streams[1].type=SalVideo;
l=make_codec_list(lc,lc->codecs_conf.video_codecs,0,NULL);
l=make_codec_list(lc,lc->codecs_conf.video_codecs,0,NULL,-1);
md->streams[1].payloads=l;
}
for(i=0; i<md->nstreams; i++) {
if (md->n_total_streams < md->n_active_streams)
md->n_total_streams = md->n_active_streams;
/* Deactivate inactive streams. */
for (i = md->n_active_streams; i < md->n_total_streams; i++) {
md->streams[i].rtp_port = 0;
md->streams[i].rtcp_port = 0;
md->streams[i].proto = SalProtoRtpAvp;
md->streams[i].type = old_md->streams[i].type;
md->streams[i].dir = SalStreamInactive;
l = make_codec_list(lc, lc->codecs_conf.video_codecs, 0, NULL, 1);
md->streams[i].payloads = l;
}
for(i=0; i<md->n_active_streams; i++) {
if (md->streams[i].proto == SalProtoRtpSavp) {
if (keep_srtp_keys && old_md && old_md->streams[i].proto==SalProtoRtpSavp){
int j;
@ -283,6 +302,12 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *
linphone_core_update_local_media_description_from_ice(md, call->ice_session);
linphone_core_update_ice_state_in_call_stats(call);
}
#ifdef BUILD_UPNP
if(call->upnp_session != NULL) {
linphone_core_update_local_media_description_from_upnp(md, call->upnp_session);
linphone_core_update_upnp_state_in_call_stats(call);
}
#endif //BUILD_UPNP
linphone_address_destroy(addr);
call->localdesc=md;
if (old_md) sal_media_description_unref(old_md);
@ -416,6 +441,11 @@ void linphone_call_init_stats(LinphoneCallStats *stats, int type) {
stats->received_rtcp = NULL;
stats->sent_rtcp = NULL;
stats->ice_state = LinphoneIceStateNotActivated;
#ifdef BUILD_UPNP
stats->upnp_state = LinphoneUpnpStateIdle;
#else
stats->upnp_state = LinphoneUpnpStateNotAvailable;
#endif //BUILD_UPNP
}
@ -449,6 +479,11 @@ LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddr
if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseStun) {
call->ping_time=linphone_core_run_stun_tests(call->core,call);
}
#ifdef BUILD_UPNP
if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseUpnp) {
call->upnp_session = linphone_upnp_session_new(call);
}
#endif //BUILD_UPNP
call->camera_active=params->has_video;
discover_mtu(lc,linphone_address_get_domain (to));
@ -510,6 +545,19 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro
case LinphonePolicyUseStun:
call->ping_time=linphone_core_run_stun_tests(call->core,call);
/* No break to also destroy ice session in this case. */
break;
case LinphonePolicyUseUpnp:
#ifdef BUILD_UPNP
call->upnp_session = linphone_upnp_session_new(call);
if (call->upnp_session != NULL) {
linphone_call_init_media_streams(call);
if (linphone_core_update_upnp_from_remote_media_description(call, sal_call_get_remote_media_description(op))<0) {
/* uPnP port mappings failed, proceed with the call anyway. */
linphone_call_delete_upnp_session(call);
}
}
#endif //BUILD_UPNP
break;
default:
break;
}
@ -658,6 +706,9 @@ void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const
static void linphone_call_destroy(LinphoneCall *obj)
{
#ifdef BUILD_UPNP
linphone_call_delete_upnp_session(obj);
#endif //BUILD_UPNP
linphone_call_delete_ice_session(obj);
if (obj->op!=NULL) {
sal_op_release(obj->op);
@ -847,6 +898,16 @@ const char *linphone_call_get_remote_user_agent(LinphoneCall *call){
return NULL;
}
/**
* Returns the far end's sip contact as a string, if available.
**/
const char *linphone_call_get_remote_contact(LinphoneCall *call){
if (call->op){
return sal_op_get_remote_contact(call->op);
}
return NULL;
}
/**
* Returns true if this calls has received a transfer that has not been
* executed yet.
@ -1727,6 +1788,15 @@ void linphone_call_delete_ice_session(LinphoneCall *call){
}
}
#ifdef BUILD_UPNP
void linphone_call_delete_upnp_session(LinphoneCall *call){
if(call->upnp_session!=NULL) {
linphone_upnp_session_destroy(call->upnp_session);
call->upnp_session=NULL;
}
}
#endif //BUILD_UPNP
static void linphone_call_log_fill_stats(LinphoneCallLog *log, AudioStream *st){
audio_stream_get_local_rtp_stats (st,&log->local_stats);
log->quality=audio_stream_get_average_quality_rating(st);
@ -2037,6 +2107,11 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse
report_bandwidth(call,as,vs);
ms_message("Thread processing load: audio=%f\tvideo=%f",audio_load,video_load);
}
#ifdef BUILD_UPNP
linphone_upnp_call_process(call);
#endif //BUILD_UPNP
#ifdef VIDEO_ENABLED
if (call->videostream!=NULL) {
OrtpEvent *ev;

View file

@ -67,7 +67,6 @@ static void linphone_core_free_hooks(LinphoneCore *lc);
#include "enum.h"
const char *linphone_core_get_nat_address_resolved(LinphoneCore *lc);
void linphone_core_get_local_ip(LinphoneCore *lc, const char *dest, char *result);
static void toggle_video_preview(LinphoneCore *lc, bool_t val);
/* relative path where is stored local ring*/
@ -925,11 +924,14 @@ bool_t linphone_core_tunnel_available(void){
}
/**
* Enable adaptive rate control (experimental feature, audio-only).
* Enable adaptive rate control.
*
* @ingroup media_parameters
*
* Adaptive rate control consists in using RTCP feedback provided information to dynamically
* control the output bitrate of the encoders, so that we can adapt to the network conditions and
* available bandwidth.
* control the output bitrate of the audio and video encoders, so that we can adapt to the network conditions and
* available bandwidth. Control of the audio encoder is done in case of audio-only call, and control of the video encoder is done for audio & video calls.
* Adaptive rate control feature is enabled by default.
**/
void linphone_core_enable_adaptive_rate_control(LinphoneCore *lc, bool_t enabled){
lp_config_set_int(lc->config,"net","adaptive_rate_control",(int)enabled);
@ -937,6 +939,8 @@ void linphone_core_enable_adaptive_rate_control(LinphoneCore *lc, bool_t enabled
/**
* Returns whether adaptive rate control is enabled.
*
* @ingroup media_parameters
*
* See linphone_core_enable_adaptive_rate_control().
**/
@ -1009,14 +1013,18 @@ int linphone_core_get_upload_bandwidth(const LinphoneCore *lc){
return lc->net_conf.upload_bw;
}
/**
* Set audio packetization time linphone expects to receive from peer
* Set audio packetization time linphone expects to receive from peer.
* A value of zero means that ptime is not specified.
* @ingroup media_parameters
*/
void linphone_core_set_download_ptime(LinphoneCore *lc, int ptime) {
lp_config_set_int(lc->config,"rtp","download_ptime",ptime);
}
/**
* Get audio packetization time linphone expects to receive from peer
* Get audio packetization time linphone expects to receive from peer.
* A value of zero means that ptime is not specified.
* @ingroup media_parameters
*/
int linphone_core_get_download_ptime(LinphoneCore *lc) {
return lp_config_get_int(lc->config,"rtp","download_ptime",0);
@ -1026,6 +1034,7 @@ int linphone_core_get_download_ptime(LinphoneCore *lc) {
* Set audio packetization time linphone will send (in absence of requirement from peer)
* A value of 0 stands for the current codec default packetization time.
*
* @ingroup media_parameters
**/
void linphone_core_set_upload_ptime(LinphoneCore *lc, int ptime){
lp_config_set_int(lc->config,"rtp","upload_ptime",ptime);
@ -1035,6 +1044,8 @@ void linphone_core_set_upload_ptime(LinphoneCore *lc, int ptime){
* Set audio packetization time linphone will send (in absence of requirement from peer)
* A value of 0 stands for the current codec default packetization time.
*
*
* @ingroup media_parameters
**/
int linphone_core_get_upload_ptime(LinphoneCore *lc){
return lp_config_get_int(lc->config,"rtp","upload_ptime",0);
@ -1228,6 +1239,9 @@ static void linphone_core_init (LinphoneCore * lc, const LinphoneCoreVTable *vta
lc->tunnel=linphone_core_tunnel_new(lc);
if (lc->tunnel) linphone_tunnel_configure(lc->tunnel);
#endif
#ifdef BUILD_UPNP
lc->upnp = linphone_upnp_context_new(lc);
#endif //BUILD_UPNP
if (lc->vtable.display_status)
lc->vtable.display_status(lc,_("Ready"));
lc->auto_net_state_mon=lc->sip_conf.auto_net_state_mon;
@ -1268,6 +1282,7 @@ LinphoneCore *linphone_core_new(const LinphoneCoreVTable *vtable,
* structure holding the codec information.
* It is possible to make copy of the list with ms_list_copy() in order to modify it
* (such as the order of codecs).
* @ingroup media_parameters
**/
const MSList *linphone_core_get_audio_codecs(const LinphoneCore *lc)
{
@ -1281,6 +1296,7 @@ const MSList *linphone_core_get_audio_codecs(const LinphoneCore *lc)
* structure holding the codec information.
* It is possible to make copy of the list with ms_list_copy() in order to modify it
* (such as the order of codecs).
* @ingroup media_parameters
**/
const MSList *linphone_core_get_video_codecs(const LinphoneCore *lc)
{
@ -1321,6 +1337,14 @@ void linphone_core_get_local_ip(LinphoneCore *lc, const char *dest, char *result
strncpy(result,ip,LINPHONE_IPADDR_SIZE);
return;
}
#ifdef BUILD_UPNP
else if (lc->upnp != NULL && linphone_core_get_firewall_policy(lc)==LinphonePolicyUseUpnp &&
linphone_upnp_context_get_state(lc->upnp) == LinphoneUpnpStateOk) {
ip = linphone_upnp_context_get_external_ipaddress(lc->upnp);
strncpy(result,ip,LINPHONE_IPADDR_SIZE);
return;
}
#endif //BUILD_UPNP
if (linphone_core_get_local_ip_for(lc->sip_conf.ipv6_enabled ? AF_INET6 : AF_INET,dest,result)==0)
return;
/*else fallback to SAL routine that will attempt to find the most realistic interface */
@ -1570,6 +1594,7 @@ void linphone_core_set_audio_port(LinphoneCore *lc, int port)
/**
* Sets the UDP port range from which to randomly select the port used for audio streaming.
* @ingroup media_parameters
*/
void linphone_core_set_audio_port_range(LinphoneCore *lc, int min_port, int max_port)
{
@ -1588,6 +1613,7 @@ void linphone_core_set_video_port(LinphoneCore *lc, int port){
/**
* Sets the UDP port range from which to randomly select the port used for video streaming.
* @ingroup media_parameters
*/
void linphone_core_set_video_port_range(LinphoneCore *lc, int min_port, int max_port)
{
@ -2016,6 +2042,12 @@ void linphone_core_iterate(LinphoneCore *lc){
linphone_call_delete_ice_session(call);
linphone_call_stop_media_streams_for_ice_gathering(call);
}
#ifdef BUILD_UPNP
if (call->upnp_session != NULL) {
ms_warning("uPnP mapping has not finished yet, proceeded with the call without uPnP anyway.");
linphone_call_delete_upnp_session(call);
}
#endif //BUILD_UPNP
linphone_core_start_invite(lc,call);
}
if (call->state==LinphoneCallIncomingReceived){
@ -2061,6 +2093,8 @@ void linphone_core_iterate(LinphoneCore *lc){
/**
* Interpret a call destination as supplied by the user, and returns a fully qualified
* LinphoneAddress.
*
* @ingroup call_control
*
* A sip address should look like DisplayName <sip:username@domain:port> .
* Basically this function performs the following tasks
@ -2269,6 +2303,7 @@ static char *get_fixed_contact(LinphoneCore *lc, LinphoneCall *call , LinphonePr
int linphone_core_proceed_with_invite_if_ready(LinphoneCore *lc, LinphoneCall *call, LinphoneProxyConfig *dest_proxy){
bool_t ice_ready = FALSE;
bool_t upnp_ready = FALSE;
bool_t ping_ready = FALSE;
if (call->ice_session != NULL) {
@ -2276,13 +2311,20 @@ int linphone_core_proceed_with_invite_if_ready(LinphoneCore *lc, LinphoneCall *c
} else {
ice_ready = TRUE;
}
#ifdef BUILD_UPNP
if (call->upnp_session != NULL) {
if (linphone_upnp_session_get_state(call->upnp_session) == LinphoneUpnpStateOk) upnp_ready = TRUE;
} else {
upnp_ready = TRUE;
}
#endif //BUILD_UPNP
if (call->ping_op != NULL) {
if (call->ping_replied == TRUE) ping_ready = TRUE;
} else {
ping_ready = TRUE;
}
if ((ice_ready == TRUE) && (ping_ready == TRUE)) {
if ((ice_ready == TRUE) && (upnp_ready == TRUE) && (ping_ready == TRUE)) {
return linphone_core_start_invite(lc, call);
}
return 0;
@ -2431,7 +2473,7 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const
SalAddress *proxy_addr=NULL;
char *real_url=NULL;
LinphoneCall *call;
bool_t use_ice = FALSE;
bool_t defer = FALSE;
linphone_core_preempt_sound_resources(lc);
@ -2529,9 +2571,21 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const
linphone_call_delete_ice_session(call);
linphone_call_stop_media_streams_for_ice_gathering(call);
} else {
use_ice = TRUE;
defer = TRUE;
}
}
else if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseUpnp) {
#ifdef BUILD_UPNP
linphone_call_init_media_streams(call);
call->start_time=time(NULL);
if (linphone_core_update_upnp(lc,call)<0) {
/* uPnP port mappings failed, proceed with the call anyway. */
linphone_call_delete_upnp_session(call);
} else {
defer = TRUE;
}
#endif //BUILD_UPNP
}
if (call->dest_proxy==NULL && lc->sip_conf.ping_with_options==TRUE){
/*defer the start of the call after the OPTIONS ping*/
@ -2541,7 +2595,7 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const
sal_op_set_user_pointer(call->ping_op,call);
call->start_time=time(NULL);
}else{
if (use_ice==FALSE) linphone_core_start_invite(lc,call);
if (defer==FALSE) linphone_core_start_invite(lc,call);
}
if (real_url!=NULL) ms_free(real_url);
@ -2551,6 +2605,7 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const
/**
* Performs a simple call transfer to the specified destination.
*
* @ingroup call_control
* The remote endpoint is expected to issue a new call to the specified destination.
* The current call remains active and thus can be later paused or terminated.
**/
@ -2581,6 +2636,8 @@ int linphone_core_transfer_call(LinphoneCore *lc, LinphoneCall *call, const char
* @param lc linphone core object
* @param call a running call you want to transfer
* @param dest a running call whose remote person will receive the transfer
*
* @ingroup call_control
*
* The transfered call is supposed to be in paused state, so that it is able to accept the transfer immediately.
* The destination call is a call previously established to introduce the transfered person.
@ -2608,7 +2665,7 @@ bool_t linphone_core_inc_invite_pending(LinphoneCore*lc){
bool_t linphone_core_incompatible_security(LinphoneCore *lc, SalMediaDescription *md){
if (linphone_core_is_media_encryption_mandatory(lc) && linphone_core_get_media_encryption(lc)==LinphoneMediaEncryptionSRTP){
int i;
for(i=0;i<md->nstreams;i++){
for(i=0;i<md->n_active_streams;i++){
SalStreamDescription *sd=&md->streams[i];
if (sd->proto!=SalProtoRtpSavp){
return TRUE;
@ -2695,9 +2752,14 @@ void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call){
int linphone_core_start_update_call(LinphoneCore *lc, LinphoneCall *call){
const char *subject;
call->camera_active=call->params.has_video;
if (call->ice_session != NULL)
if (call->ice_session != NULL) {
linphone_core_update_local_media_description_from_ice(call->localdesc, call->ice_session);
}
#ifdef BUILD_UPNP
if(call->upnp_session != NULL) {
linphone_core_update_local_media_description_from_upnp(call->localdesc, call->upnp_session);
}
#endif //BUILD_UPNP
if (call->params.in_conference){
subject="Conference";
}else{
@ -2729,21 +2791,53 @@ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const Linpho
linphone_call_set_state(call,LinphoneCallUpdating,"Updating call");
#ifdef VIDEO_ENABLED
bool_t has_video = call->params.has_video;
if ((call->ice_session != NULL) && (call->videostream != NULL) && !params->has_video) {
ice_session_remove_check_list(call->ice_session, call->videostream->ms.ice_check_list);
call->videostream->ms.ice_check_list = NULL;
// Video removing
if((call->videostream != NULL) && !params->has_video) {
if (call->ice_session != NULL) {
ice_session_remove_check_list(call->ice_session, call->videostream->ms.ice_check_list);
call->videostream->ms.ice_check_list = NULL;
}
#ifdef BUILD_UPNP
if(call->upnp_session != NULL) {
if (linphone_core_update_upnp(lc, call)<0) {
/* uPnP port mappings failed, proceed with the call anyway. */
linphone_call_delete_upnp_session(call);
}
}
#endif //BUILD_UPNP
}
call->params = *params;
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");
linphone_call_init_video_stream(call);
video_stream_prepare_video(call->videostream);
if (linphone_core_gather_ice_candidates(lc,call)<0) {
/* Ice candidates gathering failed, proceed with the call anyway. */
linphone_call_delete_ice_session(call);
} else return err;
// Video adding
if (!has_video && call->params.has_video) {
if (call->ice_session != NULL) {
/* Defer call update until the ICE candidates gathering process has finished. */
ms_message("Defer call update to gather ICE candidates");
linphone_call_init_video_stream(call);
video_stream_prepare_video(call->videostream);
if (linphone_core_gather_ice_candidates(lc,call)<0) {
/* Ice candidates gathering failed, proceed with the call anyway. */
linphone_call_delete_ice_session(call);
} else {
return err;
}
}
#ifdef BUILD_UPNP
if(call->upnp_session != NULL) {
ms_message("Defer call update to add uPnP port mappings");
linphone_call_init_video_stream(call);
video_stream_prepare_video(call->videostream);
if (linphone_core_update_upnp(lc, call)<0) {
/* uPnP port mappings failed, proceed with the call anyway. */
linphone_call_delete_upnp_session(call);
} else {
return err;
}
}
#endif //BUILD_UPNP
}
#endif
err = linphone_core_start_update_call(lc, call);
@ -2793,6 +2887,11 @@ int linphone_core_start_accept_call_update(LinphoneCore *lc, LinphoneCall *call)
}
linphone_core_update_local_media_description_from_ice(call->localdesc, call->ice_session);
}
#ifdef BUILD_UPNP
if(call->upnp_session != NULL) {
linphone_core_update_local_media_description_from_upnp(call->localdesc, call->upnp_session);
}
#endif //BUILD_UPNP
linphone_call_update_remote_session_id_and_ver(call);
sal_call_set_local_media_description(call->op,call->localdesc);
sal_call_accept(call->op);
@ -2871,8 +2970,25 @@ int linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, const
} else return 0;
}
}
#endif
#endif //VIDEO_ENABLED
}
#if BUILD_UPNP
if(call->upnp_session != NULL) {
linphone_core_update_upnp_from_remote_media_description(call, sal_call_get_remote_media_description(call->op));
#ifdef VIDEO_ENABLED
if ((call->params.has_video) && (call->params.has_video != old_has_video)) {
linphone_call_init_video_stream(call);
video_stream_prepare_video(call->videostream);
if (linphone_core_update_upnp(lc, call)<0) {
/* uPnP update failed, proceed with the call anyway. */
linphone_call_delete_upnp_session(call);
} else return 0;
}
#endif //VIDEO_ENABLED
}
#endif //BUILD_UPNP
linphone_core_start_accept_call_update(lc, call);
return 0;
}
@ -3011,6 +3127,11 @@ int linphone_core_abort_call(LinphoneCore *lc, LinphoneCall *call, const char *e
lc->ringstream=NULL;
}
linphone_call_stop_media_streams(call);
#ifdef BUILD_UPNP
linphone_call_delete_upnp_session(call);
#endif //BUILD_UPNP
if (lc->vtable.display_status!=NULL)
lc->vtable.display_status(lc,_("Call aborted") );
linphone_call_set_state(call,LinphoneCallError,error);
@ -3029,6 +3150,11 @@ static void terminate_call(LinphoneCore *lc, LinphoneCall *call){
}
linphone_call_stop_media_streams(call);
#ifdef BUILD_UPNP
linphone_call_delete_upnp_session(call);
#endif //BUILD_UPNP
if (lc->vtable.display_status!=NULL)
lc->vtable.display_status(lc,_("Call ended") );
linphone_call_set_state(call,LinphoneCallEnd,"Call terminated");
@ -3078,6 +3204,9 @@ int linphone_core_terminate_call(LinphoneCore *lc, LinphoneCall *the_call)
/**
* Decline a pending incoming call, with a reason.
*
* @ingroup call_control
*
* @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
@ -3169,8 +3298,14 @@ int linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *call)
return -1;
}
linphone_call_make_local_media_description(lc,call);
if (call->ice_session != NULL)
if (call->ice_session != NULL) {
linphone_core_update_local_media_description_from_ice(call->localdesc, call->ice_session);
}
#ifdef BUILD_UPNP
if(call->upnp_session != NULL) {
linphone_core_update_local_media_description_from_upnp(call->localdesc, call->upnp_session);
}
#endif //BUILD_UPNP
if (sal_media_description_has_dir(call->resultdesc,SalStreamSendRecv)){
sal_media_description_set_dir(call->localdesc,SalStreamSendOnly);
subject="Call on hold";
@ -3197,6 +3332,7 @@ int linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *call)
/**
* Pause all currently running calls.
* @ingroup call_control
**/
int linphone_core_pause_all_calls(LinphoneCore *lc){
const MSList *elem;
@ -3248,8 +3384,14 @@ int linphone_core_resume_call(LinphoneCore *lc, LinphoneCall *the_call)
if (call->audiostream) audio_stream_play(call->audiostream, NULL);
linphone_call_make_local_media_description(lc,the_call);
if (call->ice_session != NULL)
if (call->ice_session != NULL) {
linphone_core_update_local_media_description_from_ice(call->localdesc, call->ice_session);
}
#ifdef BUILD_UPNP
if(call->upnp_session != NULL) {
linphone_core_update_local_media_description_from_upnp(call->localdesc, call->upnp_session);
}
#endif //BUILD_UPNP
sal_call_set_local_media_description(call->op,call->localdesc);
sal_media_description_set_dir(call->localdesc,SalStreamSendRecv);
if (call->params.in_conference && !call->current_params.in_conference) subject="Conference";
@ -3273,6 +3415,8 @@ static int remote_address_compare(LinphoneCall *call, const LinphoneAddress *rad
* @param lc
* @param remote_address
* @return the LinphoneCall of the call if found
*
* @ingroup call_control
*/
LinphoneCall *linphone_core_get_call_by_remote_address(LinphoneCore *lc, const char *remote_address){
LinphoneAddress *raddr=linphone_address_new(remote_address);
@ -3746,18 +3890,18 @@ const char *linphone_core_get_ring(const LinphoneCore *lc){
* @param path
* @param lc The LinphoneCore object
*
* @ingroup media_parameters
* @ingroup initializing
**/
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)
* Gets the path to a file or folder containing the trusted root CAs (PEM format)
*
* @param lc The LinphoneCore object
*
* @ingroup media_parameters
* @ingroup initializing
**/
const char *linphone_core_get_root_ca(LinphoneCore *lc){
return sal_get_root_ca(lc->sal);
@ -3765,6 +3909,8 @@ const char *linphone_core_get_root_ca(LinphoneCore *lc){
/**
* Specify whether the tls server certificate must be verified when connecting to a SIP/TLS server.
*
* @ingroup initializing
**/
void linphone_core_verify_server_certificates(LinphoneCore *lc, bool_t yesno){
sal_verify_server_certificates(lc->sal,yesno);
@ -3772,6 +3918,7 @@ void linphone_core_verify_server_certificates(LinphoneCore *lc, bool_t yesno){
/**
* Specify whether the tls server certificate common name must be verified when connecting to a SIP/TLS server.
* @ingroup initializing
**/
void linphone_core_verify_server_cn(LinphoneCore *lc, bool_t yesno){
sal_verify_server_cn(lc->sal,yesno);
@ -4698,6 +4845,12 @@ void *linphone_core_get_user_data(LinphoneCore *lc){
return lc->data;
}
/**
* Associate a user pointer to the linphone core.
*
* @ingroup initializing
**/
void linphone_core_set_user_data(LinphoneCore *lc, void *userdata){
lc->data=userdata;
}
@ -4706,6 +4859,13 @@ int linphone_core_get_mtu(const LinphoneCore *lc){
return lc->net_conf.mtu;
}
/**
* Sets the maximum transmission unit size in bytes.
* This information is useful for sending RTP packets.
* Default value is 1500.
*
* @ingroup media_parameters
**/
void linphone_core_set_mtu(LinphoneCore *lc, int mtu){
lc->net_conf.mtu=mtu;
if (mtu>0){
@ -4865,8 +5025,8 @@ void rtp_config_uninit(LinphoneCore *lc)
lp_config_set_int(lc->config,"rtp","audio_jitt_comp",config->audio_jitt_comp);
lp_config_set_int(lc->config,"rtp","video_jitt_comp",config->video_jitt_comp);
lp_config_set_int(lc->config,"rtp","nortp_timeout",config->nortp_timeout);
lp_config_set_int(lc->config,"rtp","audio_jitt_comp_enabled",config->audio_adaptive_jitt_comp_enabled);
lp_config_set_int(lc->config,"rtp","video_jitt_comp_enabled",config->video_adaptive_jitt_comp_enabled);
lp_config_set_int(lc->config,"rtp","audio_adaptive_jitt_comp_enabled",config->audio_adaptive_jitt_comp_enabled);
lp_config_set_int(lc->config,"rtp","video_adaptive_jitt_comp_enabled",config->video_adaptive_jitt_comp_enabled);
}
static void sound_config_uninit(LinphoneCore *lc)
@ -4969,6 +5129,12 @@ static void linphone_core_uninit(LinphoneCore *lc)
usleep(50000);
#endif
}
#ifdef BUILD_UPNP
linphone_upnp_context_destroy(lc->upnp);
lc->upnp = NULL;
#endif //BUILD_UPNP
if (lc->friends)
ms_list_for_each(lc->friends,(void (*)(void *))linphone_friend_close_subscriptions);
linphone_core_set_state(lc,LinphoneGlobalShutdown,"Shutting down");

View file

@ -284,6 +284,27 @@ enum _LinphoneIceState{
**/
typedef enum _LinphoneIceState LinphoneIceState;
/**
* Enum describing uPnP states.
* @ingroup initializing
**/
enum _LinphoneUpnpState{
LinphoneUpnpStateIdle, /**< uPnP is not activate */
LinphoneUpnpStatePending, /**< uPnP process is in progress */
LinphoneUpnpStateAdding, /**< Internal use: Only used by port binding */
LinphoneUpnpStateRemoving, /**< Internal use: Only used by port binding */
LinphoneUpnpStateNotAvailable, /**< uPnP is not available */
LinphoneUpnpStateOk, /**< uPnP is enabled */
LinphoneUpnpStateKo, /**< uPnP processing has failed */
};
/**
* Enum describing uPnP states.
* @ingroup initializing
**/
typedef enum _LinphoneUpnpState LinphoneUpnpState;
/**
* The LinphoneCallStats objects carries various statistic informations regarding quality of audio or video streams.
*
@ -309,6 +330,7 @@ struct _LinphoneCallStats {
mblk_t* sent_rtcp;/**<Last RTCP packet sent, as a mblk_t structure. See oRTP documentation for details how to extract information from it*/
float round_trip_delay; /**<Round trip propagation time in seconds if known, -1 if unknown.*/
LinphoneIceState ice_state; /**< State of ICE processing. */
LinphoneUpnpState upnp_state; /**< State of uPnP processing. */
float download_bandwidth; /**<Download bandwidth measurement of received stream, expressed in kbit/s, including IP/UDP/RTP headers*/
float upload_bandwidth; /**<Download bandwidth measurement of sent stream, expressed in kbit/s, including IP/UDP/RTP headers*/
};
@ -374,6 +396,7 @@ bool_t linphone_call_camera_enabled(const LinphoneCall *lc);
int linphone_call_take_video_snapshot(LinphoneCall *call, const char *file);
LinphoneReason linphone_call_get_reason(const LinphoneCall *call);
const char *linphone_call_get_remote_user_agent(LinphoneCall *call);
const char *linphone_call_get_remote_contact(LinphoneCall *call);
float linphone_call_get_play_volume(LinphoneCall *call);
float linphone_call_get_record_volume(LinphoneCall *call);
float linphone_call_get_current_quality(LinphoneCall *call);
@ -712,7 +735,14 @@ void linphone_chat_message_set_external_body_url(LinphoneChatMessage* message,co
* Get text part of this message
* @return text or NULL if no text.
*/
const char * linphone_chat_message_get_text(const LinphoneChatMessage* message);
const char * linphone_chat_message_get_text(const LinphoneChatMessage* message);
/**
* Get the time the message was sent
* @return time_t or NULL if no time
*/
time_t linphone_chat_message_get_time(const LinphoneChatMessage* message);
/**
* user pointer get function
*/
@ -885,7 +915,8 @@ typedef enum _LinphoneFirewallPolicy{
LinphonePolicyNoFirewall,
LinphonePolicyUseNatAddress,
LinphonePolicyUseStun,
LinphonePolicyUseIce
LinphonePolicyUseIce,
LinphonePolicyUseUpnp,
} LinphoneFirewallPolicy;
typedef enum _LinphoneWaitingState{
@ -1006,16 +1037,8 @@ int linphone_core_get_upload_bandwidth(const LinphoneCore *lc);
void linphone_core_enable_adaptive_rate_control(LinphoneCore *lc, bool_t enabled);
bool_t linphone_core_adaptive_rate_control_enabled(const LinphoneCore *lc);
/**
* set audio packetization time linphone expect to receive from peer
* @ingroup media_parameters
*
*/
void linphone_core_set_download_ptime(LinphoneCore *lc, int ptime);
/**
* get audio packetization time linphone expect to receive from peer, 0 means unspecified
* @ingroup media_parameters
*/
int linphone_core_get_download_ptime(LinphoneCore *lc);
void linphone_core_set_upload_ptime(LinphoneCore *lc, int ptime);
@ -1046,7 +1069,7 @@ int linphone_core_enable_payload_type(LinphoneCore *lc, PayloadType *pt, bool_t
*/
#define LINPHONE_FIND_PAYLOAD_IGNORE_CHANNELS -1
/**
* Get payload type from mime type and clock rate
* Get payload type from mime type and clock rate
* @ingroup media_parameters
* This function searches in audio and video codecs for the given payload type name and clockrate.
* @param lc #LinphoneCore object

View file

@ -1508,7 +1508,17 @@ extern "C" jlong Java_org_linphone_core_LinphoneCallImpl_getRemoteAddress( JNIEn
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));
const char *value=linphone_call_get_remote_user_agent(call);
jstring jvalue=NULL;
if (value) jvalue=env->NewStringUTF(value);
return jvalue;
}
extern "C" jstring Java_org_linphone_core_LinphoneCallImpl_getRemoteContact(JNIEnv *env, jobject thiz, jlong ptr) {
LinphoneCall *call = (LinphoneCall *)ptr;
const char *value=linphone_call_get_remote_contact(call);
jstring jvalue = NULL;
if (value) jvalue=env->NewStringUTF(value);
return jvalue;
}
@ -2229,6 +2239,18 @@ extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_getConfig(JNIEnv *env,
return (jlong) linphone_core_get_config((LinphoneCore *)lc);
}
extern "C" jlong Java_org_linphone_core_LpConfigImpl_newLpConfigImpl(JNIEnv *env, jobject thiz, jstring file) {
const char *cfile = env->GetStringUTFChars(file, NULL);
LpConfig *lp = lp_config_new(cfile);
env->ReleaseStringUTFChars(file, cfile);
return (jlong) lp;
}
extern "C" void Java_org_linphone_core_LpConfigImpl_delete(JNIEnv *env, jobject thiz, jlong lpc) {
LpConfig *lp = (LpConfig *)lpc;
lp_config_destroy(lp);
}
extern "C" void Java_org_linphone_core_LpConfigImpl_setInt(JNIEnv *env, jobject thiz, jlong lpc,
jstring section, jstring key, jint value) {
const char *csection = env->GetStringUTFChars(section, NULL);

View file

@ -215,14 +215,17 @@ LpConfig * lp_config_new(const char *filename){
lpconfig->filename=ortp_strdup(filename);
lpconfig->file=fopen(filename,"rw");
if (lpconfig->file!=NULL){
struct stat fileStat;
lp_config_parse(lpconfig,lpconfig->file);
fclose(lpconfig->file);
fclose(lpconfig->file);
#if !defined(_WIN32_WCE)
/* make existing configuration files non-group/world-accessible */
if (chmod(filename, S_IRUSR | S_IWUSR) == -1)
ms_warning("unable to correct permissions on "
"configuration file: %s",
strerror(errno));
if ((stat(filename,&fileStat) == 0) && (S_ISREG(fileStat.st_mode))) {
/* make existing configuration files non-group/world-accessible */
if (chmod(filename, S_IRUSR | S_IWUSR) == -1) {
ms_warning("unable to correct permissions on "
"configuration file: %s", strerror(errno));
}
}
#endif /*_WIN32_WCE*/
lpconfig->file=NULL;
lpconfig->modified=0;

View file

@ -734,7 +734,7 @@ void linphone_core_update_local_media_description_from_ice(SalMediaDescription *
}
strncpy(desc->ice_pwd, ice_session_local_pwd(session), sizeof(desc->ice_pwd));
strncpy(desc->ice_ufrag, ice_session_local_ufrag(session), sizeof(desc->ice_ufrag));
for (i = 0; i < desc->nstreams; i++) {
for (i = 0; i < desc->n_active_streams; i++) {
SalStreamDescription *stream = &desc->streams[i];
IceCheckList *cl = ice_session_check_list(session, i);
nb_candidates = 0;
@ -838,7 +838,7 @@ void linphone_core_update_ice_from_remote_media_description(LinphoneCall *call,
ice_session_restart(call->ice_session);
ice_restarted = TRUE;
} else {
for (i = 0; i < md->nstreams; i++) {
for (i = 0; i < md->n_total_streams; i++) {
const SalStreamDescription *stream = &md->streams[i];
IceCheckList *cl = ice_session_check_list(call->ice_session, i);
if (cl && (strcmp(stream->rtp_addr, "0.0.0.0") == 0)) {
@ -857,7 +857,7 @@ void linphone_core_update_ice_from_remote_media_description(LinphoneCall *call,
}
ice_session_set_remote_credentials(call->ice_session, md->ice_ufrag, md->ice_pwd);
}
for (i = 0; i < md->nstreams; i++) {
for (i = 0; i < md->n_total_streams; i++) {
const SalStreamDescription *stream = &md->streams[i];
IceCheckList *cl = ice_session_check_list(call->ice_session, i);
if (cl && (stream->ice_pwd[0] != '\0') && (stream->ice_ufrag[0] != '\0')) {
@ -873,7 +873,7 @@ void linphone_core_update_ice_from_remote_media_description(LinphoneCall *call,
}
/* Create ICE check lists if needed and parse ICE attributes. */
for (i = 0; i < md->nstreams; i++) {
for (i = 0; i < md->n_total_streams; i++) {
const SalStreamDescription *stream = &md->streams[i];
IceCheckList *cl = ice_session_check_list(call->ice_session, i);
if (cl == NULL) {
@ -930,7 +930,7 @@ void linphone_core_update_ice_from_remote_media_description(LinphoneCall *call,
}
}
}
for (i = ice_session_nb_check_lists(call->ice_session); i > md->nstreams; i--) {
for (i = ice_session_nb_check_lists(call->ice_session); i > md->n_active_streams; i--) {
ice_session_remove_check_list(call->ice_session, ice_session_check_list(call->ice_session, i - 1));
}
ice_session_check_mismatch(call->ice_session);
@ -948,8 +948,8 @@ bool_t linphone_core_media_description_contains_video_stream(const SalMediaDescr
{
int i;
for (i = 0; i < md->nstreams; i++) {
if ((md->streams[i].type == SalVideo) && (md->streams[i].rtp_port != 0))
for (i = 0; i < md->n_active_streams; i++) {
if (md->streams[i].type == SalVideo)
return TRUE;
}
return FALSE;
@ -1021,14 +1021,15 @@ static int get_local_ip_with_getifaddrs(int type, char *address, int size)
if (ifp->ifa_addr && ifp->ifa_addr->sa_family == type
&& (ifp->ifa_flags & UP_FLAG) && !(ifp->ifa_flags & IFF_LOOPBACK))
{
getnameinfo(ifp->ifa_addr,
if(getnameinfo(ifp->ifa_addr,
(type == AF_INET6) ?
sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in),
address, size, NULL, 0, NI_NUMERICHOST);
if (strchr(address, '%') == NULL) { /*avoid ipv6 link-local addresses */
/*ms_message("getifaddrs() found %s",address);*/
ret++;
break;
address, size, NULL, 0, NI_NUMERICHOST) == 0) {
if (strchr(address, '%') == NULL) { /*avoid ipv6 link-local addresses */
/*ms_message("getifaddrs() found %s",address);*/
ret++;
break;
}
}
}
}
@ -1099,26 +1100,26 @@ static int get_local_ip_for_with_connect(int type, const char *dest, char *resul
}
int linphone_core_get_local_ip_for(int type, const char *dest, char *result){
strcpy(result,type==AF_INET ? "127.0.0.1" : "::1");
strcpy(result,type==AF_INET ? "127.0.0.1" : "::1");
#ifdef HAVE_GETIFADDRS
if (dest==NULL) {
/*we use getifaddrs for lookup of default interface */
int found_ifs;
found_ifs=get_local_ip_with_getifaddrs(type,result,LINPHONE_IPADDR_SIZE);
if (found_ifs==1){
return 0;
}else if (found_ifs<=0){
/*absolutely no network on this machine */
return -1;
}
}
if (dest==NULL) {
/*we use getifaddrs for lookup of default interface */
int found_ifs;
found_ifs=get_local_ip_with_getifaddrs(type,result,LINPHONE_IPADDR_SIZE);
if (found_ifs==1){
return 0;
}else if (found_ifs<=0){
/*absolutely no network on this machine */
return -1;
}
}
#endif
/*else use connect to find the best local ip address */
if (type==AF_INET)
dest="87.98.157.38"; /*a public IP address*/
else dest="2a00:1450:8002::68";
return get_local_ip_for_with_connect(type,dest,result);
/*else use connect to find the best local ip address */
if (type==AF_INET)
dest="87.98.157.38"; /*a public IP address*/
else dest="2a00:1450:8002::68";
return get_local_ip_for_with_connect(type,dest,result);
}
#ifndef WIN32

View file

@ -19,6 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "sal.h"
#include "offeranswer.h"
#include "private.h"
static bool_t only_telephone_event(const MSList *l){
for(;l!=NULL;l=l->next){
@ -267,22 +268,23 @@ static void initiate_incoming(const SalStreamDescription *local_cap,
* and the returned response (remote).
**/
int offer_answer_initiate_outgoing(const SalMediaDescription *local_offer,
const SalMediaDescription *remote_answer,
SalMediaDescription *result){
int i,j;
const SalMediaDescription *remote_answer,
SalMediaDescription *result){
int i,j;
const SalStreamDescription *ls,*rs;
for(i=0,j=0;i<local_offer->nstreams;++i){
for(i=0,j=0;i<local_offer->n_total_streams;++i){
ms_message("Processing for stream %i",i);
ls=&local_offer->streams[i];
rs=sal_media_description_find_stream((SalMediaDescription*)remote_answer,ls->proto,ls->type);
if (rs) {
if (rs) {
initiate_outgoing(ls,rs,&result->streams[j]);
++j;
}
else ms_warning("No matching stream for %i",i);
}
result->nstreams=j;
result->n_active_streams=j;
result->n_total_streams=local_offer->n_total_streams;
result->bandwidth=remote_answer->bandwidth;
strcpy(result->addr,remote_answer->addr);
return 0;
@ -294,12 +296,13 @@ int offer_answer_initiate_outgoing(const SalMediaDescription *local_offer,
* The returned media description is an answer and should be sent to the offerer.
**/
int offer_answer_initiate_incoming(const SalMediaDescription *local_capabilities,
const SalMediaDescription *remote_offer,
SalMediaDescription *result, bool_t one_matching_codec){
const SalMediaDescription *remote_offer,
SalMediaDescription *result, bool_t one_matching_codec){
int i;
const SalStreamDescription *ls=NULL,*rs;
for(i=0;i<remote_offer->nstreams;++i){
result->n_active_streams=0;
for(i=0;i<remote_offer->n_total_streams;++i){
rs=&remote_offer->streams[i];
if (rs->proto!=SalProtoUnknown){
ls=sal_media_description_find_stream((SalMediaDescription*)local_capabilities,rs->proto,rs->type);
@ -310,6 +313,7 @@ int offer_answer_initiate_incoming(const SalMediaDescription *local_capabilities
}else ms_warning("Unknown protocol for mline %i, declining",i);
if (ls){
initiate_incoming(ls,rs,&result->streams[i],one_matching_codec);
result->n_active_streams++;
}
else {
/* create an inactive stream for the answer, as there where no matching stream a local capability */
@ -322,7 +326,7 @@ int offer_answer_initiate_incoming(const SalMediaDescription *local_capabilities
}
}
}
result->nstreams=i;
result->n_total_streams=i;
strcpy(result->username, local_capabilities->username);
strcpy(result->addr,local_capabilities->addr);
result->bandwidth=local_capabilities->bandwidth;

View file

@ -28,9 +28,11 @@
extern "C" {
#endif
#include "linphonecore.h"
#include "linphonefriend.h"
#include "linphone_tunnel.h"
#include "linphonecore_utils.h"
#include "sal.h"
#include "sipsetup.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
@ -38,6 +40,9 @@ extern "C" {
#include "mediastreamer2/ice.h"
#include "mediastreamer2/mediastream.h"
#include "mediastreamer2/msconference.h"
#ifdef BUILD_UPNP
#include "upnp.h"
#endif //BUILD_UPNP
#ifndef LIBLINPHONE_VERSION
#define LIBLINPHONE_VERSION LINPHONE_VERSION
@ -98,6 +103,7 @@ struct _LinphoneChatMessage {
void* message_userdata;
char* external_body_url;
LinphoneAddress* from;
time_t time;
};
typedef struct StunCandidate{
@ -145,6 +151,9 @@ struct _LinphoneCall
OrtpEvQueue *videostream_app_evq;
CallCallbackObj nextVideoFrameDecoded;
LinphoneCallStats stats[2];
#ifdef BUILD_UPNP
UpnpSession *upnp_session;
#endif //BUILD_UPNP
IceSession *ice_session;
LinphoneChatMessage* pending_message;
int ping_time;
@ -278,7 +287,7 @@ void linphone_proxy_config_write_to_config_file(struct _LpConfig* config,Linphon
int linphone_proxy_config_normalize_number(LinphoneProxyConfig *cfg, const char *username, char *result, size_t result_len);
void linphone_core_message_received(LinphoneCore *lc, const char *from, const char *raw_msg,const char* external_url);
void linphone_core_message_received(LinphoneCore *lc, const SalMessage *msg);
void linphone_core_play_tone(LinphoneCore *lc);
@ -293,6 +302,7 @@ void linphone_call_stop_audio_stream(LinphoneCall *call);
void linphone_call_stop_video_stream(LinphoneCall *call);
void linphone_call_stop_media_streams(LinphoneCall *call);
void linphone_call_delete_ice_session(LinphoneCall *call);
void linphone_call_delete_upnp_session(LinphoneCall *call);
void linphone_call_stop_media_streams_for_ice_gathering(LinphoneCall *call);
void linphone_call_update_crypto_parameters(LinphoneCall *call, SalMediaDescription *old_md, SalMediaDescription *new_md);
void linphone_call_update_remote_session_id_and_ver(LinphoneCall *call);
@ -572,8 +582,8 @@ struct _LinphoneCore
bool_t network_reachable;
bool_t use_preview_window;
time_t network_last_check;
bool_t network_last_status;
time_t network_last_check;
bool_t network_last_status;
bool_t ringstream_autorelease;
bool_t pad[3];
@ -582,13 +592,16 @@ struct _LinphoneCore
LinphoneTunnel *tunnel;
char* device_id;
MSList *last_recv_msg_ids;
#ifdef BUILD_UPNP
UpnpContext *upnp;
#endif //BUILD_UPNP
};
LinphoneTunnel *linphone_core_tunnel_new(LinphoneCore *lc);
void linphone_tunnel_destroy(LinphoneTunnel *tunnel);
void linphone_tunnel_configure(LinphoneTunnel *tunnel);
void linphone_tunnel_enable_logs_with_handler(LinphoneTunnel *tunnel, bool_t enabled, OrtpLogFunc logHandler);
bool_t linphone_core_can_we_add_call(LinphoneCore *lc);
int linphone_core_add_call( LinphoneCore *lc, LinphoneCall *call);
int linphone_core_del_call( LinphoneCore *lc, LinphoneCall *call);
@ -656,6 +669,9 @@ 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);
int linphone_upnp_init(LinphoneCore *lc);
void linphone_upnp_destroy(LinphoneCore *lc);
#ifdef __cplusplus
}
#endif

View file

@ -431,7 +431,7 @@ static dial_plan_t const dial_plans[]={
{"Congo Democratic Republic" ,"CD" , "243" , 9 , "00" },
{"Cook Islands" ,"CK" , "682" , 5 , "00" },
{"Costa Rica" ,"CR" , "506" , 8 , "00" },
{"Cte d'Ivoire" ,"AD" , "225" , 8 , "00" },
{"C<EFBFBD>te d'Ivoire" ,"AD" , "225" , 8 , "00" },
{"Croatia" ,"HR" , "385" , 9 , "00" },
{"Cuba" ,"CU" , "53" , 8 , "119" },
{"Cyprus" ,"CY" , "357" , 8 , "00" },
@ -549,7 +549,7 @@ static dial_plan_t const dial_plans[]={
{"Portugal" ,"PT" , "351" , 9 , "00" },
{"Puerto Rico" ,"PR" , "1" , 10 , "011" },
{"Qatar" ,"QA" , "974" , 8 , "00" },
{"RŽunion Island" ,"RE" , "262" , 9 , "011" },
{"R<EFBFBD>union Island" ,"RE" , "262" , 9 , "011" },
{"Romania" ,"RO" , "40" , 9 , "00" },
{"Russian Federation" ,"RU" , "7" , 10 , "8" },
{"Rwanda" ,"RW" , "250" , 9 , "00" },
@ -560,7 +560,7 @@ static dial_plan_t const dial_plans[]={
{"Saint Vincent and the Grenadines","VC" , "1" , 10 , "011" },
{"Samoa" ,"WS" , "685" , 7 , "0" },
{"San Marino" ,"SM" , "378" , 10 , "00" },
{"So TomŽ and Prncipe" ,"ST" , "239" , 7 , "00" },
{"S<EFBFBD>o Tom<6F> and Pr<50>ncipe" ,"ST" , "239" , 7 , "00" },
{"Saudi Arabia" ,"SA" , "966" , 9 , "00" },
{"Senegal" ,"SN" , "221" , 9 , "00" },
{"Serbia" ,"RS" , "381" , 9 , "00" },

View file

@ -77,7 +77,7 @@ void sal_media_description_unref(SalMediaDescription *md){
SalStreamDescription *sal_media_description_find_stream(SalMediaDescription *md,
SalMediaProto proto, SalStreamType type){
int i;
for(i=0;i<md->nstreams;++i){
for(i=0;i<md->n_active_streams;++i){
SalStreamDescription *ss=&md->streams[i];
if (ss->proto==proto && ss->type==type) return ss;
}
@ -85,17 +85,13 @@ SalStreamDescription *sal_media_description_find_stream(SalMediaDescription *md,
}
bool_t sal_media_description_empty(const SalMediaDescription *md){
int i;
for(i=0;i<md->nstreams;++i){
const SalStreamDescription *ss=&md->streams[i];
if (ss->rtp_port!=0) return FALSE;
}
if (md->n_active_streams > 0) return FALSE;
return TRUE;
}
void sal_media_description_set_dir(SalMediaDescription *md, SalStreamDir stream_dir){
int i;
for(i=0;i<md->nstreams;++i){
for(i=0;i<md->n_active_streams;++i){
SalStreamDescription *ss=&md->streams[i];
ss->dir=stream_dir;
}
@ -111,7 +107,7 @@ static bool_t has_dir(const SalMediaDescription *md, SalStreamDir stream_dir){
int i;
/* we are looking for at least one stream with requested direction, inactive streams are ignored*/
for(i=0;i<md->nstreams;++i){
for(i=0;i<md->n_active_streams;++i){
const SalStreamDescription *ss=&md->streams[i];
if (ss->dir==stream_dir) return TRUE;
/*compatibility check for phones that only used the null address and no attributes */
@ -225,9 +221,9 @@ int sal_media_description_equals(const SalMediaDescription *md1, const SalMediaD
int i;
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->n_total_streams != md2->n_total_streams) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED;
if (md1->bandwidth != md2->bandwidth) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED;
for(i = 0; i < md1->nstreams; ++i){
for(i = 0; i < md1->n_total_streams; ++i){
result |= sal_stream_description_equals(&md1->streams[i], &md2->streams[i]);
}
return result;
@ -347,6 +343,10 @@ const char *sal_op_get_contact(const SalOp *op){
return ((SalOpBase*)op)->contact;
}
const char *sal_op_get_remote_contact(const SalOp *op){
return ((SalOpBase*)op)->remote_contact;
}
const char *sal_op_get_route(const SalOp *op){
#ifdef BELLE_SIP
ms_fatal("sal_op_get_route not supported, use sal_op_get_route_addresses instead");
@ -381,6 +381,9 @@ void __sal_op_set_network_origin(SalOp *op, const char *origin){
SET_PARAM(op,origin);
}
void __sal_op_set_remote_contact(SalOp *op, const char *ct){
assign_string(&((SalOpBase*)op)->remote_contact,ct);
}
void __sal_op_set_network_origin_address(SalOp *op, SalAddress *origin){
char* address_string=sal_address_as_string(origin); /*can probably be optimized*/
__sal_op_set_network_origin(op,address_string);
@ -413,6 +416,10 @@ void __sal_op_free(SalOp *op){
ms_free(b->remote_ua);
b->remote_ua=NULL;
}
if (b->remote_contact){
ms_free(b->remote_contact);
b->remote_contact=NULL;
}
if (b->local_media)
sal_media_description_unref(b->local_media);
if (b->remote_media)

View file

@ -181,7 +181,8 @@ typedef struct SalMediaDescription{
int refcount;
char addr[64];
char username[64];
int nstreams;
int n_active_streams;
int n_total_streams;
int bandwidth;
unsigned int session_ver;
unsigned int session_id;
@ -197,6 +198,7 @@ typedef struct SalMessage{
const char *text;
const char *url;
const char *message_id;
time_t time;
}SalMessage;
#define SAL_MEDIA_DESCRIPTION_MAX_MESSAGE_ATTRIBUTES 5
@ -229,6 +231,7 @@ typedef struct SalOpBase{
SalMediaDescription *remote_media;
void *user_pointer;
const char* call_id;
char *remote_contact;
SalAddress* service_route; /*as defined by rfc3608, might be a list*/
} SalOpBase;
@ -412,6 +415,7 @@ const SalAddress *sal_op_get_contact_address(const SalOp *op);
const char *sal_op_get_route(const SalOp *op);
const MSList* sal_op_get_route_addresses(const SalOp *op);
const char *sal_op_get_proxy(const SalOp *op);
const char *sal_op_get_remote_contact(const SalOp *op);
/*for incoming requests, returns the origin of the packet as a sip uri*/
const char *sal_op_get_network_origin(const SalOp *op);
const SalAddress *sal_op_get_network_origin_address(const SalOp *op);
@ -473,7 +477,7 @@ int sal_ping(SalOp *op, const char *from, const char *to);
#define payload_type_set_number(pt,n) (pt)->user_data=(void*)((long)n);
#define payload_type_set_number(pt,n) (pt)->user_data=(void*)((long)n);
#define payload_type_get_number(pt) ((int)(long)(pt)->user_data)
/*misc*/
@ -486,6 +490,7 @@ void sal_disable_logs();
void __sal_op_init(SalOp *b, Sal *sal);
void __sal_op_set_network_origin(SalOp *op, const char *origin /*a sip uri*/);
void __sal_op_set_network_origin_address(SalOp *op, SalAddress *origin);
void __sal_op_set_remote_contact(SalOp *op, const char *ct);
void __sal_op_free(SalOp *b);
/*test api*/

View file

@ -52,7 +52,6 @@ void sal_get_default_local_ip(Sal *sal, int address_family,char *ip, size_t iple
}
}
static SalOp * sal_find_call(Sal *sal, int cid){
const MSList *elem;
SalOp *op;
@ -589,18 +588,15 @@ static void sdp_process(SalOp *h){
strcpy(h->result->addr,h->base.remote_media->addr);
h->result->bandwidth=h->base.remote_media->bandwidth;
for(i=0;i<h->result->nstreams;++i){
if (h->result->streams[i].rtp_port>0){
strcpy(h->result->streams[i].rtp_addr,h->base.remote_media->streams[i].rtp_addr);
strcpy(h->result->streams[i].rtcp_addr,h->base.remote_media->streams[i].rtcp_addr);
h->result->streams[i].ptime=h->base.remote_media->streams[i].ptime;
h->result->streams[i].bandwidth=h->base.remote_media->streams[i].bandwidth;
h->result->streams[i].rtp_port=h->base.remote_media->streams[i].rtp_port;
h->result->streams[i].rtcp_port=h->base.remote_media->streams[i].rtcp_port;
if (h->result->streams[i].proto == SalProtoRtpSavp) {
h->result->streams[i].crypto[0] = h->base.remote_media->streams[i].crypto[0];
}
for(i=0;i<h->result->n_active_streams;++i){
strcpy(h->result->streams[i].rtp_addr,h->base.remote_media->streams[i].rtp_addr);
strcpy(h->result->streams[i].rtcp_addr,h->base.remote_media->streams[i].rtcp_addr);
h->result->streams[i].ptime=h->base.remote_media->streams[i].ptime;
h->result->streams[i].bandwidth=h->base.remote_media->streams[i].bandwidth;
h->result->streams[i].rtp_port=h->base.remote_media->streams[i].rtp_port;
h->result->streams[i].rtcp_port=h->base.remote_media->streams[i].rtcp_port;
if (h->result->streams[i].proto == SalProtoRtpSavp) {
h->result->streams[i].crypto[0] = h->base.remote_media->streams[i].crypto[0];
}
}
}
@ -674,8 +670,11 @@ int sal_call(SalOp *h, const char *from, const char *to){
ms_error("Fail to send invite ! Error code %d", err);
return -1;
}else{
char *tmp=NULL;
callid=osip_message_get_call_id(invite);
osip_call_id_to_str(callid,(char **)(&h->base.call_id));
osip_call_id_to_str(callid,&tmp);
h->base.call_id=ms_strdup(tmp);
osip_free(tmp);
sal_add_call(h->base.root,h);
}
return 0;
@ -1017,6 +1016,19 @@ static void set_remote_ua(SalOp* op, osip_message_t *req){
}
}
static void set_remote_contact(SalOp* op, osip_message_t *req){
if (op->base.remote_contact==NULL){
osip_contact_t *h=NULL;
osip_message_get_contact(req,0,&h);
if (h){
char *tmp=NULL;
osip_contact_to_str(h,&tmp);
__sal_op_set_remote_contact(op,tmp);
osip_free(tmp);
}
}
}
static void set_replaces(SalOp *op, osip_message_t *req){
osip_header_t *h=NULL;
@ -1054,12 +1066,17 @@ static void inc_new_call(Sal *sal, eXosip_event_t *ev){
SalOp *op=sal_op_new(sal);
osip_from_t *from,*to;
osip_call_info_t *call_info;
char *tmp;
char *tmp=NULL;
sdp_message_t *sdp=eXosip_get_sdp_info(ev->request);
osip_call_id_t *callid=osip_message_get_call_id(ev->request);
osip_call_id_to_str(callid,(char**)(&op->base.call_id));
osip_call_id_to_str(callid,&tmp);
op->base.call_id=ms_strdup(tmp);
osip_free(tmp);
set_network_origin(op,ev->request);
set_remote_contact(op,ev->request);
set_remote_ua(op,ev->request);
set_replaces(op,ev->request);
@ -1237,6 +1254,7 @@ static void call_accepted(Sal *sal, eXosip_event_t *ev){
op->did=ev->did;
set_remote_ua(op,ev->response);
set_remote_contact(op,ev->response);
sdp=eXosip_get_sdp_info(ev->response);
if (sdp){
@ -1747,6 +1765,9 @@ static bool_t comes_from_local_if(osip_message_t *msg){
return FALSE;
}
static const char *days[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
static const char *months[]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
static void text_received(Sal *sal, eXosip_event_t *ev){
osip_body_t *body=NULL;
char *from=NULL,*msg=NULL;
@ -1756,6 +1777,26 @@ static void text_received(Sal *sal, eXosip_event_t *ev){
int external_body_size=0;
SalMessage salmsg;
char message_id[256]={0};
osip_header_t *date=NULL;
struct tm ret={};
char tmp1[80]={0};
char tmp2[80]={0};
int i,j;
osip_message_get_date(ev->request,0,&date);
if(date==NULL){
ms_error("Could not get the date of message");
return;
}
sscanf(date->hvalue,"%3c,%d%s%d%d:%d:%d",tmp1,&ret.tm_mday,tmp2,
&ret.tm_year,&ret.tm_hour,&ret.tm_min,&ret.tm_sec);
ret.tm_year-=1900;
for(i=0;i<7;i++) {
if(strcmp(tmp1,days[i])==0) ret.tm_wday=i;
}
for(j=0;j<12;j++) {
if(strcmp(tmp2,months[j])==0) ret.tm_mon=j;
}
content_type= osip_message_get_content_type(ev->request);
if (!content_type) {
@ -1796,6 +1837,7 @@ static void text_received(Sal *sal, eXosip_event_t *ev){
salmsg.text=msg;
salmsg.url=external_body_size>0 ? unquoted_external_body_url : NULL;
salmsg.message_id=message_id;
salmsg.time=mktime(&ret);
sal->callbacks.text_received(sal,&salmsg);
osip_free(from);
}

View file

@ -81,8 +81,22 @@ void sal_remove_in_subscribe(Sal *sal, SalOp *op){
sal->in_subscribes=ms_list_remove(sal->in_subscribes,op);
}
#ifdef WIN32
static inline char *my_ctime_r(const time_t *t, char *buf){
strcpy(buf,ctime(t));
return buf;
}
#else
#define my_ctime_r ctime_r
#endif
int sal_message_send(SalOp *op, const char *from, const char *to, const char* content_type, const char *msg){
osip_message_t *sip=NULL;
time_t t;
time(&t);
char buf[26];
if(op->cid == -1)
{
@ -97,6 +111,7 @@ int sal_message_send(SalOp *op, const char *from, const char *to, const char* co
eXosip_message_build_request(&sip,"MESSAGE",sal_op_get_to(op),
sal_op_get_from(op),sal_op_get_route(op));
if (sip!=NULL){
osip_message_set_date(sip,my_ctime_r(&t,buf));
osip_message_set_content_type(sip,content_type);
if (msg) osip_message_set_body(sip,msg,strlen(msg));
sal_add_other(op->base.root,op,sip);

View file

@ -394,7 +394,7 @@ static void add_line(sdp_message_t *msg, int lineno, const SalStreamDescription
sdp_message_t *media_description_to_sdp(const SalMediaDescription *desc){
int i;
sdp_message_t *msg=create_generic_sdp(desc);
for(i=0;i<desc->nstreams;++i){
for(i=0;i<desc->n_total_streams;++i){
add_line(msg,i,&desc->streams[i]);
}
return msg;
@ -463,6 +463,8 @@ int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc){
}
}
desc->n_active_streams = 0;
/* for each m= line */
for (i=0; !sdp_message_endof_media (msg, i) && i<SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++)
{
@ -486,6 +488,8 @@ int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc){
strncpy(stream->rtp_addr,rtp_addr,sizeof(stream->rtp_addr));
if (rtp_port)
stream->rtp_port=atoi(rtp_port);
if (stream->rtp_port > 0)
desc->n_active_streams++;
stream->ptime=_sdp_message_get_a_ptime(msg,i);
if (strcasecmp("audio", mtype) == 0){
@ -609,6 +613,6 @@ int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc){
}
}
}
desc->nstreams=i;
desc->n_total_streams=i;
return 0;
}

1058
coreapi/upnp.c Normal file

File diff suppressed because it is too large Load diff

45
coreapi/upnp.h Normal file
View file

@ -0,0 +1,45 @@
/*
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 LINPHONE_UPNP_H
#define LINPHONE_UPNP_H
#include "mediastreamer2/upnp_igd.h"
#include "linphonecore.h"
#include "sal.h"
typedef struct _UpnpSession UpnpSession;
typedef struct _UpnpContext UpnpContext;
int linphone_core_update_local_media_description_from_upnp(SalMediaDescription *desc, UpnpSession *session);
int linphone_core_update_upnp_from_remote_media_description(LinphoneCall *call, const SalMediaDescription *md);
int linphone_core_update_upnp(LinphoneCore *lc, LinphoneCall *call);
int linphone_upnp_call_process(LinphoneCall *call);
UpnpSession* linphone_upnp_session_new(LinphoneCall *call);
void linphone_upnp_session_destroy(UpnpSession* session);
LinphoneUpnpState linphone_upnp_session_get_state(UpnpSession *session);
UpnpContext *linphone_upnp_context_new(LinphoneCore *lc);
void linphone_upnp_context_destroy(UpnpContext *ctx);
LinphoneUpnpState linphone_upnp_context_get_state(UpnpContext *ctx);
const char *linphone_upnp_context_get_external_ipaddress(UpnpContext *ctx);
void linphone_core_update_upnp_state_in_call_stats(LinphoneCall *call);
#endif //LINPHONE_UPNP_H

View file

@ -5,6 +5,7 @@ UI_FILES= about.ui \
parameters.ui \
sip_account.ui \
call_logs.ui \
keypad.ui \
log.ui \
buddylookup.ui \
tunnel_config.ui \

View file

@ -1,71 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0"?>
<interface>
<requires lib="gtk+" version="2.24"/>
<!-- interface-naming-policy project-wide -->
<object class="GtkDialog" id="call_statistics">
<property name="can_focus">False</property>
<property name="border_width">5</property>
<property name="title" translatable="yes">Call statistics</property>
<property name="type_hint">dialog</property>
<signal name="response" handler="linphone_gtk_call_statistics_closed" swapped="no"/>
<signal name="response" handler="linphone_gtk_call_statistics_closed"/>
<child internal-child="vbox">
<object class="GtkVBox" id="dialog-vbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">2</property>
<child internal-child="action_area">
<object class="GtkHButtonBox" id="dialog-action_area1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="layout_style">end</property>
<child>
<placeholder/>
</child>
<child>
<object class="GtkButton" id="button1">
<property name="label">gtk-close</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>
<property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkFrame" id="frame1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkAlignment" id="alignment1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="left_padding">12</property>
<child>
<object class="GtkTable" id="table1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="n_rows">6</property>
<property name="n_columns">2</property>
<property name="homogeneous">True</property>
<child>
<object class="GtkLabel" id="audio_codec_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Audio codec</property>
</object>
<packing>
@ -75,7 +38,6 @@
<child>
<object class="GtkLabel" id="video_codec_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Video codec</property>
</object>
<packing>
@ -87,7 +49,6 @@
<child>
<object class="GtkLabel" id="label3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Audio IP bandwidth usage</property>
</object>
<packing>
@ -99,7 +60,6 @@
<child>
<object class="GtkLabel" id="audio_codec">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="left_attach">1</property>
@ -109,7 +69,6 @@
<child>
<object class="GtkLabel" id="video_codec">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="left_attach">1</property>
@ -121,7 +80,6 @@
<child>
<object class="GtkLabel" id="audio_bandwidth_usage">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="left_attach">1</property>
@ -133,8 +91,7 @@
<child>
<object class="GtkLabel" id="label4">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Media connectivity</property>
<property name="label" translatable="yes">Audio Media connectivity</property>
</object>
<packing>
<property name="top_attach">4</property>
@ -143,15 +100,8 @@
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<object class="GtkLabel" id="media_connectivity">
<object class="GtkLabel" id="audio_media_connectivity">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="left_attach">1</property>
@ -163,7 +113,6 @@
<child>
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Video IP bandwidth usage</property>
</object>
<packing>
@ -175,7 +124,6 @@
<child>
<object class="GtkLabel" id="video_bandwidth_usage">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="left_attach">1</property>
@ -184,6 +132,27 @@
<property name="bottom_attach">4</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="label" translatable="yes">Video Media connectivity</property>
</object>
<packing>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="video_media_connectivity">
<property name="visible">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
</packing>
</child>
</object>
</child>
</object>
@ -191,7 +160,6 @@
<child type="label">
<object class="GtkLabel" id="call_statistics_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">&lt;b&gt;Call statistics and information&lt;/b&gt;</property>
<property name="use_markup">True</property>
</object>
@ -203,6 +171,34 @@
<property name="position">1</property>
</packing>
</child>
<child internal-child="action_area">
<object class="GtkHButtonBox" id="dialog-action_area1">
<property name="visible">True</property>
<property name="layout_style">end</property>
<child>
<placeholder/>
</child>
<child>
<object class="GtkButton" id="button1">
<property name="label">gtk-close</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
</object>
</child>
<action-widgets>

View file

@ -90,7 +90,8 @@ void udpate_tab_chat_header(GtkWidget *chat_view,const LinphoneAddress *uri,Linp
}
void linphone_gtk_push_text(GtkWidget *w, const LinphoneAddress *from, const char *message, gboolean me,LinphoneChatRoom *cr){
void linphone_gtk_push_text(GtkWidget *w, const LinphoneAddress *from,
const char *message, gboolean me,LinphoneChatRoom *cr, time_t t){
GtkTextView *text=GTK_TEXT_VIEW(linphone_gtk_get_widget(w,"textview"));
GtkTextBuffer *buffer=gtk_text_view_get_buffer(text);
GtkTextIter iter,begin,end;
@ -129,15 +130,23 @@ void linphone_gtk_push_text(GtkWidget *w, const LinphoneAddress *from, const cha
}
g_object_set_data(G_OBJECT(linphone_gtk_get_main_window()),"history",hash);
gtk_text_buffer_get_end_iter(buffer,&iter);
if(me){
gtk_text_buffer_get_end_iter(buffer,&iter);
list=g_list_append(list,GINT_TO_POINTER(gtk_text_iter_get_line(&iter)));
gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,"Message in progress.. ",-1,
"italic","right","small","font_grey",NULL);
gtk_text_buffer_get_end_iter(buffer,&iter);
gtk_text_buffer_insert(buffer,&iter,"\n",-1);
g_object_set_data(G_OBJECT(w),"list",list);
} else {
struct tm *tm=localtime(&t);
char buf[80];
strftime(buf,80,"%H:%M",tm);
gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,buf,-1,
"italic","right","small","font_grey",NULL);
}
gtk_text_buffer_get_end_iter(buffer,&iter);
gtk_text_buffer_insert(buffer,&iter,"\n",-1);
GtkTextMark *mark=gtk_text_buffer_create_mark(buffer,NULL,&iter,FALSE);
gtk_text_view_scroll_mark_onscreen(text,mark);
@ -193,13 +202,7 @@ void update_chat_state_message(LinphoneChatMessageState state){
break;
default : result="Message in progress.. ";
}
GDateTime *dt=g_date_time_new_now_local();
char *time=g_date_time_format(dt,"%k:%M");
gchar result2[80];
sprintf(result2,"%s %s",result,time);
gtk_text_buffer_insert_with_tags_by_name(b,&iter,result2,-1,
gtk_text_buffer_insert_with_tags_by_name(b,&iter,result,-1,
"italic","right","small","font_grey",NULL);
list=g_list_remove(list,g_list_nth_data(list,0));
g_object_set_data(G_OBJECT(page),"list",list);
@ -221,10 +224,10 @@ void linphone_gtk_send_text(){
entered=gtk_entry_get_text(GTK_ENTRY(entry));
if (strlen(entered)>0) {
LinphoneChatMessage *msg;
msg=linphone_chat_room_create_message(cr,entered);
linphone_gtk_push_text(w,
linphone_gtk_get_used_identity(),
entered,TRUE,cr);
msg=linphone_chat_room_create_message(cr,entered);
entered,TRUE,cr,linphone_chat_message_get_time(msg));
linphone_chat_room_send_message2(cr,msg,on_chat_state_changed,NULL);
gtk_entry_set_text(GTK_ENTRY(entry),"");
}
@ -338,25 +341,25 @@ void linphone_gtk_chat_close(GtkWidget *button){
}
void linphone_gtk_text_received(LinphoneCore *lc, LinphoneChatRoom *room, const LinphoneAddress *from, const char *message){
void linphone_gtk_text_received(LinphoneCore *lc, LinphoneChatRoom *room,
LinphoneChatMessage *msg){
GtkWidget *main_window=linphone_gtk_get_main_window();
GtkWidget *friendlist=linphone_gtk_get_widget(main_window,"contact_list");
GtkWidget *w;
GDateTime *dt=g_date_time_new_now_local();
char *time=g_date_time_format(dt,"%k:%M");
w=(GtkWidget*)g_object_get_data(G_OBJECT(friendlist),"chatview");
if(w!=NULL){
linphone_gtk_load_chatroom(room,from,w);
linphone_gtk_load_chatroom(room,linphone_chat_message_get_from(msg),w);
} else {
w=linphone_gtk_init_chatroom(room,from);
w=linphone_gtk_init_chatroom(room,linphone_chat_message_get_from(msg));
g_object_set_data(G_OBJECT(friendlist),"chatview",(gpointer)w);
g_object_set_data(G_OBJECT(friendlist),"from",(gpointer)from);
g_object_set_data(G_OBJECT(friendlist),"from",(gpointer)linphone_chat_message_get_from(msg));
}
const char *display=linphone_address_get_display_name(from);
const char *display=linphone_address_get_display_name(linphone_chat_message_get_from(msg));
if (display==NULL || display[0]=='\0') {
display=linphone_address_get_username(from);
display=linphone_address_get_username(linphone_chat_message_get_from(msg));
}
#ifdef HAVE_GTK_OSXs
@ -365,16 +368,15 @@ void linphone_gtk_text_received(LinphoneCore *lc, LinphoneChatRoom *room, const
#else
if(!gtk_window_is_active(GTK_WINDOW(main_window))){
if(!GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"is_notified"))){
gchar result2[80];
sprintf(result2,"%s \n %s sent at %s",message,display,time);
linphone_gtk_notify(NULL,result2);
linphone_gtk_notify(NULL,linphone_chat_message_get_text(msg));
g_object_set_data(G_OBJECT(w),"is_notified",GINT_TO_POINTER(TRUE));
} else {
g_object_set_data(G_OBJECT(w),"is_notified",GINT_TO_POINTER(FALSE));
}
}
#endif
linphone_gtk_push_text(w,from,message,FALSE,room);
linphone_gtk_push_text(w,linphone_chat_message_get_from(msg),
linphone_chat_message_get_text(msg),FALSE,room,linphone_chat_message_get_time(msg));
linphone_gtk_update_chat_picture();
//gtk_window_present(GTK_WINDOW(w));
/*gtk_window_set_urgency_hint(GTK_WINDOW(w),TRUE);*/

View file

@ -231,10 +231,29 @@ static const char *ice_state_to_string(LinphoneIceState ice_state){
return "invalid";
}
static const char *upnp_state_to_string(LinphoneUpnpState ice_state){
switch(ice_state){
case LinphoneUpnpStateIdle:
return _("uPnP not activated");
case LinphoneUpnpStatePending:
return _("uPnP in progress");
case LinphoneUpnpStateNotAvailable:
return _("uPnp not available");
case LinphoneUpnpStateOk:
return _("uPnP is running");
case LinphoneUpnpStateKo:
return _("uPnP failed");
default:
break;
}
return "invalid";
}
static void _refresh_call_stats(GtkWidget *callstats, LinphoneCall *call){
const LinphoneCallStats *as=linphone_call_get_audio_stats(call);
const LinphoneCallStats *vs=linphone_call_get_video_stats(call);
LinphoneIceState ice_state=as->ice_state;
const char *audio_media_connectivity = _("Direct");
const char *video_media_connectivity = _("Direct");
gchar *tmp=g_strdup_printf(_("download: %f\nupload: %f (kbit/s)"),
as->download_bandwidth,as->upload_bandwidth);
gtk_label_set_markup(GTK_LABEL(linphone_gtk_get_widget(callstats,"audio_bandwidth_usage")),tmp);
@ -243,7 +262,18 @@ static void _refresh_call_stats(GtkWidget *callstats, LinphoneCall *call){
vs->download_bandwidth,vs->upload_bandwidth);
gtk_label_set_markup(GTK_LABEL(linphone_gtk_get_widget(callstats,"video_bandwidth_usage")),tmp);
g_free(tmp);
gtk_label_set_text(GTK_LABEL(linphone_gtk_get_widget(callstats,"media_connectivity")),ice_state_to_string(ice_state));
if(as->upnp_state != LinphoneUpnpStateNotAvailable && as->upnp_state != LinphoneUpnpStateIdle) {
audio_media_connectivity = upnp_state_to_string(as->upnp_state);
} else if(as->ice_state != LinphoneIceStateNotActivated) {
audio_media_connectivity = ice_state_to_string(as->ice_state);
}
gtk_label_set_text(GTK_LABEL(linphone_gtk_get_widget(callstats,"audio_media_connectivity")),audio_media_connectivity);
if(vs->upnp_state != LinphoneUpnpStateNotAvailable && vs->upnp_state != LinphoneUpnpStateIdle) {
video_media_connectivity = upnp_state_to_string(vs->upnp_state);
} else if(vs->ice_state != LinphoneIceStateNotActivated) {
video_media_connectivity = ice_state_to_string(vs->ice_state);
}
gtk_label_set_text(GTK_LABEL(linphone_gtk_get_widget(callstats,"video_media_connectivity")),video_media_connectivity);
}
static gboolean refresh_call_stats(GtkWidget *callstats){
@ -642,7 +672,7 @@ void linphone_gtk_in_call_view_set_in_call(LinphoneCall *call){
gtk_widget_hide(linphone_gtk_get_widget(callview,"answer_decline_panel"));
gtk_label_set_markup(GTK_LABEL(status),in_conf ? _("In conference") : _("<b>In call</b>"));
gtk_widget_set_sensitive(linphone_gtk_get_widget(callview,"conference_button"),!in_conf);
gtk_widget_set_sensitive(linphone_gtk_get_widget(callview,"transfer_button"),!in_conf);

277
gtk/keypad.ui Normal file
View file

@ -0,0 +1,277 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="2.24"/>
<!-- interface-naming-policy project-wide -->
<object class="GtkWindow" id="keypad">
<property name="can_focus">False</property>
<child>
<object class="GtkFrame" id="frame3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0.5</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkAspectFrame" id="aspectframe1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<child>
<object class="GtkTable" id="dtmf_table">
<property name="visible">True</property>
<property name="can_focus">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="border_width">4</property>
<property name="n_rows">4</property>
<property name="n_columns">4</property>
<property name="homogeneous">True</property>
<child>
<object class="GtkButton" id="dtmf_D">
<property name="label" translatable="yes">D</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>
</object>
<packing>
<property name="left_attach">3</property>
<property name="right_attach">4</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
</packing>
</child>
<child>
<object class="GtkButton" id="dtmf_#">
<property name="label" translatable="yes">#</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>
</object>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
</packing>
</child>
<child>
<object class="GtkButton" id="dtmf_0">
<property name="label" translatable="yes">0</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>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
</packing>
</child>
<child>
<object class="GtkButton" id="dtmf_*">
<property name="label" translatable="yes">*</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>
</object>
<packing>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
</packing>
</child>
<child>
<object class="GtkButton" id="dtmf_C">
<property name="label" translatable="yes">C</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>
</object>
<packing>
<property name="left_attach">3</property>
<property name="right_attach">4</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
</packing>
</child>
<child>
<object class="GtkButton" id="dtmf_9">
<property name="label" translatable="yes">9</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>
</object>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
</packing>
</child>
<child>
<object class="GtkButton" id="dtmf_8">
<property name="label" translatable="yes">8</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>
</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>
</packing>
</child>
<child>
<object class="GtkButton" id="dtmf_7">
<property name="label" translatable="yes">7</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>
</object>
<packing>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
</packing>
</child>
<child>
<object class="GtkButton" id="dtmf_B">
<property name="label" translatable="yes">B</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>
</object>
<packing>
<property name="left_attach">3</property>
<property name="right_attach">4</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
</packing>
</child>
<child>
<object class="GtkButton" id="dtmf_6">
<property name="label" translatable="yes">6</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>
</object>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
</packing>
</child>
<child>
<object class="GtkButton" id="dtmf_5">
<property name="label" translatable="yes">5</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>
</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>
</packing>
</child>
<child>
<object class="GtkButton" id="dtmf_4">
<property name="label" translatable="yes">4</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>
</object>
<packing>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
</packing>
</child>
<child>
<object class="GtkButton" id="dtmf_A">
<property name="label" translatable="yes">A</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>
</object>
<packing>
<property name="left_attach">3</property>
<property name="right_attach">4</property>
</packing>
</child>
<child>
<object class="GtkButton" id="dtmf_3">
<property name="label" translatable="yes">3</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>
</object>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
</packing>
</child>
<child>
<object class="GtkButton" id="dtmf_2">
<property name="label" translatable="yes">2</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>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
</packing>
</child>
<child>
<object class="GtkButton" id="dtmf_1">
<property name="label" translatable="yes">1</property>
<property name="width_request">40</property>
<property name="height_request">40</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>
</object>
</child>
</object>
</child>
</object>
</child>
<child type="label_item">
<placeholder/>
</child>
</object>
</child>
</object>
</interface>

View file

@ -74,7 +74,7 @@ void linphone_gtk_fill_soundcards(GtkWidget *pb);
void linphone_gtk_fill_webcams(GtkWidget *pb);
void linphone_gtk_load_identities(void);
LinphoneChatRoom * linphone_gtk_create_chatroom(const LinphoneAddress *with);
void linphone_gtk_text_received(LinphoneCore *lc, LinphoneChatRoom *room, const LinphoneAddress *from, const char *message);
void linphone_gtk_text_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage *msg);
void linphone_gtk_call_log_update(GtkWidget *w);
void linphone_gtk_create_log_window(void);
void linphone_gtk_log_show(void);
@ -102,7 +102,6 @@ void linphone_gtk_terminate_call(GtkWidget *button);
void update_tab_header(LinphoneCall *call,gboolean pause);
void linphone_gtk_show_directory_search(void);
void linphone_gtk_status_icon_set_blinking(gboolean val);
void linphone_gtk_notify(LinphoneCall *call, const char *msg);
LinphoneChatRoom *linphone_gtk_start_chat(GtkTreeView* t);

View file

@ -230,7 +230,8 @@ static void linphone_gtk_init_liblinphone(const char *config_file,
vtable.display_warning=linphone_gtk_display_warning;
vtable.display_url=linphone_gtk_display_url;
vtable.call_log_updated=linphone_gtk_call_log_updated;
vtable.text_received=linphone_gtk_text_received;
//vtable.text_received=linphone_gtk_text_received;
vtable.message_received=linphone_gtk_text_received;
vtable.refer_received=linphone_gtk_refer_received;
vtable.buddy_info_updated=linphone_gtk_buddy_info_updated;
vtable.call_encryption_changed=linphone_gtk_call_encryption_changed;
@ -744,7 +745,9 @@ static void linphone_gtk_update_call_buttons(LinphoneCall *call){
linphone_gtk_enable_conference_button(lc,FALSE);
}
update_video_title();
if (call) linphone_gtk_update_video_button(call);
if (call) {
linphone_gtk_update_video_button(call);
}
}
static gboolean linphone_gtk_start_call_do(GtkWidget *uri_bar){
@ -1444,7 +1447,7 @@ void linphone_gtk_load_identities(void){
static void linphone_gtk_dtmf_pressed(GtkButton *button){
const char *label=(char *)g_object_get_data(G_OBJECT(button),"label");
GtkWidget *uri_bar=linphone_gtk_get_widget(gtk_widget_get_toplevel(GTK_WIDGET(button)),"uribar");
GtkWidget *uri_bar=linphone_gtk_get_widget(linphone_gtk_get_main_window(),"uribar");
int pos=-1;
gtk_editable_insert_text(GTK_EDITABLE(uri_bar),label,1,&pos);
linphone_core_play_dtmf (linphone_gtk_get_core(),label[0],-1);
@ -1458,8 +1461,8 @@ static void linphone_gtk_dtmf_released(GtkButton *button){
}
static void linphone_gtk_connect_digits(void){
GtkContainer *cont=GTK_CONTAINER(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"dtmf_table"));
static void linphone_gtk_connect_digits(GtkWidget *w){
GtkContainer *cont=GTK_CONTAINER(linphone_gtk_get_widget(w,"dtmf_table"));
GList *children=gtk_container_get_children(cont);
GList *elem;
for(elem=children;elem!=NULL;elem=elem->next){
@ -1497,11 +1500,10 @@ static void linphone_gtk_configure_main_window(){
static const char *home;
static const char *start_call_icon;
static const char *add_call_icon;
//static const char *stop_call_icon;
static const char *search_icon;
static gboolean update_check_menu;
static gboolean buttons_have_borders;
static gboolean show_abcd;
//static gboolean show_abcd;
GtkWidget *w=linphone_gtk_get_main_window();
GHashTable *contacts_history;
@ -1513,11 +1515,10 @@ static void linphone_gtk_configure_main_window(){
home=linphone_gtk_get_ui_config("home","http://www.linphone.org");
start_call_icon=linphone_gtk_get_ui_config("start_call_icon","startcall-green.png");
add_call_icon=linphone_gtk_get_ui_config("add_call_icon","addcall-green.png");
//stop_call_icon=linphone_gtk_get_ui_config("stop_call_icon","stopcall-small.png");
search_icon=linphone_gtk_get_ui_config("directory_search_icon",NULL);
update_check_menu=linphone_gtk_get_ui_config_int("update_check_menu",0);
buttons_have_borders=linphone_gtk_get_ui_config_int("buttons_border",1);
show_abcd=linphone_gtk_get_ui_config_int("show_abcd",1);
//show_abcd=linphone_gtk_get_ui_config_int("show_abcd",1);
config_loaded=TRUE;
}
linphone_gtk_configure_window(w,"main_window");
@ -1558,7 +1559,7 @@ static void linphone_gtk_configure_main_window(){
}
*/
}
{
/*{
GdkPixbuf *pbuf=create_pixbuf("dialer-orange.png");
if (pbuf) {
GtkImage *img=GTK_IMAGE(linphone_gtk_get_widget(w,"keypad_tab_icon"));
@ -1570,20 +1571,20 @@ static void linphone_gtk_configure_main_window(){
g_object_unref(G_OBJECT(scaled));
g_object_unref(G_OBJECT(pbuf));
}
}
}*/
if (linphone_gtk_can_manage_accounts()) {
gtk_widget_show(linphone_gtk_get_widget(w,"assistant_item"));
}
if (update_check_menu){
gtk_widget_show(linphone_gtk_get_widget(w,"versioncheck_item"));
}
if (!show_abcd){
/*if (!show_abcd){
gtk_widget_hide(linphone_gtk_get_widget(w,"dtmf_A"));
gtk_widget_hide(linphone_gtk_get_widget(w,"dtmf_B"));
gtk_widget_hide(linphone_gtk_get_widget(w,"dtmf_C"));
gtk_widget_hide(linphone_gtk_get_widget(w,"dtmf_D"));
gtk_table_resize(GTK_TABLE(linphone_gtk_get_widget(w,"dtmf_table")),4,3);
}
}*/
}
void linphone_gtk_manage_login(void){
@ -1647,24 +1648,34 @@ void linphone_gtk_init_dtmf_table(GtkWidget *mw){
g_object_set_data(G_OBJECT(linphone_gtk_get_widget(mw,"dtmf_0")),"label","0");
g_object_set_data(G_OBJECT(linphone_gtk_get_widget(mw,"dtmf_#")),"label","#");
g_object_set_data(G_OBJECT(linphone_gtk_get_widget(mw,"dtmf_*")),"label","*");
}
void linphone_gtk_create_keypad(GtkWidget *button){
GtkWidget *mw=linphone_gtk_get_main_window();
GtkWidget *k=(GtkWidget *)g_object_get_data(G_OBJECT(mw),"keypad");
if(k!=NULL){
gtk_widget_destroy(k);
}
GtkWidget *keypad=linphone_gtk_create_window("keypad");
linphone_gtk_connect_digits(keypad);
linphone_gtk_init_dtmf_table(keypad);
g_object_set_data(G_OBJECT(mw),"keypad",(gpointer)keypad);
gtk_widget_show(keypad);
}
static void linphone_gtk_init_main_window(){
GtkWidget *main_window;
linphone_gtk_configure_main_window();
linphone_gtk_manage_login();
load_uri_history();
linphone_gtk_load_identities();
linphone_gtk_set_my_presence(linphone_core_get_presence_info(linphone_gtk_get_core()));
linphone_gtk_show_friends();
linphone_gtk_connect_digits();
main_window=linphone_gtk_get_main_window();
linphone_gtk_call_log_update(main_window);
linphone_gtk_init_dtmf_table(main_window);
linphone_gtk_update_call_buttons (NULL);
g_object_set_data(G_OBJECT(main_window),"keypad",NULL);
g_object_set_data(G_OBJECT(main_window),"is_conf",GINT_TO_POINTER(FALSE));
/*prevent the main window from being destroyed by a user click on WM controls, instead we hide it*/
g_signal_connect (G_OBJECT (main_window), "delete-event",

View file

@ -70,13 +70,13 @@
<child>
<object class="GtkProgressBar" id="sound_indicator">
<property name="width_request">90</property>
<property name="height_request">10</property>
<property name="height_request">30</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
@ -155,7 +155,7 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkImage" id="image13">
<object class="GtkImage" id="send_picture">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-ok</property>
@ -273,7 +273,17 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<placeholder/>
<object class="GtkLabel" id="in_call_uri">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">label</property>
<property name="justify">center</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
<packing>
@ -282,19 +292,6 @@
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="in_call_uri">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">label</property>
<property name="justify">center</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkHBox" id="encryption_box">
<property name="can_focus">False</property>
@ -354,7 +351,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
<property name="position">1</property>
</packing>
</child>
<child>
@ -419,7 +416,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">3</property>
<property name="position">2</property>
</packing>
</child>
<child>
@ -460,7 +457,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">4</property>
<property name="position">3</property>
</packing>
</child>
<child>
@ -556,7 +553,7 @@
<property name="expand">False</property>
<property name="fill">False</property>
<property name="padding">7</property>
<property name="position">5</property>
<property name="position">4</property>
</packing>
</child>
</object>
@ -640,6 +637,36 @@
<property name="can_focus">False</property>
<property name="stock">gtk-connect</property>
</object>
<object class="GtkImage" id="image13">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-add</property>
</object>
<object class="GtkImage" id="image14">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-add</property>
</object>
<object class="GtkImage" id="image15">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-add</property>
</object>
<object class="GtkImage" id="image16">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-add</property>
</object>
<object class="GtkImage" id="image17">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-missing-image</property>
</object>
<object class="GtkImage" id="image18">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-select-color</property>
</object>
<object class="GtkImage" id="image2">
<property name="visible">True</property>
<property name="can_focus">False</property>
@ -916,6 +943,7 @@
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="padding">2</property>
<property name="position">0</property>
</packing>
</child>
@ -944,6 +972,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="padding">6</property>
<property name="position">2</property>
</packing>
</child>
@ -1062,6 +1091,22 @@
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button1">
<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="image">image18</property>
<signal name="clicked" handler="linphone_gtk_create_keypad" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="pack_type">end</property>
<property name="position">3</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
@ -1073,7 +1118,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="padding">12</property>
<property name="padding">6</property>
<property name="position">0</property>
</packing>
</child>
@ -1082,453 +1127,10 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
<object class="GtkHBox" id="hbox5">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<child>
<object class="GtkVBox" id="vbox7">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<child>
<object class="GtkFrame" id="frame3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0.5</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkAlignment" id="alignment5">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xscale">0</property>
<property name="yscale">0</property>
<child>
<object class="GtkAspectFrame" id="aspectframe1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<child>
<object class="GtkTable" id="dtmf_table">
<property name="visible">True</property>
<property name="can_focus">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="border_width">4</property>
<property name="n_rows">4</property>
<property name="n_columns">4</property>
<property name="homogeneous">True</property>
<child>
<object class="GtkButton" id="dtmf_D">
<property name="label" translatable="yes">D</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>
</object>
<packing>
<property name="left_attach">3</property>
<property name="right_attach">4</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
</packing>
</child>
<child>
<object class="GtkButton" id="dtmf_#">
<property name="label" translatable="yes">#</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>
</object>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
</packing>
</child>
<child>
<object class="GtkButton" id="dtmf_0">
<property name="label" translatable="yes">0</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>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
</packing>
</child>
<child>
<object class="GtkButton" id="dtmf_*">
<property name="label" translatable="yes">*</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>
</object>
<packing>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
</packing>
</child>
<child>
<object class="GtkButton" id="dtmf_C">
<property name="label" translatable="yes">C</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>
</object>
<packing>
<property name="left_attach">3</property>
<property name="right_attach">4</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
</packing>
</child>
<child>
<object class="GtkButton" id="dtmf_9">
<property name="label" translatable="yes">9</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>
</object>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
</packing>
</child>
<child>
<object class="GtkButton" id="dtmf_8">
<property name="label" translatable="yes">8</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>
</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>
</packing>
</child>
<child>
<object class="GtkButton" id="dtmf_7">
<property name="label" translatable="yes">7</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>
</object>
<packing>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
</packing>
</child>
<child>
<object class="GtkButton" id="dtmf_B">
<property name="label" translatable="yes">B</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>
</object>
<packing>
<property name="left_attach">3</property>
<property name="right_attach">4</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
</packing>
</child>
<child>
<object class="GtkButton" id="dtmf_6">
<property name="label" translatable="yes">6</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>
</object>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
</packing>
</child>
<child>
<object class="GtkButton" id="dtmf_5">
<property name="label" translatable="yes">5</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>
</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>
</packing>
</child>
<child>
<object class="GtkButton" id="dtmf_4">
<property name="label" translatable="yes">4</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>
</object>
<packing>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
</packing>
</child>
<child>
<object class="GtkButton" id="dtmf_A">
<property name="label" translatable="yes">A</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>
</object>
<packing>
<property name="left_attach">3</property>
<property name="right_attach">4</property>
</packing>
</child>
<child>
<object class="GtkButton" id="dtmf_3">
<property name="label" translatable="yes">3</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>
</object>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
</packing>
</child>
<child>
<object class="GtkButton" id="dtmf_2">
<property name="label" translatable="yes">2</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>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
</packing>
</child>
<child>
<object class="GtkButton" id="dtmf_1">
<property name="label" translatable="yes">1</property>
<property name="width_request">40</property>
<property name="height_request">40</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>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
<child type="label_item">
<placeholder/>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkFrame" id="directory_search_box">
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkHBox" id="directory_search_vbox">
<property name="can_focus">False</property>
<child>
<object class="GtkEntry" id="directory_search_entry">
<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>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="directory_search_button">
<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="relief">none</property>
<signal name="clicked" handler="linphone_gtk_directory_search_button_clicked" swapped="no"/>
<child>
<object class="GtkHBox" id="hbox12">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkImage" id="directory_search_button_icon">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-find</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="directory_search_button_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Search</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="label14">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">&lt;b&gt;Add contacts from directory&lt;/b&gt;</property>
<property name="use_markup">True</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="padding">5</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkHButtonBox" id="hbuttonbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkButton" id="add_contact_button">
<property name="label" translatable="yes">Add contact</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="image">image10</property>
<signal name="clicked" handler="linphone_gtk_add_contact" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">3</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
<placeholder/>
</child>
<child type="tab">
<object class="GtkHBox" id="hbox2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkImage" id="keypad_tab_icon">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-missing-image</property>
<property name="icon-size">1</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="Keypad">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Keypad</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="tab_fill">False</property>
</packing>
<placeholder/>
</child>
<child>
<object class="GtkVBox" id="keypad_frame">
@ -1539,6 +1141,28 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">2</property>
<child>
<object class="GtkScrolledWindow" id="scrolledwindow2">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">never</property>
<child>
<object class="GtkTreeView" id="logs_view">
<property name="width_request">350</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="headers_visible">False</property>
<signal name="cursor-changed" handler="linphone_gtk_history_row_selected" swapped="no"/>
<signal name="row-activated" handler="linphone_gtk_history_row_activated" swapped="no"/>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkHButtonBox" id="dialog-action_area1">
<property name="visible">True</property>
@ -1571,29 +1195,137 @@
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">0</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="scrolledwindow2">
<object class="GtkVBox" id="vbox7">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">never</property>
<property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<child>
<object class="GtkTreeView" id="logs_view">
<property name="width_request">350</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="headers_visible">False</property>
<signal name="cursor-changed" handler="linphone_gtk_history_row_selected" swapped="no"/>
<signal name="row-activated" handler="linphone_gtk_history_row_activated" swapped="no"/>
<placeholder/>
</child>
<child>
<object class="GtkFrame" id="directory_search_box">
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkHBox" id="directory_search_vbox">
<property name="can_focus">False</property>
<child>
<object class="GtkEntry" id="directory_search_entry">
<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>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="directory_search_button">
<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="relief">none</property>
<signal name="clicked" handler="linphone_gtk_directory_search_button_clicked" swapped="no"/>
<child>
<object class="GtkHBox" id="hbox12">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkImage" id="directory_search_button_icon">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-find</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="directory_search_button_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Search</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="label14">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">&lt;b&gt;Add contacts from directory&lt;/b&gt;</property>
<property name="use_markup">True</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="padding">5</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkHButtonBox" id="hbuttonbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkButton" id="add_contact_button">
<property name="label" translatable="yes">Add contact</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="image">image16</property>
<signal name="clicked" handler="linphone_gtk_add_contact" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">3</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="pack_type">end</property>
<property name="position">2</property>
</packing>
</child>
</object>
@ -1654,7 +1386,7 @@
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="padding">4</property>
<property name="padding">6</property>
<property name="position">1</property>
</packing>
</child>

View file

@ -765,6 +765,23 @@
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="use_upnp">
<property name="label" translatable="yes">Behind NAT / Firewall (use uPnP)</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>
<property name="group">no_nat</property>
<signal name="toggled" handler="linphone_gtk_use_upnp_toggled" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">4</property>
</packing>
</child>
<child>
<object class="GtkHBox" id="hbox24">
<property name="visible">True</property>

View file

@ -236,6 +236,11 @@ void linphone_gtk_use_ice_toggled(GtkWidget *w){
linphone_core_set_firewall_policy(linphone_gtk_get_core(),LinphonePolicyUseIce);
}
void linphone_gtk_use_upnp_toggled(GtkWidget *w){
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)))
linphone_core_set_firewall_policy(linphone_gtk_get_core(),LinphonePolicyUseUpnp);
}
void linphone_gtk_mtu_changed(GtkWidget *w){
if (GTK_WIDGET_SENSITIVE(w))
linphone_core_set_mtu(linphone_gtk_get_core(),gtk_spin_button_get_value(GTK_SPIN_BUTTON(w)));
@ -1074,6 +1079,9 @@ void linphone_gtk_show_parameters(void){
case LinphonePolicyUseIce:
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb,"use_ice")),TRUE);
break;
case LinphonePolicyUseUpnp:
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb,"use_upnp")),TRUE);
break;
}
mtu=linphone_core_get_mtu(lc);
if (mtu<=0){

View file

@ -102,22 +102,22 @@ public interface LinphoneCall {
/**
* The call's parameters are updated, used for example when video is asked by remote
*/
public static final State CallUpdatedByRemote = new State(15, "CallUpdatedByRemote");
public static final State CallUpdatedByRemote = new State(15, "UpdatedByRemote");
/**
* We are proposing early media to an incoming call
*/
public static final State CallIncomingEarlyMedia = new State(16,"CallIncomingEarlyMedia");
public static final State CallIncomingEarlyMedia = new State(16,"IncomingEarlyMedia");
/**
* The remote accepted the call update initiated by us
* We have initiated a call update. When the remote accepts the call update, state will move to StreamsRunning.
*/
public static final State CallUpdated = new State(17, "CallUpdated");
public static final State CallUpdating = new State(17, "Updating");
/**
* The call object is now released.
*/
public static final State CallReleased = new State(18,"CallReleased");
public static final State CallReleased = new State(18,"Released");
private State(int value,String stringValue) {
@ -160,17 +160,6 @@ public interface LinphoneCall {
**/
LinphoneCallLog getCallLog();
/**
* Set the audio statistics associated with this call.
* @return LinphoneCallStats
*/
void setAudioStats(LinphoneCallStats stats);
/**
* Set the video statistics associated with this call.
* @return LinphoneCallStats
*/
void setVideoStats(LinphoneCallStats stats);
/**
* Get the audio statistics associated with this call.
@ -184,6 +173,10 @@ public interface LinphoneCall {
*/
LinphoneCallStats getVideoStats();
/**
* Get call's remote parameters, as proposed by far end.
* This is useful for example to know if far end supports video or encryption.
**/
LinphoneCallParams getRemoteParams();
LinphoneCallParams getCurrentParamsCopy();
@ -273,6 +266,11 @@ public interface LinphoneCall {
* Obtain the remote user agent string.
*/
String getRemoteUserAgent();
/**
* Obtain the remote sip contact string.
**/
String getRemoteContact();
/**
* Take a photo of currently received video and write it into a jpeg file.

View file

@ -67,6 +67,7 @@ abstract public class LinphoneCoreFactory {
* @return
*/
abstract public LinphoneAddress createLinphoneAddress(String address);
abstract public LpConfig createLpConfig(String file);
abstract public LinphoneProxyConfig createProxyConfig(String identity, String proxy,String route,boolean enableRegister) throws LinphoneCoreException;
/**

View file

@ -179,6 +179,11 @@ class LinphoneCallImpl implements LinphoneCall {
public String getRemoteUserAgent() {
return getRemoteUserAgent(nativePtr);
}
private native String getRemoteContact(long nativePtr);
public String getRemoteContact() {
return getRemoteContact(nativePtr);
}
private native void takeSnapshot(long nativePtr, String path);
public void takeSnapshot(String path) {

View file

@ -105,6 +105,11 @@ public class LinphoneCoreFactoryImpl extends LinphoneCoreFactory {
public LinphoneAddress createLinphoneAddress(String identity) {
return new LinphoneAddressImpl(identity);
}
@Override
public LpConfig createLpConfig(String file) {
return new LpConfigImpl(file);
}
@Override
public LinphoneCore createLinphoneCore(LinphoneCoreListener listener,

View file

@ -27,6 +27,15 @@ class LpConfigImpl implements LpConfig {
public LpConfigImpl(long ptr) {
nativePtr=ptr;
}
private native long newLpConfigImpl(String file);
private native void delete(long ptr);
public LpConfigImpl(String file) {
nativePtr = newLpConfigImpl(file);
}
protected void finalize() throws Throwable {
delete(nativePtr);
}
private native void setInt(long ptr, String section, String key, int value);
public void setInt(String section, String key, int value) {

View file

@ -0,0 +1,68 @@
package org.linphone.tools;
import org.linphone.core.LpConfig;
import org.linphone.mediastream.Log;
public class Lpc2Xml {
private enum LogLevel {
DEBUG,
MESSAGE,
WARNING,
ERROR,
}
private static boolean mAvailable;
private long internalPtr = 0;
private native void init();
private native void destroy();
public Lpc2Xml() {
init();
}
public void finalize() {
destroy();
}
public native int setLpc(LpConfig lpc);
public native int convertFile(String file);
public native int convertString(StringBuffer content);
public void printLog(int level, String message) {
if(level > 0 && level < LogLevel.values().length) {
switch(LogLevel.values()[level]) {
case DEBUG:
Log.d(message);
break;
case MESSAGE:
Log.i(message);
break;
case WARNING:
Log.w(message);
break;
case ERROR:
Log.e(message);
break;
}
}
}
static boolean isAvailable() {
return mAvailable;
}
// Load library
static {
try {
System.loadLibrary("xml2");
System.loadLibrary("lpc2xml");
mAvailable = true;
} catch (Throwable e) {
mAvailable = false;
}
}
}

View file

@ -0,0 +1,72 @@
package org.linphone.tools;
import org.linphone.core.LpConfig;
import org.linphone.mediastream.Log;
public class Xml2Lpc {
private enum LogLevel {
DEBUG,
MESSAGE,
WARNING,
ERROR
}
private static boolean mAvailable;
private long internalPtr = 0;
private native void init();
private native void destroy();
public Xml2Lpc() {
init();
}
public void finalize() {
destroy();
}
public native int setXmlFile(String filename);
public native int setXmlString(String content);
public native int setXsdFile(String filename);
public native int setXsdString(String content);
public native int validate();
public native int convert(LpConfig config);
public void printLog(int level, String message) {
if(level > 0 && level < LogLevel.values().length) {
switch(LogLevel.values()[level]) {
case DEBUG:
Log.d(message);
break;
case MESSAGE:
Log.i(message);
break;
case WARNING:
Log.w(message);
break;
case ERROR:
Log.e(message);
break;
}
}
}
public static boolean isAvailable() {
return mAvailable;
}
// Load library
static {
try {
System.loadLibrary("xml2");
System.loadLibrary("xml2lpc");
mAvailable = true;
} catch (Throwable e) {
mAvailable = false;
}
}
}

@ -1 +1 @@
Subproject commit 3a231efb89305d775ab39a6866ee981a891aed7e
Subproject commit e5d52990695be15802741e920801f77d24bd8fba

2
oRTP

@ -1 +1 @@
Subproject commit 20abeb39e1edae0f72080f7998410e9b16b9da05
Subproject commit b055a505042c4420e104ce81a09790c5373f62bb

View file

@ -26,6 +26,7 @@ gtk/loginframe.c
[type: gettext/glade]gtk/dscp_settings.ui
[type: gettext/glade]gtk/call_statistics.ui
[type: gettext/glade]gtk/tunnel_config.ui
[type: gettext/glade]gtk/keypad.ui
coreapi/linphonecore.c
coreapi/misc.c
coreapi/presence.c

View file

@ -11,6 +11,8 @@ COMMON_CFLAGS=\
$(STRICT_OPTIONS) \
$(LIBXML2_CFLAGS)
EXTRA_DIST=xml2lpc_jni.cc lpc2xml_jni.cc
if BUILD_TOOLS
lib_LTLIBRARIES=libxml2lpc.la liblpc2xml.la

View file

@ -57,11 +57,11 @@ void lpc2xml_context_destroy(lpc2xml_context *ctx) {
}
free(ctx);
}
/*
static void lpc2xml_context_clear_logs(lpc2xml_context *ctx) {
ctx->errorBuffer[0]='\0';
ctx->warningBuffer[0]='\0';
}*/
}
static void lpc2xml_log(lpc2xml_context *xmlCtx, int level, const char *fmt, ...) {
va_list args;
@ -72,12 +72,34 @@ static void lpc2xml_log(lpc2xml_context *xmlCtx, int level, const char *fmt, ...
va_end(args);
}
static void lpc2xml_genericxml_error(void *ctx, const char *fmt, ...) {
lpc2xml_context *xmlCtx = (lpc2xml_context *)ctx;
int sl = strlen(xmlCtx->errorBuffer);
va_list args;
va_start(args, fmt);
vsnprintf(xmlCtx->errorBuffer + sl, LPC2XML_BZ-sl, fmt, args);
va_end(args);
}
/*
static void lpc2xml_genericxml_warning(void *ctx, const char *fmt, ...) {
lpc2xml_context *xmlCtx = (lpc2xml_context *)ctx;
int sl = strlen(xmlCtx->warningBuffer);
va_list args;
va_start(args, fmt);
vsnprintf(xmlCtx->warningBuffer + sl, LPC2XML_BZ-sl, fmt, args);
va_end(args);
}
*/
static int processEntry(const char *section, const char *entry, xmlNode *node, lpc2xml_context *ctx) {
const char *content = lp_config_get_string(ctx->lpc, section, entry, NULL);
if(content == NULL) {
lpc2xml_log(ctx->ctx, LPC2XML_ERROR, "Issue when reading the lpc");
return -1;
}
lpc2xml_log(ctx, LPC2XML_MESSAGE, "Set %s|%s = %s", section, entry, content);
xmlNodeSetContent(node, (const xmlChar *) content);
return 0;
}
@ -103,6 +125,7 @@ static void processSection_cb(const char *entry, struct __processSectionCtx *ctx
ctx->ret = -1;
return;
}
ctx->ret = processEntry(ctx->section, entry, node, ctx->ctx);
}
}
@ -195,36 +218,69 @@ int lpc2xml_set_lpc(lpc2xml_context* context, const LpConfig *lpc) {
}
int lpc2xml_convert_file(lpc2xml_context* context, const char *filename) {
int ret = 0;
int ret = -1;
lpc2xml_context_clear_logs(context);
xmlSetGenericErrorFunc(context, lpc2xml_genericxml_error);
xmlSaveCtxtPtr save_ctx = xmlSaveToFilename(filename, "UTF-8", XML_SAVE_FORMAT);
ret = internal_convert_lpc2xml(context);
if(ret == 0) {
ret = xmlSaveDoc(save_ctx, context->doc);
if(save_ctx != NULL) {
ret = internal_convert_lpc2xml(context);
if(ret == 0) {
ret = xmlSaveDoc(save_ctx, context->doc);
if(ret != 0) {
lpc2xml_log(context, LPC2XML_ERROR, "Can't save document");
lpc2xml_log(context, LPC2XML_ERROR, "%s", context->errorBuffer);
}
}
xmlSaveClose(save_ctx);
} else {
lpc2xml_log(context, LPC2XML_ERROR, "Can't open file:%s", filename);
lpc2xml_log(context, LPC2XML_ERROR, "%s", context->errorBuffer);
}
xmlSaveClose(save_ctx);
return ret;
}
int lpc2xml_convert_fd(lpc2xml_context* context, int fd) {
int ret = 0;
int ret = -1;
lpc2xml_context_clear_logs(context);
xmlSetGenericErrorFunc(context, lpc2xml_genericxml_error);
xmlSaveCtxtPtr save_ctx = xmlSaveToFd(fd, "UTF-8", XML_SAVE_FORMAT);
ret = internal_convert_lpc2xml(context);
if(ret == 0) {
ret = xmlSaveDoc(save_ctx, context->doc);
if(save_ctx != NULL) {
ret = internal_convert_lpc2xml(context);
if(ret == 0) {
ret = xmlSaveDoc(save_ctx, context->doc);
if(ret != 0) {
lpc2xml_log(context, LPC2XML_ERROR, "Can't save document");
lpc2xml_log(context, LPC2XML_ERROR, "%s", context->errorBuffer);
}
}
xmlSaveClose(save_ctx);
} else {
lpc2xml_log(context, LPC2XML_ERROR, "Can't open fd:%d", fd);
lpc2xml_log(context, LPC2XML_ERROR, "%s", context->errorBuffer);
}
xmlSaveClose(save_ctx);
return ret;
}
int lpc2xml_convert_string(lpc2xml_context* context, char **content) {
int ret = 0;
int ret = -1;
xmlBufferPtr buffer = xmlBufferCreate();
lpc2xml_context_clear_logs(context);
xmlSetGenericErrorFunc(context, lpc2xml_genericxml_error);
xmlSaveCtxtPtr save_ctx = xmlSaveToBuffer(buffer, "UTF-8", XML_SAVE_FORMAT);
internal_convert_lpc2xml(context);
if(ret == 0) {
ret = xmlSaveDoc(save_ctx, context->doc);
if(save_ctx != NULL) {
ret = internal_convert_lpc2xml(context);
if(ret == 0) {
ret = xmlSaveDoc(save_ctx, context->doc);
if(ret != 0) {
lpc2xml_log(context, LPC2XML_ERROR, "Can't save document");
lpc2xml_log(context, LPC2XML_ERROR, "%s", context->errorBuffer);
}
}
xmlSaveClose(save_ctx);
} else {
lpc2xml_log(context, LPC2XML_ERROR, "Can't initialize internal buffer");
lpc2xml_log(context, LPC2XML_ERROR, "%s", context->errorBuffer);
}
xmlSaveClose(save_ctx);
if(ret == 0) {
#if LIBXML_VERSION >= 20800
*content = (char *)xmlBufferDetach(buffer);

123
tools/lpc2xml_jni.cc Normal file
View file

@ -0,0 +1,123 @@
/*
xml2lpc_jni.cc
Copyright (C) 2013 Belledonne Communications, Grenoble, France
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 "my_jni.h"
extern "C" {
#include "lpc2xml.h"
}
#ifdef USE_JAVAH
#include "lpc2xml_jni.h"
#endif
#include <stdio.h>
struct jni_lpc2xml_ctx {
JNIEnv *env;
jobject obj;
lpc2xml_context *ctx;
};
static bool update_and_check_context(jni_lpc2xml_ctx *jni_ctx, JNIEnv *env, jobject obj) {
if(jni_ctx != NULL && jni_ctx->ctx != NULL) {
jni_ctx->env = env;
jni_ctx->obj = obj;
return true;
}
return false;
}
#define LPC2XML_CALLBACK_BUFFER_SIZE 1024
extern "C" void Java_org_linphone_tools_Lpc2Xml_callback (void *ctx, lpc2xml_log_level level, const char *fmt, va_list list) {
jni_lpc2xml_ctx *jni_ctx = (jni_lpc2xml_ctx *)ctx;
if(jni_ctx->ctx != NULL) {
JNIEnv *env = jni_ctx->env;
jobject obj = jni_ctx->obj;
char buffer[LPC2XML_CALLBACK_BUFFER_SIZE];
vsnprintf(buffer, LPC2XML_CALLBACK_BUFFER_SIZE, fmt, list);
jstring javaString = env->NewStringUTF(buffer);
jint javaLevel = level;
my_jni::callVoidMethod<void>(env, obj, "Lpc2Xml", "printLog", "(ILjava/lang/String;)V", javaLevel, javaString);
}
}
extern "C" void Java_org_linphone_tools_Lpc2Xml_init(JNIEnv *env, jobject obj) {
jni_lpc2xml_ctx *jni_ctx = new jni_lpc2xml_ctx();
jni_ctx->env = env;
jni_ctx->obj = obj;
jni_ctx->ctx = lpc2xml_context_new(Java_org_linphone_tools_Lpc2Xml_callback, obj);
bool result = my_jni::setLongField<jni_lpc2xml_ctx*>(env, obj, "Lpc2Xml", "internalPtr", jni_ctx);
if(!result) {
lpc2xml_context_destroy(jni_ctx->ctx);
delete jni_ctx;
}
}
extern "C" void Java_org_linphone_tools_Lpc2Xml_destroy(JNIEnv *env, jobject obj) {
jni_lpc2xml_ctx *jni_ctx = my_jni::getLongField<jni_lpc2xml_ctx*>(env, obj, "Lpc2Xml", "internalPtr");
if(jni_ctx != NULL) {
jni_ctx->env = env;
jni_ctx->obj = obj;
if(jni_ctx->ctx != NULL) {
lpc2xml_context_destroy(jni_ctx->ctx);
}
delete jni_ctx;
my_jni::setLongField<jni_lpc2xml_ctx*>(env, obj, "Lpc2Xml", "internalPtr", NULL);
}
}
extern "C" jint Java_org_linphone_tools_Lpc2Xml_setLpc(JNIEnv *env, jobject obj, jobject javaLpc) {
jni_lpc2xml_ctx *jni_ctx = my_jni::getLongField<jni_lpc2xml_ctx*>(env, obj, "Lpc2Xml", "internalPtr");
jint ret = -666;
if(update_and_check_context(jni_ctx, env, obj)) {
LpConfig *lpc = my_jni::getLongField<LpConfig*>(env, javaLpc, "LpConfigImpl", "nativePtr");
if(lpc != NULL) {
lpc2xml_set_lpc(jni_ctx->ctx, lpc);
}
}
return ret;
}
extern "C" jint Java_org_linphone_tools_Lpc2Xml_convertFile(JNIEnv *env, jobject obj, jstring javaFile) {
jni_lpc2xml_ctx *jni_ctx = my_jni::getLongField<jni_lpc2xml_ctx*>(env, obj, "Lpc2Xml", "internalPtr");
jint ret = -666;
if(update_and_check_context(jni_ctx, env, obj)) {
const char *file = env->GetStringUTFChars(javaFile, 0);
ret = lpc2xml_convert_file(jni_ctx->ctx, file);
env->ReleaseStringChars(javaFile, (jchar *)file);
}
return ret;
}
extern "C" jint Java_org_linphone_tools_Lpc2Xml_convertString(JNIEnv *env, jobject obj, jobject javaStringBuffer) {
jni_lpc2xml_ctx *jni_ctx = my_jni::getLongField<jni_lpc2xml_ctx*>(env, obj, "Lpc2Xml", "internalPtr");
jint ret = -666;
if(update_and_check_context(jni_ctx, env, obj)) {
char *string = NULL;
ret = lpc2xml_convert_string(jni_ctx->ctx, &string);
if(string != NULL) {
jstring javaString = env->NewStringUTF(string);
my_jni::callObjectMethod<jobject>(env, obj, "StringBuffer", "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;", javaString);
env->ReleaseStringChars(javaString, (jchar *)string);
}
}
return ret;
}

108
tools/my_jni.h Normal file
View file

@ -0,0 +1,108 @@
/*
my_jni.cc
Copyright (C) 2013 Belledonne Communications, Grenoble, France
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 __MY_JNI__H
#define __MY_JNI__H
#include <jni.h>
extern "C" {
#include "linphonecore_utils.h"
}
#define defCallMethod(Type) \
template <typename ReturnType> \
static ReturnType call##Type##Method(JNIEnv *env, jobject obj, const char *className, const char *methodName, \
const char *methodSignature, ...) { \
jclass my_class = env->GetObjectClass(obj); \
if(my_class == 0) { \
ms_error("Can't get %s JNI class", className); \
return NULL; \
} \
jmethodID my_method = env->GetMethodID(my_class, methodName, methodSignature); \
if(my_method == 0) { \
ms_error("Can't get %s %s %s method", className, methodSignature); \
return NULL; \
} \
va_list vl; \
va_start(vl, methodSignature); \
ReturnType ret = env->Call##Type##MethodV(obj, my_method, vl); \
va_end(vl); \
return ret; \
} \
#define defGetterTypeField(Type, JavaType, JavaStringType) \
template <typename ValueType> \
static ValueType get##Type##Field(JNIEnv *env, jobject obj, const char *className, const char *fieldName) { \
jclass my_class = env->GetObjectClass(obj); \
if(my_class == 0) { \
ms_error("Can't get %s JNI class", className); \
return NULL; \
} \
jfieldID my_field = env->GetFieldID(my_class, fieldName, JavaStringType); \
if(my_field == 0) { \
ms_error("Can't get %s %s field", className, fieldName); \
return NULL; \
} \
return (ValueType) env->Get##Type##Field(obj, my_field); \
} \
#define defSetterTypeField(Type, JavaType, JavaStringType) \
template <typename ValueType> \
static bool set##Type##Field(JNIEnv *env, jobject obj, const char *className, const char *fieldName, ValueType val) { \
jclass my_class = env->GetObjectClass(obj); \
if(my_class == 0) { \
ms_error("Can't get %s JNI class", className); \
return false; \
} \
jfieldID my_field = env->GetFieldID(my_class, fieldName, JavaStringType); \
if(my_field == 0) { \
ms_error("Can't get %s %s field", className, fieldName); \
return false; \
} \
env->Set##Type##Field(obj, my_field, (JavaType) val); \
return true; \
} \
#define defGetterAndSetterTypeField(Type, JavaType, JavaStringType) \
defGetterTypeField(Type, JavaType, JavaStringType) \
defSetterTypeField(Type, JavaType, JavaStringType) \
namespace my_jni {
template <typename ReturnType>
static void callVoidMethod(JNIEnv *env, jobject obj, const char *className, const char *methodName,
const char *methodSignature, ...) {
jclass my_class = env->GetObjectClass(obj);
if(my_class == 0) {
ms_error("Can't get %s JNI class", className);
return;
}
jmethodID my_method = env->GetMethodID(my_class, methodName, methodSignature);
if(my_method == 0) {
ms_error("Can't get %s %s %s method", className, methodName, methodSignature);
return;
}
va_list vl;
va_start(vl, methodSignature);
env->CallVoidMethodV(obj, my_method, vl);
va_end(vl);
}
defCallMethod(Object)
defGetterAndSetterTypeField(Long, jlong, "J")
}
#endif //__MY_JNI__H

View file

@ -148,7 +148,7 @@ static int processEntry(xmlElement *element, const char *sectionName, xml2lpc_co
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);
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);
@ -231,8 +231,10 @@ int xml2lpc_validate(xml2lpc_context *xmlCtx) {
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);
if(strlen(xmlCtx->warningBuffer) > 0)
xml2lpc_log(xmlCtx, XML2LPC_WARNING, "%s", xmlCtx->warningBuffer);
if(strlen(xmlCtx->errorBuffer) > 0)
xml2lpc_log(xmlCtx, XML2LPC_ERROR, "%s", xmlCtx->errorBuffer);
} else if(ret < 0) {
xml2lpc_log(xmlCtx, XML2LPC_ERROR, "Internal error");
}
@ -242,6 +244,13 @@ int xml2lpc_validate(xml2lpc_context *xmlCtx) {
int xml2lpc_convert(xml2lpc_context *xmlCtx, LpConfig *lpc) {
xml2lpc_context_clear_logs(xmlCtx);
if(xmlCtx->doc == NULL) {
xml2lpc_log(xmlCtx, XML2LPC_ERROR, "No doc set");
return -1;
}
if(lpc == NULL) {
xml2lpc_log(xmlCtx, XML2LPC_ERROR, "Invalid lpc");
}
xmlCtx->lpc = lpc;
return internal_convert_xml2lpc(xmlCtx);
}

149
tools/xml2lpc_jni.cc Normal file
View file

@ -0,0 +1,149 @@
/*
xml2lpc_jni.cc
Copyright (C) 2013 Belledonne Communications, Grenoble, France
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 "my_jni.h"
extern "C" {
#include "xml2lpc.h"
}
#ifdef USE_JAVAH
#include "xml2lpc_jni.h"
#endif
#include <stdio.h>
struct jni_xml2lpc_ctx {
JNIEnv *env;
jobject obj;
xml2lpc_context *ctx;
};
static bool update_and_check_context(jni_xml2lpc_ctx *jni_ctx, JNIEnv *env, jobject obj) {
if(jni_ctx != NULL && jni_ctx->ctx != NULL) {
jni_ctx->env = env;
jni_ctx->obj = obj;
return true;
}
return false;
}
#define XML2LPC_CALLBACK_BUFFER_SIZE 1024
extern "C" void Java_org_linphone_tools_Xml2Lpc_callback (void *ctx, xml2lpc_log_level level, const char *fmt, va_list list) {
jni_xml2lpc_ctx *jni_ctx = (jni_xml2lpc_ctx *)ctx;
if(jni_ctx->ctx != NULL) {
JNIEnv *env = jni_ctx->env;
jobject obj = jni_ctx->obj;
char buffer[XML2LPC_CALLBACK_BUFFER_SIZE];
vsnprintf(buffer, XML2LPC_CALLBACK_BUFFER_SIZE, fmt, list);
jstring javaString = env->NewStringUTF(buffer);
jint javaLevel = level;
my_jni::callVoidMethod<void>(env, obj, "Xml2Lpc", "printLog", "(ILjava/lang/String;)V", javaLevel, javaString);
}
}
extern "C" void Java_org_linphone_tools_Xml2Lpc_init(JNIEnv *env, jobject obj) {
jni_xml2lpc_ctx *jni_ctx = new jni_xml2lpc_ctx();
jni_ctx->env = env;
jni_ctx->obj = obj;
jni_ctx->ctx = xml2lpc_context_new(Java_org_linphone_tools_Xml2Lpc_callback, jni_ctx);
bool result = my_jni::setLongField<jni_xml2lpc_ctx*>(env, obj, "Xml2Lpc", "internalPtr", jni_ctx);
if(!result) {
xml2lpc_context_destroy(jni_ctx->ctx);
delete jni_ctx;
}
}
extern "C" void Java_org_linphone_tools_Xml2Lpc_destroy(JNIEnv *env, jobject obj) {
jni_xml2lpc_ctx *jni_ctx = my_jni::getLongField<jni_xml2lpc_ctx*>(env, obj, "Xml2Lpc", "internalPtr");
if(jni_ctx != NULL) {
jni_ctx->env = env;
jni_ctx->obj = obj;
if(jni_ctx->ctx) {
xml2lpc_context_destroy(jni_ctx->ctx);
}
delete jni_ctx;
my_jni::setLongField<jni_xml2lpc_ctx*>(env, obj, "Xml2Lpc", "internalPtr", NULL);
}
}
extern "C" jint Java_org_linphone_tools_Xml2Lpc_setXmlFile(JNIEnv *env, jobject obj, jstring javaXmlFile) {
jni_xml2lpc_ctx *jni_ctx = my_jni::getLongField<jni_xml2lpc_ctx*>(env, obj, "Xml2Lpc", "internalPtr");
jint ret = -666;
if(update_and_check_context(jni_ctx, env, obj)) {
const char *xmlFile = env->GetStringUTFChars(javaXmlFile, 0);
ret = xml2lpc_set_xml_file(jni_ctx->ctx, xmlFile);
env->ReleaseStringChars(javaXmlFile, (jchar *)xmlFile);
}
return ret;
}
extern "C" jint Java_org_linphone_tools_Xml2Lpc_setXmlString(JNIEnv *env, jobject obj, jstring javaXmlString) {
jni_xml2lpc_ctx *jni_ctx = my_jni::getLongField<jni_xml2lpc_ctx*>(env, obj, "Xml2Lpc", "internalPtr");
jint ret = -666;
if(update_and_check_context(jni_ctx, env, obj)) {
const char *xmlString = env->GetStringUTFChars(javaXmlString, 0);
ret = xml2lpc_set_xml_string(jni_ctx->ctx, xmlString);
env->ReleaseStringChars(javaXmlString, (jchar *)xmlString);
}
return ret;
}
extern "C" jint Java_org_linphone_tools_Xml2Lpc_setXsdFile(JNIEnv *env, jobject obj, jstring javaXsdFile) {
jni_xml2lpc_ctx *jni_ctx = my_jni::getLongField<jni_xml2lpc_ctx*>(env, obj, "Xml2Lpc", "internalPtr");
jint ret = -666;
if(update_and_check_context(jni_ctx, env, obj)) {
const char *xsdFile = env->GetStringUTFChars(javaXsdFile, 0);
ret = xml2lpc_set_xsd_file(jni_ctx->ctx, xsdFile);
env->ReleaseStringChars(javaXsdFile, (jchar *)xsdFile);
}
return ret;
}
extern "C" jint Java_org_linphone_tools_Xml2Lpc_setXsdString(JNIEnv *env, jobject obj, jstring javaXsdString) {
jni_xml2lpc_ctx *jni_ctx = my_jni::getLongField<jni_xml2lpc_ctx*>(env, obj, "Xml2Lpc", "internalPtr");
jint ret = -666;
if(update_and_check_context(jni_ctx, env, obj)) {
const char *xsdString = env->GetStringUTFChars(javaXsdString, 0);
ret = xml2lpc_set_xsd_string(jni_ctx->ctx, xsdString);
env->ReleaseStringChars(javaXsdString, (jchar *)xsdString);
}
return ret;
}
extern "C" jint Java_org_linphone_tools_Xml2Lpc_validate(JNIEnv *env, jobject obj) {
jni_xml2lpc_ctx *jni_ctx = my_jni::getLongField<jni_xml2lpc_ctx*>(env, obj, "Xml2Lpc", "internalPtr");
jint ret = -666;
if(update_and_check_context(jni_ctx, env, obj)) {
ret = xml2lpc_validate(jni_ctx->ctx);
}
return ret;
}
extern "C" jint Java_org_linphone_tools_Xml2Lpc_convert(JNIEnv *env, jobject obj, jobject javaLpc) {
jni_xml2lpc_ctx *jni_ctx = my_jni::getLongField<jni_xml2lpc_ctx*>(env, obj, "Xml2Lpc", "internalPtr");
jint ret = -666;
if(update_and_check_context(jni_ctx, env, obj)) {
LpConfig *lpc = my_jni::getLongField<LpConfig*>(env, javaLpc, "LpConfigImpl", "nativePtr");
if(lpc != NULL) {
ret = xml2lpc_convert(jni_ctx->ctx, lpc);
}
}
return ret;
}