Merge commit '728ed3077cf4e47e6e972732a3f8a1b39a96f2ed' into dev_lime

Conflicts:
	build/android/Android.mk
	coreapi/chat.c
	coreapi/help/filetransfer.c
	tester/message_tester.c
This commit is contained in:
Margaux Clerc 2014-09-25 17:52:30 +02:00
commit 4a8ce7f061
173 changed files with 16875 additions and 8043 deletions

View file

@ -1,18 +1,102 @@
cmake_minimum_required(VERSION 2.6)
project(LINPHONE C)
############################################################################
# CMakeLists.txt
# Copyright (C) 2014 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.
#
############################################################################
cmake_minimum_required(VERSION 2.8.12)
project(LINPHONE C CXX)
set(LINPHONE_MAJOR_VERSION "3")
set(LINPHONE_MINOR_VERSION "7")
set(LINPHONE_MICRO_VERSION "0")
set(LINPHONE_VERSION "${LINPHONE_MAJOR_VERSION}.${LINPHONE_MINOR_VERSION}.${LINPHONE_MICRO_VERSION}")
set(LINPHONE_SO_VERSION "6")
include(CMakeDependentOption)
option(ENABLE_STATIC "Build static library (default is shared library)." NO)
option(ENABLE_CONSOLE_UI "Turn on or off compilation of console interface." YES)
option(ENABLE_DATE "Use build date in internal version number." NO)
option(ENABLE_GTK_UI "Turn on or off compilation of gtk interface." YES)
option(ENABLE_LDAP "Enable LDAP support." NO)
option(ENABLE_MSG_STORAGE "Turn on compilation of message storage." YES)
option(ENABLE_NOTIFY "Enable libnotify support." YES)
option(ENABLE_RELATIVE_PREFIX "Find resources relatively to the installation directory." NO)
option(ENABLE_TOOLS "Turn on or off compilation of console interface" YES)
option(ENABLE_TUNNEL "Turn on compilation of tunnel support." NO)
option(ENABLE_TUTORIALS "Enable compilation of tutorials." YES)
option(ENABLE_UNIT_TESTS "Enable compilation of unit tests." YES)
option(ENABLE_UPNP "Build with uPnP support." YES)
option(ENABLE_VIDEO "Build with video support." YES)
cmake_dependent_option(ENABLE_ASSISTANT "Turn on assistant compiling." YES "ENABLE_GTK_UI" NO)
list(APPEND CMAKE_MODULE_PATH ${CMAKE_PREFIX_PATH}/share/cmake/Modules)
include(CheckIncludeFile)
if(MSVC)
list(APPEND CMAKE_REQUIRED_INCLUDES ${CMAKE_PREFIX_PATH}/include/MSVC)
endif()
find_package(BelleSIP REQUIRED)
find_package(MS2 REQUIRED)
find_package(XML2 REQUIRED)
option(LINPHONE_ENABLE_VIDEO "Build linphone with video support." ON)
include_directories(
include/
coreapi/
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_BINARY_DIR}/coreapi/
${BELLESIP_INCLUDE_DIRS}
${MS2_INCLUDE_DIRS}
${XML2_INCLUDE_DIRS}
)
include_directories(
${CMAKE_INSTALL_PREFIX}/include
${CMAKE_INSTALL_PREFIX}/include/libxml2
)
if(MSVC)
include_directories(${CMAKE_PREFIX_PATH}/include/MSVC)
endif()
if(ENABLE_RELATIVE_PREFIX)
set(LINPHONE_DATA_DIR ".")
else()
set(LINPHONE_DATA_DIR "${CMAKE_INSTALL_PREFIX}")
endif()
set(LINPHONE_PLUGINS_DIR "${LINPHONE_DATA_DIR}/lib/liblinphone/plugins")
set(PACKAGE_LOCALE_DIR "${LINPHONE_DATA_DIR}/share/locale")
set(PACKAGE_DATA_DIR "${LINPHONE_DATA_DIR}/share")
set(PACKAGE_SOUND_DIR "${LINPHONE_DATA_DIR}/share/sounds/linphone")
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/config.h PROPERTIES GENERATED ON)
add_definitions(-DHAVE_CONFIG_H)
add_subdirectory(coreapi)
add_subdirectory(share)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/FindLinphone.cmake
DESTINATION share/cmake/Modules
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
)

74
FindLinphone.cmake Normal file
View file

@ -0,0 +1,74 @@
############################################################################
# FindLinphone.txt
# Copyright (C) 2014 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.
#
############################################################################
#
# - Find the linphone include file and library
#
# LINPHONE_FOUND - system has linphone
# LINPHONE_INCLUDE_DIRS - the linphone include directory
# LINPHONE_LIBRARIES - The libraries needed to use linphone
# LINPHONE_CPPFLAGS - The compilation flags needed to use linphone
# LINPHONE_LDFLAGS - The linking flags needed to use linphone
find_package(ORTP REQUIRED)
find_package(MS2 REQUIRED)
find_package(XML2 REQUIRED)
find_package(BelleSIP REQUIRED)
set(_LINPHONEROOT_PATHS
${WITH_LINPHONE}
${CMAKE_INSTALL_PREFIX}
)
find_path(LINPHONE_INCLUDE_DIRS
NAMES linphone/linphonecore.h
HINTS _LINPHONE_ROOT_PATHS
PATH_SUFFIXES include
)
if(LINPHONE_INCLUDE_DIRS)
set(HAVE_LINPHONE_LINPHONECORE_H 1)
endif()
find_library(LINPHONE_LIBRARIES
NAMES linphone
HINTS ${_LINPHONE_ROOT_PATHS}
PATH_SUFFIXES bin lib
)
list(APPEND LINPHONE_INCLUDE_DIRS ${ORTP_INCLUDE_DIRS} ${MS2_INCLUDE_DIRS} ${XML2_INCLUDE_DIRS} ${BELLESIP_INCLUDE_DIRS})
list(APPEND LINPHONE_LIBRARIES ${ORTP_LIBRARIES} ${MS2_LIBRARIES} ${XML2_LIBRARIES} ${BELLESIP_LIBRARIES})
if(WIN32)
list(APPEND LINPHONE_LIBRARIES shlwapi)
endif(WIN32)
list(REMOVE_DUPLICATES LINPHONE_INCLUDE_DIRS)
list(REMOVE_DUPLICATES LINPHONE_LIBRARIES)
set(LINPHONE_CPPFLAGS "${MS2_CPPFLAGS}")
set(LINPHONE_LDFLAGS "${MS2_LDFLAGS} ${BELLESIP_LDFLAGS}")
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Linphone
DEFAULT_MSG
LINPHONE_INCLUDE_DIRS LINPHONE_LIBRARIES
)
mark_as_advanced(LINPHONE_INCLUDE_DIRS LINPHONE_LIBRARIES LINPHONE_CPPFLAGS LINPHONE_LDFLAGS)

7
README
View file

@ -33,10 +33,13 @@ This is Linphone, a free (GPL) video softphone based on the SIP protocol.
Here is the command line to get these dependencies installed for Ubuntu && Debian
$ sudo apt-get install libtool intltool libgtk2.0-dev libspeexdsp-dev libavcodec-dev libswscale-dev libx11-dev libxv-dev libgl1-mesa-dev libglew1.6-dev libv4l-dev libxml2-dev
$ sudo apt-get install libtool intltool libgtk2.0-dev libspeexdsp-dev \
libavcodec-dev libswscale-dev libx11-dev libxv-dev libgl1-mesa-dev \
libglew1.6-dev libv4l-dev libxml2-dev
+ for optional library
$ sudo apt-get install libreadline-dev libgsm1-dev libtheora-dev libsoup2.4-dev libsqlite3-dev libupnp4-dev
$ sudo apt-get install libreadline-dev libgsm1-dev libtheora-dev \
libsoup2.4-dev libsqlite3-dev libupnp4-dev
+ Install srtp (optional) for call encryption :
$ git clone git://git.linphone.org/srtp.git

View file

@ -4,6 +4,7 @@
You need:
- Xcode (download from apple or using appstore application)
- Java SE
- Macports: http://www.macports.org/
Download and install macports using its user friendly installer.
@ -17,7 +18,7 @@ You need:
$ sudo port install automake autoconf libtool intltool wget cunit
- Install some linphone dependencies with macports
$ sudo port install antlr3 speex libvpx readline sqlite3 libsoup openldap
$ sudo port install antlr3 speex libvpx readline sqlite3 libsoup openldap libupnp
$ sudo port install ffmpeg-devel -gpl2
- Install gtk. It is recommended to use the quartz backend for better integration.

View file

@ -4,20 +4,20 @@ Software to install
Download lastest mingw-get-setup.exe from http://www.mingw.org
Run mingw-get-setup.exe.
In the package list, select and install:
* mingw32-developer-tool
* mingw-developer-toolkit
* mingw32-base
* mingw32-gcc-g++
* mingw32-pthreads-w32
* msys-base
* msys-zip
* msys-unzip
* msys-wget
For more information:
http://www.mingw.org/wiki/Getting_Started
In mingw shell (also refered as msys), run
mingw-get install msys-zip
mingw-get install msys-unzip
mingw-get install msys-wget
mkdir -p /opt/perl/bin
cp /bin/perl /opt/perl/bin/.
@ -29,7 +29,7 @@ Download lastest linphone-deps-win32 zip from
http://download.savannah.gnu.org/releases-noredirect/linphone/misc
using your browser.
Download lastest gtk+-2.24.10 win32 _bundle_ from http://www.gtk.org
Download gtk+-2.24.10 win32 _bundle_ from http://www.gtk.org, direct link: http://ftp.gnome.org/pub/gnome/binaries/win32/gtk+/2.24/gtk+-bundle_2.24.10-20120208_win32.zip
Install all these three package in /:
@ -48,7 +48,7 @@ libintl.a libintl.la libintl.dll.a
* Download and install Inno Setup Compiler (required only if you run 'make setup.exe'). Add it to your windows Path environment variable.
* Install msys-git from (http://code.google.com/p/msysgit/). During installation you are asked to make a choice about how line endings are treated by git. Choose "Checkout line endings as they are, commit as they are". THIS CHOICE IS VERY IMPORTANT. OTHERS BREAK AUTOMAKE.
* Install msys-git from (http://msysgit.github.io/). During installation you are asked to make a choice about how line endings are treated by git. Choose "Checkout line endings as they are, commit as they are". THIS CHOICE IS VERY IMPORTANT. OTHERS BREAK AUTOMAKE.
General rules for compilation
@ -63,6 +63,7 @@ cd /c/sources
Building belle-sip
******************
* make sure that java version 1.6 is available in the PATH. java-1.7 will not work with antlr generator.
* download the sources with msys-git shell using the following command:
$ git clone git://git.linphone.org/belle-sip.git
* compile and install
@ -98,7 +99,8 @@ Building plugins (optional)
***************************
This the example for msx264 (H264 plugin), the same applies for other linphone plugins.
$ cd mediastreamer2/plugins/msx264
$ git clone git://git.linphone.org/msx264.git
$ cd msx264
$ ./autogen.sh
$ PKG_CONFIG_PATH=/usr/lib/pkgconfig ./configure --prefix=/usr --enable-shared --disable-static
#make a binary zip of this plugin

View file

@ -65,11 +65,14 @@ LOCAL_SRC_FILES := \
xml2lpc.c \
lpc2xml.c \
remote_provisioning.c \
quality_reporting.c \
call_log.c \
call_params.c \
lime.c \
quality_reporting.c
player.c
ifndef LINPHONE_VERSION
LINPHONE_VERSION = "Devel"
ifndef LIBLINPHONE_VERSION
LIBLINPHONE_VERSION = "Devel"
endif
LOCAL_CFLAGS += \
@ -78,7 +81,7 @@ LOCAL_CFLAGS += \
-DINET6 \
-DENABLE_TRACE \
-DHAVE_CONFIG_H \
-DLINPHONE_VERSION=\"$(LINPHONE_VERSION)\" \
-DLIBLINPHONE_VERSION=\"$(LIBLINPHONE_VERSION)\" \
-DLINPHONE_PLUGINS_DIR=\"\\tmp\" \
-DUSE_BELLESIP

View file

@ -1 +0,0 @@
#define LIBLINPHONE_GIT_VERSION "unknown"

View file

@ -13,7 +13,8 @@ common_SRC_FILES := \
flexisip_tester.c \
tester.c \
remote_provisioning_tester.c \
quality_reporting_tester.c
quality_reporting_tester.c \
transport_tester.c
common_C_INCLUDES += \
$(LOCAL_PATH) \
@ -32,6 +33,10 @@ LOCAL_C_INCLUDES = $(common_C_INCLUDES)
LOCAL_CFLAGS = -DIN_LINPHONE
LOCAL_LDLIBS := -llog
ifeq ($(BUILD_MATROSKA), 1)
LOCAL_CFLAGS += -DHAVE_MATROSKA
endif
LOCAL_SHARED_LIBRARIES := cunit liblinphone
include $(BUILD_SHARED_LIBRARY)

View file

@ -107,6 +107,8 @@
<ClCompile Include="..\..\coreapi\bellesip_sal\sal_op_publish.c" />
<ClCompile Include="..\..\coreapi\bellesip_sal\sal_op_registration.c" />
<ClCompile Include="..\..\coreapi\bellesip_sal\sal_sdp.c" />
<ClCompile Include="..\..\coreapi\call_log.c" />
<ClCompile Include="..\..\coreapi\call_params.c" />
<ClCompile Include="..\..\coreapi\callbacks.c" />
<ClCompile Include="..\..\coreapi\chat.c" />
<ClCompile Include="..\..\coreapi\conference.c" />
@ -124,6 +126,7 @@
<ClCompile Include="..\..\coreapi\message_storage.c" />
<ClCompile Include="..\..\coreapi\misc.c" />
<ClCompile Include="..\..\coreapi\offeranswer.c" />
<ClCompile Include="..\..\coreapi\player.c" />
<ClCompile Include="..\..\coreapi\presence.c" />
<ClCompile Include="..\..\coreapi\proxy.c" />
<ClCompile Include="..\..\coreapi\quality_reporting.c" />

View file

@ -105,6 +105,7 @@
<ClCompile Include="..\..\..\tester\setup_tester.c" />
<ClCompile Include="..\..\..\tester\stun_tester.c" />
<ClCompile Include="..\..\..\tester\tester.c" />
<ClCompile Include="..\..\..\tester\transport_tester.c" />
<ClCompile Include="linphone-tester-native.cpp">
<CompileAsWinRT>true</CompileAsWinRT>
</ClCompile>
@ -153,4 +154,4 @@
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsPhone\v$(TargetPlatformVersion)\Microsoft.Cpp.WindowsPhone.$(TargetPlatformVersion).targets" />
</Project>
</Project>

32
config.h.cmake Normal file
View file

@ -0,0 +1,32 @@
/***************************************************************************
* config.h.cmake
* Copyright (C) 2014 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.
*
****************************************************************************/
#define LINPHONE_MAJOR_VERSION ${LINPHONE_MAJOR_VERSION}
#define LINPHONE_MINOR_VERSION ${LINPHONE_MINOR_VERSION}
#define LINPHONE_MICRO_VERSION ${LINPHONE_MICRO_VERSION}
#define LINPHONE_VERSION "${LINPHONE_VERSION}"
#define LIBLINPHONE_VERSION "${LINPHONE_VERSION}"
#define LINPHONE_PLUGINS_DIR "${LINPHONE_PLUGINS_DIR}"
#define PACKAGE_LOCALE_DIR "${PACKAGE_LOCALE_DIR}"
#define PACKAGE_DATA_DIR "${PACKAGE_DATA_DIR}"
#define PACKAGE_SOUND_DIR "${PACKAGE_SOUND_DIR}"

View file

@ -36,7 +36,7 @@ m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])],)
AC_SUBST([docdir], [${datadir}/doc])
AC_CONFIG_HEADERS(config.h)
AC_CONFIG_MACRO_DIR([m4])
dnl don't put anythingelse before AC_PROG_CC unless checking if macro still work for clang
dnl do not put anythingelse before AC_PROG_CC unless checking if macro still work for clang
AC_PROG_CXX(["xcrun clang++" g++])
AC_PROG_CC(["xcrun clang" gcc])
@ -135,7 +135,7 @@ AC_DEFINE_UNQUOTED(LINPHONE_ALL_LANGS, "$ALL_LINGUAS", [All supported languages]
if test "$mingw_found" != "yes" ; then
dnl gettext macro does not work properly under mingw. And we want to use the one provided by GTK.
dnl AM_GNU_GETTEXT pollutes CPPFLAGS: workaround this.
CPPFLAGS_save=$CPPFLAGS
AM_GNU_GETTEXT([external])
@ -185,29 +185,29 @@ if test "$enable_ldap" = "true"; then
[AC_MSG_ERROR([You need libldap for LDAP support])]
)
AC_CHECK_HEADERS(ldap.h, [foo=bar], [AC_MSG_ERROR( [ldap.h not found] ) ] )
found_ldap=yes
found_ldap=yes
fi
PKG_CHECK_MODULES(SASL, [libsasl2],[found_sasl=yes],[found_sasl=no] )
if test "$found_sasl" = "no"; then
AC_CHECK_LIB(sasl2, sasl_client_init , [SASL_LIBS="-lsasl2"],
[AC_MSG_ERROR([You need SASL for LDAP support] ) ]
)
AC_CHECK_HEADERS(sasl/sasl.h,foo=bar, [AC_MSG_ERROR([sasl/sasl.h not found])])
found_sasl=yes
found_sasl=yes
fi
AC_SUBST(LDAP_CFLAGS)
AC_SUBST(LDAP_LIBS)
AC_SUBST(SASL_CFLAGS)
AC_SUBST(SASL_LIBS)
if test "$found_ldap$found_sasl" = "yesyes"; then
AC_DEFINE(BUILD_LDAP,1,[Defined if LDAP build option enabled])
else
AC_MSG_ERROR([Can't use LDAP due to previous errors])
AC_MSG_ERROR([Cannot use LDAP due to previous errors])
fi
fi
@ -248,7 +248,7 @@ AC_ARG_ENABLE(upnp,
)
if test "$build_upnp" != "false" ; then
PKG_CHECK_MODULES([LIBUPNP], [libupnp],
PKG_CHECK_MODULES([LIBUPNP], [libupnp],
[if pkg-config --atleast-version=1.6 "libupnp < 1.7"; then
build_upnp=true
else
@ -277,7 +277,7 @@ 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] )
AC_DEFINE(BUILD_TOOLS, 1, [Define if tools enabled] )
fi
dnl conditionnal build of gtk interface.
@ -537,7 +537,7 @@ fi
dnl conditionnal build of video support
AC_ARG_ENABLE(video,
[AS_HELP_STRING([--enable-video], [Turn on video support compiling])],
[AS_HELP_STRING([--enable-video], [Turn on video support compiling (default=yes)])],
[case "${enableval}" in
yes) video=true ;;
no) video=false ;;
@ -553,10 +553,10 @@ AC_ARG_WITH(ffmpeg,
)
if test "$video" = "true"; then
if test "$enable_x11" = "true"; then
AC_CHECK_HEADERS(X11/Xlib.h)
if test "$build_macos" = "yes"; then
if test "$build_macos" = "yes"; then
X11_LIBS="-L/usr/X11/lib -lX11"
else
AC_CHECK_LIB(X11,XUnmapWindow, X11_LIBS="-lX11")
@ -644,7 +644,7 @@ 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] )
AC_DEFINE(BUILD_WIZARD, 1, [Define if wizard enabled] )
fi
AC_CHECK_HEADERS(libudev.h)
@ -656,27 +656,42 @@ AC_CHECK_LIB(udev,udev_new)
AC_ARG_ENABLE(strict,
AC_HELP_STRING([--enable-strict], [Build with stricter options (gcc only) @<:@yes@:>@]),
AC_HELP_STRING([--enable-strict], [Build with stricter options @<:@yes@:>@]),
[strictness="${enableval}"],
[strictness=yes]
)
STRICT_OPTIONS="-Wall"
STRICT_OPTIONS="-Wall -Wuninitialized"
STRICT_OPTIONS_CC="-Wdeclaration-after-statement "
STRICT_OPTIONS_CXX=""
#for clang
case $CC in
case $CC in
*clang*)
STRICT_OPTIONS="$STRICT_OPTIONS -Qunused-arguments"
STRICT_OPTIONS="$STRICT_OPTIONS -Qunused-arguments "
#disabled due to wrong optimization false positive with small string
#(cf. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=35903)
STRICT_OPTIONS="$STRICT_OPTIONS -Wno-array-bounds "
;;
esac
# because Darwin's gcc is actually clang, we need to check it...
case "$target_os" in
*darwin*)
STRICT_OPTIONS="$STRICT_OPTIONS -Wno-error=unknown-warning-option -Qunused-arguments -Wno-tautological-compare -Wno-unused-function "
#disabled due to wrong optimization false positive with small string
#(cf. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=35903)
STRICT_OPTIONS="$STRICT_OPTIONS -Wno-array-bounds "
;;
esac
if test "$strictness" = "yes" ; then
STRICT_OPTIONS="$STRICT_OPTIONS -Werror"
CFLAGS="$CFLAGS -fno-strict-aliasing"
fi
AC_SUBST(STRICT_OPTIONS)
AC_SUBST(STRICT_OPTIONS_CC)
AC_SUBST(STRICT_OPTIONS_CXX)
top_srcdir=`dirname $0`
@ -783,13 +798,13 @@ if test x$enable_msg_storage != xfalse; then
fi
enable_msg_storage=false
fi
AC_SUBST(SQLITE3_CFLAGS)
AC_SUBST(SQLITE3_LIBS)
fi
PKG_CHECK_MODULES(BELLESIP, [belle-sip >= 1.3.1])
SIPSTACK_CFLAGS="$BELLESIP_CFLAGS"
@ -887,7 +902,7 @@ AC_PATH_PROG(DOXYGEN,doxygen,false)
AM_CONDITIONAL(HAVE_DOXYGEN, test $DOXYGEN != false)
AC_CONFIG_FILES([
AC_CONFIG_FILES([
Makefile
build/Makefile
build/macos/Makefile

View file

@ -3,12 +3,13 @@
AM_CPPFLAGS=\
-I$(top_srcdir) \
-I$(top_srcdir)/coreapi \
-I$(top_srcdir)/include
-I$(top_srcdir)/include
COMMON_CFLAGS=\
-DIN_LINPHONE \
-D_ORTP_SOURCE \
$(STRICT_OPTIONS) \
$(STRICT_OPTIONS_CC) \
$(ORTP_CFLAGS) \
$(MEDIASTREAMER_CFLAGS) \
$(VIDEO_CFLAGS) \

View file

@ -515,7 +515,7 @@ lpc_cmd_help(LinphoneCore *lc, char *arg)
i=0;
while (advanced_commands[i].help)
{
linphonec_out("%10.10s\t%s\n", advanced_commands[i].name,
linphonec_out("%20.20s\t%s\n", advanced_commands[i].name,
advanced_commands[i].help);
i++;
}
@ -603,6 +603,7 @@ lpc_cmd_chat(LinphoneCore *lc, char *args)
char *arg1 = args;
char *arg2 = NULL;
char *ptr = args;
LinphoneChatRoom *cr;
if (!args) return 0;
@ -619,7 +620,7 @@ lpc_cmd_chat(LinphoneCore *lc, char *args)
/* missing one parameter */
return 0;
}
LinphoneChatRoom *cr = linphone_core_create_chat_room(lc,arg1);
cr = linphone_core_create_chat_room(lc,arg1);
linphone_chat_room_send_message(cr,arg2);
return 1;
}
@ -2441,8 +2442,9 @@ static void lpc_display_call_states(LinphoneCore *lc){
}else{
for(;elem!=NULL;elem=elem->next){
const char *flag;
bool_t in_conference;
call=(LinphoneCall*)elem->data;
bool_t in_conference=linphone_call_params_get_local_conference_mode(linphone_call_get_current_params(call));
in_conference=linphone_call_params_get_local_conference_mode(linphone_call_get_current_params(call));
tmp=linphone_call_get_remote_address_as_string (call);
flag=in_conference ? "conferencing" : "";
flag=linphone_call_has_transfer_pending(call) ? "transfer pending" : flag;

View file

@ -367,8 +367,8 @@ static void linphonec_call_state_changed(LinphoneCore *lc, LinphoneCall *call, L
if ( auto_answer) {
answer_call=TRUE;
} else if (real_early_media_sending) {
linphonec_out("Sending early media using real hardware\n");
LinphoneCallParams* callparams = linphone_core_create_default_call_parameters(lc);
linphonec_out("Sending early media using real hardware\n");
linphone_call_params_enable_early_media_sending(callparams, TRUE);
if (vcap_enabled) linphone_call_params_enable_video(callparams, TRUE);
linphone_core_accept_early_media_with_params(lc, call, callparams);
@ -536,6 +536,7 @@ char *linphonec_readline(char *prompt){
fprintf(stdout,"%s",prompt);
fflush(stdout);
while(1){
ms_mutex_lock(&prompt_mutex);
if (have_prompt){
char *ret=strdup(received_prompt);
@ -546,15 +547,17 @@ char *linphonec_readline(char *prompt){
ms_mutex_unlock(&prompt_mutex);
linphonec_idle_call();
#ifdef WIN32
Sleep(20);
/* Following is to get the video window going as it
should. Maybe should we only have this on when the option -V
or -D is on? */
MSG msg;
{
MSG msg;
Sleep(20);
/* Following is to get the video window going as it
should. Maybe should we only have this on when the option -V
or -D is on? */
if (PeekMessage(&msg, NULL, 0, 0,1)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
if (PeekMessage(&msg, NULL, 0, 0,1)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
#else
usleep(20000);
@ -747,7 +750,7 @@ linphonec_init(int argc, char **argv)
linphone_core_enable_video_display(linphonec, display_enabled);
if (display_enabled && window_id != 0)
{
printf ("Setting window_id: 0x%x\n", window_id);
printf("Setting window_id: 0x%x\n", window_id);
linphone_core_set_native_video_window_id(linphonec,window_id);
}
@ -828,12 +831,13 @@ linphonec_prompt_for_auth_final(LinphoneCore *lc)
#ifdef HAVE_READLINE
rl_hook_func_t *old_event_hook;
#endif
LinphoneAuthInfo *pending_auth;
if (reentrancy!=0) return 0;
reentrancy++;
LinphoneAuthInfo *pending_auth=auth_stack.elem[auth_stack.nitems-1];
pending_auth=auth_stack.elem[auth_stack.nitems-1];
snprintf(auth_prompt, 256, "Password for %s on %s: ",
pending_auth->username, pending_auth->realm);

View file

@ -177,12 +177,14 @@ static void spawn_linphonec(int argc, char *argv[]){
static void spawn_linphonec(int argc, char *argv[]){
PROCESS_INFORMATION pinfo;
STARTUPINFO si;
BOOL ret;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pinfo, sizeof(pinfo) );
BOOL ret=CreateProcess(NULL,"linphoned.exe --pipe -c NUL",
ret=CreateProcess(NULL,"linphoned.exe --pipe -c NUL",
NULL,
NULL,
FALSE,

View file

@ -1,47 +1,30 @@
############################################################################
# CMakeLists.txt
# Copyright (C) 2014 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.
#
############################################################################
if(MSVC)
find_library(LIBGCC NAMES gcc)
find_library(LIBMINGWEX NAMES mingwex)
endif()
find_library(LIBORTP NAMES ortp)
find_library(LIBMEDIASTREAMER_BASE NAMES mediastreamer_base)
find_library(LIBMEDIASTREAMER_VOIP NAMES mediastreamer_voip)
find_library(LIBBELLESIP NAMES bellesip)
find_library(LIBXML2 NAMES xml2)
find_program(GIT git)
set(GIT_VERSION "unknown")
if(GIT)
execute_process(
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMAND ${GIT} describe --always
OUTPUT_VARIABLE GIT_DESCRIBE
OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMAND ${GIT} describe --abbrev=0
OUTPUT_VARIABLE GIT_TAG
OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMAND ${GIT} rev-parse HEAD
OUTPUT_VARIABLE GIT_REVISION
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(GIT_DESCRIBE)
set(GIT_VERSION ${GIT_DESCRIBE})
else(GIT_DESCRIBE)
if(GIT_REVISION)
set(GIT_VERSION ${GIT_REVISION})
endif(GIT_REVISION)
endif(GIT_DESCRIBE)
endif(GIT)
execute_process(
COMMAND ${CMAKE_COMMAND} -E echo "#define LIBLINPHONE_GIT_VERSION \"${GIT_VERSION}\""
OUTPUT_FILE ${CMAKE_CURRENT_BINARY_DIR}/liblinphone_gitversion.h
)
set(SOURCE_FILES
address.c
@ -59,6 +42,8 @@ set(SOURCE_FILES
bellesip_sal/sal_op_registration.c
bellesip_sal/sal_sdp.c
callbacks.c
call_log.c
call_params.c
chat.c
conference.c
ec-calibrator.c
@ -68,7 +53,6 @@ set(SOURCE_FILES
info.c
linphonecall.c
linphonecore.c
#linphone_tunnel.cc
linphone_tunnel_stubs.c
linphone_tunnel_config.c
lpconfig.c
@ -76,6 +60,7 @@ set(SOURCE_FILES
message_storage.c
misc.c
offeranswer.c
player.c
presence.c
proxy.c
quality_reporting.c
@ -83,7 +68,6 @@ set(SOURCE_FILES
sal.c
siplogin.c
sipsetup.c
#TunnelManager.cc
xml.c
xml2lpc.c
bellesip_sal/sal_impl.h
@ -99,55 +83,86 @@ set(SOURCE_FILES
sipsetup.h
xml2lpc.h
)
if(ENABLE_TUNNEL)
list(APPEND SOURCE_FILES
linphone_tunnel.cc
TunnelManager.cc
)
add_definitions(-DTUNNEL_ENABLED)
endif()
set(GENERATED_SOURCE_FILES
${CMAKE_CURRENT_BINARY_DIR}/liblinphone_gitversion.h
)
set_source_files_properties(${GENERATED_SOURCE_FILES} PROPERTIES GENERATED TRUE)
find_package(Git)
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/liblinphone_gitversion.h
COMMAND ${CMAKE_COMMAND} -DGIT_EXECUTABLE=${GIT_EXECUTABLE} -DWORK_DIR=${CMAKE_CURRENT_SOURCE_DIR} -DOUTPUT_DIR=${CMAKE_CURRENT_BINARY_DIR} -P ${CMAKE_CURRENT_SOURCE_DIR}/gitversion.cmake)
add_definitions(
-D_TRUE_TIME
-DIN_LINPHONE
-DUSE_BELLESIP
#-DTUNNEL_ENABLED
-DLINPHONE_PACKAGE_NAME="linphone"
-DLINPHONE_VERSION="Devel"
-DLIBLINPHONE_EXPORTS
-DLINPHONE_PLUGINS_DIR=""
)
if(LINPHONE_ENABLE_VIDEO)
if(ENABLE_VIDEO)
add_definitions(-DVIDEO_ENABLED)
endif(LINPHONE_ENABLE_VIDEO)
endif()
if(WIN32)
add_definitions(
-DWINDOW_NATIVE
/FIliblinphone_gitversion.h
set(LIBS
${LIBGCC}
${LIBMINGWEX}
${BELLESIP_LIBRARIES}
${MS2_LIBRARIES}
${XML2_LIBRARIES}
)
if(WIN32)
list(APPEND LIBS shlwapi)
endif()
set(LIBS ws2_32)
endif(WIN32)
set(LIBS ${LIBS} ${LIBGCC} ${LIBMINGWEX} ${LIBORTP} ${LIBMEDIASTREAMER_BASE} ${LIBMEDIASTREAMER_VOIP} ${LIBBELLESIP} ${LIBXML2})
add_library(linphone SHARED ${SOURCE_FILES})
set_target_properties(linphone PROPERTIES VERSION 3.7.0 SOVERSION 5)
target_link_libraries(linphone ${LIBS})
if(ENABLE_STATIC)
add_library(linphone STATIC ${SOURCE_FILES} ${GENERATED_SOURCE_FILES})
target_link_libraries(linphone ${LIBS})
else()
add_library(linphone SHARED ${SOURCE_FILES} ${GENERATED_SOURCE_FILES})
set_target_properties(linphone PROPERTIES VERSION ${LINPHONE_VERSION} SOVERSION ${LINPHONE_SO_VERSION} LINKER_LANGUAGE CXX)
target_link_libraries(linphone ${LIBS})
if(MSVC)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/Debug/linphone.pdb
DESTINATION bin
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
)
endif()
endif()
endif()
install(TARGETS linphone
RUNTIME DESTINATION bin
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
)
file(GLOB HEADER_FILES "*.h")
set(HEADER_FILES
call_log.h
call_params.h
event.h
linphonecore.h
linphonecore_utils.h
linphonefriend.h
linphonepresence.h
linphone_tunnel.h
lpc2xml.h
lpconfig.h
sipsetup.h
xml2lpc.h
)
install(FILES ${HEADER_FILES}
DESTINATION include/linphone
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
)
if(WIN32)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/Debug/linphone.pdb
DESTINATION bin
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
)
endif()
endif(WIN32)
add_subdirectory(help)

View file

@ -5,6 +5,12 @@ GITDESCRIBE=`cd $(top_srcdir) && git describe --always`
GIT_TAG=`cd $(top_srcdir) && git describe --abbrev=0`
GITREVISION=`cd $(top_srcdir) && git rev-parse HEAD`
## This command is used to check if the sources are cloned in a git repo.
## We can't only depend on the presence of the .git/ directory anymore,
## because of gits submodule handling.
## We now simply issue a git log on configure.ac and if the output is empty (error or file not tracked), then we are not in git.
GITLOG=$(shell git log -1 --pretty=format:%H $(top_srcdir)/configure.ac)
ECHO=/bin/echo
SUBDIRS=. help
@ -18,7 +24,7 @@ CLEANFILES=$(GITVERSION_FILE)
## Process this file with automake to produce Makefile.in
linphone_includedir=$(includedir)/linphone
linphone_include_HEADERS=linphonecore.h linphonefriend.h linphonepresence.h linphonecore_utils.h lpconfig.h sipsetup.h event.h xml2lpc.h lpc2xml.h linphone_tunnel.h
linphone_include_HEADERS=linphonecore.h linphonefriend.h linphonepresence.h linphonecore_utils.h lpconfig.h sipsetup.h event.h xml2lpc.h lpc2xml.h linphone_tunnel.h call_log.h call_params.h
lib_LTLIBRARIES=liblinphone.la
@ -54,12 +60,15 @@ liblinphone_la_SOURCES=\
remote_provisioning.c \
lime.c \
quality_reporting.c quality_reporting.h\
call_log.c \
call_params.c \
player.c \
$(GITVERSION_FILE)
if BUILD_UPNP
liblinphone_la_SOURCES+=upnp.c upnp.h
endif
liblinphone_la_SOURCES+= bellesip_sal/sal_address_impl.c \
bellesip_sal/sal_impl.c bellesip_sal/sal_impl.h \
bellesip_sal/sal_op_impl.c \
@ -74,7 +83,7 @@ liblinphone_la_SOURCES+= bellesip_sal/sal_address_impl.c \
bellesip_sal/sal_op_events.c
if BUILD_WIZARD
liblinphone_la_SOURCES+=sipwizard.c
liblinphone_la_SOURCES+=sipwizard.c
endif
liblinphone_la_SOURCES+=linphone_tunnel_config.c
@ -133,8 +142,9 @@ endif
AM_CPPFLAGS=\
-I$(top_srcdir) -I$(top_srcdir)/include -I$(builddir)
AM_CFLAGS=\
$(STRICT_OPTIONS) -DIN_LINPHONE \
COMMON_CFLAGS=\
$(STRICT_OPTIONS) \
-DIN_LINPHONE \
$(ORTP_CFLAGS) \
$(MEDIASTREAMER_CFLAGS) \
$(SIPSTACK_CFLAGS) \
@ -150,19 +160,20 @@ AM_CFLAGS=\
$(LDAP_CFLAGS) $(SASL_CFLAGS)
if BUILD_WIZARD
AM_CFLAGS+= -DBUILD_WIZARD
COMMON_CFLAGS+= -DBUILD_WIZARD
endif
AM_CFLAGS+= -DUSE_BELLESIP
COMMON_CFLAGS+= -DUSE_BELLESIP
AM_CXXFLAGS=$(AM_CFLAGS)
AM_CFLAGS=$(COMMON_CFLAGS) $(STRICT_OPTIONS_CC)
AM_CXXFLAGS=$(COMMON_CFLAGS) $(STRICT_OPTIONS_CXX)
#Make sure that we are in linphone's git tree by doing git log $(top_srcdir)/configure.ac.
#if it is something known to git, then that will be ok to check the git describe number and make sure it is consistent with
#if it is something known to git, then that will be ok to check the git describe number and make sure it is consistent with
#the PACKAGE_VERSION given in configure.ac
make_gitversion_h:
if test -d $(top_srcdir)/.git ; then \
if test -n "$(GITLOG)" ; then \
if test "$(GITDESCRIBE)" != "" ; then \
if test "$(GIT_TAG)" != "$(PACKAGE_VERSION)" ; then \
echo "*** PACKAGE_VERSION and git tag differ. Please put them identical."; \

View file

@ -1,7 +1,7 @@
/*
* C Implementation: tunnel
*
* Description:
* Description:
*
*
* Author: Simon Morlat <simon.morlat@linphone.org>, (C) 2009
@ -19,18 +19,17 @@
#ifndef USE_BELLESIP
#include "eXosip2/eXosip_transport_hook.h"
#endif
#include "tunnel/udp_mirror.hh"
#include "private.h"
#ifdef ANDROID
#include <android/log.h>
#endif
belledonnecomm::TunnelManager *bcTunnel(const LinphoneTunnel *tunnel);
using namespace belledonnecomm;
using namespace ::std;
void TunnelManager::addServer(const char *ip, int port,unsigned int udpMirrorPort,unsigned int delay) {
if (ip == NULL) {
ip = "";
@ -53,7 +52,6 @@ void TunnelManager::cleanServers() {
mServerAddrs.clear();
UdpMirrorClientList::iterator it;
mAutoDetectStarted=false;
for (it = mUdpMirrorClients.begin(); it != mUdpMirrorClients.end();) {
UdpMirrorClient& s=*it++;
s.stop();
@ -67,11 +65,6 @@ void TunnelManager::reconnect(){
mTunnelClient->reconnect();
}
void TunnelManager::setCallback(StateCallback cb, void *userdata) {
mCallback=cb;
mCallbackData=userdata;
}
static void sCloseRtpTransport(RtpTransport *t, void *userData){
TunnelSocket *s=(TunnelSocket*)userData;
TunnelManager *manager=(TunnelManager*)s->getUserPointer();
@ -79,13 +72,16 @@ static void sCloseRtpTransport(RtpTransport *t, void *userData){
}
void TunnelManager::closeRtpTransport(RtpTransport *t, TunnelSocket *s){
mTunnelClient->closeSocket(s);
ms_free(t);
}
static RtpTransport *sCreateRtpTransport(void* userData, int port){
return ((TunnelManager *) userData)->createRtpTransport(port);
}
void sDestroyRtpTransport(RtpTransport *t){
ms_free(t);
}
RtpTransport *TunnelManager::createRtpTransport(int port){
TunnelSocket *socket=mTunnelClient->createSocket(port);
socket->setUserPointer(this);
@ -94,14 +90,15 @@ RtpTransport *TunnelManager::createRtpTransport(int port){
t->t_recvfrom=customRecvfrom;
t->t_sendto=customSendto;
t->t_close=sCloseRtpTransport;
t->t_destroy=sDestroyRtpTransport;
t->data=socket;
return t;
}
void TunnelManager::start() {
if (!mTunnelClient) {
void TunnelManager::startClient() {
if (mTunnelClient == NULL) {
mTunnelClient = new TunnelClient();
mTunnelClient->setCallback((StateCallback)tunnelCallback,this);
mTunnelClient->setCallback((TunnelClientController::StateCallback)tunnelCallback,this);
list<ServerAddr>::iterator it;
for(it=mServerAddrs.begin();it!=mServerAddrs.end();++it){
const ServerAddr &addr=*it;
@ -110,14 +107,23 @@ void TunnelManager::start() {
mTunnelClient->setHttpProxy(mHttpProxyHost.c_str(), mHttpProxyPort, mHttpUserName.c_str(), mHttpPasswd.c_str());
}
mTunnelClient->start();
linphone_core_set_rtp_transport_factories(mCore,&mTransportFactories);
if(mTunnelizeSipPackets) {
sal_enable_tunnel(mCore->sal, mTunnelClient);
}
}
bool TunnelManager::isStarted() {
return mTunnelClient != 0 && mTunnelClient->isStarted();
void TunnelManager::stopClient(){
linphone_core_set_rtp_transport_factories(mCore,NULL);
sal_disable_tunnel(mCore->sal);
if (mTunnelClient){
delete mTunnelClient;
mTunnelClient=NULL;
}
}
bool TunnelManager::isReady() const {
return mTunnelClient && mTunnelClient->isReady() && mReady;
bool TunnelManager::isConnected() const {
return mTunnelClient != NULL && mTunnelClient->isReady();
}
int TunnelManager::customSendto(struct _RtpTransport *t, mblk_t *msg , int flags, const struct sockaddr *to, socklen_t tolen){
@ -135,15 +141,20 @@ int TunnelManager::customRecvfrom(struct _RtpTransport *t, mblk_t *msg, int flag
}
TunnelManager::TunnelManager(LinphoneCore* lc) :TunnelClientController()
,mCore(lc)
,mCallback(NULL)
,mEnabled(false)
,mTunnelClient(NULL)
,mAutoDetectStarted(false)
,mReady(false)
,mHttpProxyPort(0){
TunnelManager::TunnelManager(LinphoneCore* lc) :
mCore(lc),
#ifndef USE_BELLESIP
mSipSocket(NULL),
mExosipTransport(NULL),
#endif
mMode(LinphoneTunnelModeDisable),
mTunnelClient(NULL),
mIsConnected(false),
mHttpProxyPort(0),
mPreviousRegistrationEnabled(false),
mTunnelizeSipPackets(true),
mVTable(NULL)
{
linphone_core_add_iterate_hook(mCore,(LinphoneCoreIterateHook)sOnIterate,this);
mTransportFactories.audio_rtcp_func=sCreateRtpTransport;
mTransportFactories.audio_rtcp_func_data=this;
@ -153,104 +164,94 @@ TunnelManager::TunnelManager(LinphoneCore* lc) :TunnelClientController()
mTransportFactories.video_rtcp_func_data=this;
mTransportFactories.video_rtp_func=sCreateRtpTransport;
mTransportFactories.video_rtp_func_data=this;
mVTable = linphone_vtable_new();
mVTable->network_reachable = networkReachableCb;
linphone_core_add_listener(mCore, mVTable);
}
TunnelManager::~TunnelManager(){
stopClient();
linphone_core_remove_listener(mCore, mVTable);
linphone_vtable_destroy(mVTable);
}
void TunnelManager::stopClient(){
sal_disable_tunnel(mCore->sal);
if (mTunnelClient){
delete mTunnelClient;
mTunnelClient=NULL;
void TunnelManager::registration(){
// registration occurs always after an unregistation has been made. First we
// need to reset the previous registration mode
LinphoneProxyConfig* lProxy;
linphone_core_get_default_proxy(mCore, &lProxy);
if (lProxy) {
linphone_proxy_config_edit(lProxy);
linphone_proxy_config_enable_register(lProxy,mPreviousRegistrationEnabled);
linphone_proxy_config_done(lProxy);
}
}
void TunnelManager::processTunnelEvent(const Event &ev){
LinphoneProxyConfig* lProxy;
linphone_core_get_default_proxy(mCore, &lProxy);
if (mEnabled && mTunnelClient->isReady()){
if (ev.mData.mConnected){
ms_message("Tunnel is up, registering now");
linphone_core_set_firewall_policy(mCore,LinphonePolicyNoFirewall);
linphone_core_set_rtp_transport_factories(mCore,&mTransportFactories);
sal_enable_tunnel(mCore->sal, mTunnelClient);
//register
if (lProxy) {
linphone_proxy_config_refresh_register(lProxy);
}
mReady=true;
}else if (mEnabled && !mTunnelClient->isReady()){
/* we got disconnected from the tunnel */
mReady=false;
registration();
} else {
ms_error("Tunnel has been disconnected");
}
}
void TunnelManager::waitUnRegistration(){
void TunnelManager::waitUnRegistration() {
LinphoneProxyConfig* lProxy;
linphone_core_get_default_proxy(mCore, &lProxy);
if (lProxy && linphone_proxy_config_get_state(lProxy)==LinphoneRegistrationOk) {
int i=0;
linphone_proxy_config_edit(lProxy);
linphone_proxy_config_enable_register(lProxy,FALSE);
linphone_proxy_config_done(lProxy);
//make sure unregister is sent and authenticated
do{
linphone_core_iterate(mCore);
ms_usleep(20000);
if (i>100){
ms_message("tunnel: timeout for unregistration expired, giving up");
break;
}
i++;
}while(linphone_proxy_config_get_state(lProxy)!=LinphoneRegistrationCleared);
}
if (lProxy){
mPreviousRegistrationEnabled=linphone_proxy_config_register_enabled(lProxy);
if (linphone_proxy_config_is_registered(lProxy)) {
int i=0;
linphone_proxy_config_edit(lProxy);
linphone_proxy_config_enable_register(lProxy,FALSE);
linphone_proxy_config_done(lProxy);
sal_unregister(lProxy->op);
//make sure unregister is sent and authenticated
do{
linphone_core_iterate(mCore);
ms_usleep(20000);
if (i>100){
ms_message("tunnel: timeout for unregistration expired, giving up");
break;
}
i++;
}while(linphone_proxy_config_is_registered(lProxy));
ms_message("Unregistration %s", linphone_proxy_config_is_registered(lProxy)?"failed":"succeeded");
}else{
ms_message("No registration pending");
}
}
}
void TunnelManager::enable(bool isEnable) {
ms_message("Turning tunnel [%s]",(isEnable?"on":"off"));
if (isEnable && !mEnabled){
mEnabled=true;
//1 save transport and firewall policy
linphone_core_get_sip_transports(mCore, &mRegularTransport);
mPreviousFirewallPolicy=linphone_core_get_firewall_policy(mCore);
//2 unregister
/*Each time tunnel is enabled/disabled, we need to unregister previous session and re-register. Since tunnel initialization
is asynchronous, we temporary disable auto register while tunnel sets up, and reenable it when re-registering. */
void TunnelManager::setMode(LinphoneTunnelMode mode) {
if(mMode != mode) {
waitUnRegistration();
//3 insert tunnel
start();
}else if (!isEnable && mEnabled){
//1 unregister
waitUnRegistration();
mEnabled=false;
stopClient();
mReady=false;
linphone_core_set_rtp_transport_factories(mCore,NULL);
sal_disable_tunnel(mCore->sal);
// Set empty transports to force the setting of regular transport, otherwise it is not applied
LCSipTransports lTransport;
lTransport.udp_port = 0;
lTransport.tcp_port = 0;
lTransport.tls_port = 0;
lTransport.dtls_port = 0;
linphone_core_set_sip_transports(mCore, &lTransport);
//Restore transport and firewall policy
linphone_core_set_sip_transports(mCore, &mRegularTransport);
linphone_core_set_firewall_policy(mCore, mPreviousFirewallPolicy);
//register
LinphoneProxyConfig* lProxy;
linphone_core_get_default_proxy(mCore, &lProxy);
if (lProxy) {
linphone_proxy_config_edit(lProxy);
linphone_proxy_config_enable_register(lProxy,TRUE);
linphone_proxy_config_done(lProxy);
switch(mode) {
case LinphoneTunnelModeEnable:
mMode = mode;
startClient();
/* registration is done by proccessTunnelEvent() when the tunnel
the tunnel succeed to connect */
break;
case LinphoneTunnelModeDisable:
mMode = mode;
stopClient();
registration();
break;
case LinphoneTunnelModeAuto:
mMode = mode;
autoDetect();
/* Registration is not needed because processUdpMirrorEvent() will
call either connect() or disconnect(). Should disconnect() is called,
processUdpMirrorEvent() care to call registratin() */
break;
default:
ms_error("TunnelManager::setMode(): invalid mode (%d)", mode);
}
}
}
@ -320,30 +321,29 @@ void TunnelManager::enableLogs(bool isEnabled,LogHandler logHandler) {
SetLogLevel(TUNNEL_ERROR|TUNNEL_WARN);
}
}
bool TunnelManager::isEnabled() {
return mEnabled;
LinphoneTunnelMode TunnelManager::getMode() const {
return mMode;
}
void TunnelManager::processUdpMirrorEvent(const Event &ev){
if (ev.mData.mHaveUdp) {
LOGI("Tunnel is not required, disabling");
enable(false);
mAutoDetectStarted = false;
stopClient();
registration();
} else {
mCurrentUdpMirrorClient++;
if (mCurrentUdpMirrorClient !=mUdpMirrorClients.end()) {
// enable tunnel but also try backup server
LOGI("Tunnel is required, enabling; Trying backup udp mirror");
UdpMirrorClient &lUdpMirrorClient=*mCurrentUdpMirrorClient;
lUdpMirrorClient.start(TunnelManager::sUdpMirrorClientCallback,(void*)this);
} else {
LOGI("Tunnel is required, enabling; no backup udp mirror available");
mAutoDetectStarted = false;
startClient();
}
enable(true);
}
}
@ -361,21 +361,22 @@ void TunnelManager::sUdpMirrorClientCallback(bool isUdpAvailable, void* data) {
thiz->postEvent(ev);
}
void TunnelManager::networkReachableCb(LinphoneCore *lc, bool_t reachable) {
TunnelManager *tunnel = bcTunnel(linphone_core_get_tunnel(lc));
if(reachable && tunnel->getMode() == LinphoneTunnelModeAuto) {
tunnel->autoDetect();
}
}
void TunnelManager::autoDetect() {
// first check if udp mirrors was provisionned
if (mUdpMirrorClients.empty()) {
LOGE("No UDP mirror server configured aborting auto detection");
return;
}
if (mAutoDetectStarted) {
LOGE("auto detection already in progress, restarting");
(*mCurrentUdpMirrorClient).stop();
}
mAutoDetectStarted=true;
mCurrentUdpMirrorClient =mUdpMirrorClients.begin();
mCurrentUdpMirrorClient = mUdpMirrorClients.begin();
UdpMirrorClient &lUdpMirrorClient=*mCurrentUdpMirrorClient;
lUdpMirrorClient.start(TunnelManager::sUdpMirrorClientCallback,(void*)this);
}
void TunnelManager::setHttpProxyAuthInfo(const char* username,const char* passwd) {
@ -384,6 +385,22 @@ void TunnelManager::setHttpProxyAuthInfo(const char* username,const char* passwd
if (mTunnelClient) mTunnelClient->setHttpProxyAuthInfo(username,passwd);
}
void TunnelManager::tunnelizeSipPackets(bool enable){
if(enable != mTunnelizeSipPackets) {
mTunnelizeSipPackets = enable;
if(isConnected()) {
waitUnRegistration();
if(mTunnelizeSipPackets) sal_enable_tunnel(mCore->sal, mTunnelClient);
else sal_disable_tunnel(mCore->sal);
registration();
}
}
}
bool TunnelManager::tunnelizeSipPacketsEnabled() const {
return mTunnelizeSipPackets;
}
void TunnelManager::setHttpProxy(const char *host,int port, const char *username, const char *passwd){
mHttpUserName=username?username:"";
mHttpPasswd=passwd?passwd:"";
@ -392,6 +409,6 @@ void TunnelManager::setHttpProxy(const char *host,int port, const char *username
if (mTunnelClient) mTunnelClient->setHttpProxy(host, port, username, passwd);
}
LinphoneCore *TunnelManager::getLinphoneCore(){
LinphoneCore *TunnelManager::getLinphoneCore() const{
return mCore;
}

View file

@ -1,7 +1,7 @@
/*
* C Implementation: tunnel
*
* Description:
* Description:
*
*
*
@ -12,35 +12,35 @@
#define __TUNNEL_CLIENT_MANAGER_H__
#include <list>
#include <string>
#include "tunnel/client.hh"
#include <tunnel/client.hh>
#include <tunnel/udp_mirror.hh>
#include "linphonecore.h"
#include "linphone_tunnel.h"
#ifndef USE_BELLESIP
extern "C" {
#include "eXosip2/eXosip_transport_hook.h"
#include <eXosip2/eXosip_transport_hook.h>
}
#endif
namespace belledonnecomm {
class TunnelClient;
class UdpMirrorClient;
/**
* @addtogroup tunnel_client
* @addtogroup tunnel_client
* @{
**/
/**
* The TunnelManager class extends the LinphoneCore functionnality in order to provide an easy to use API to
* The TunnelManager class extends the LinphoneCore functionnality in order to provide an easy to use API to
* - provision tunnel servers ip addresses and ports
* - start/stop the tunneling service
* - be informed of of connection and disconnection events to the tunnel server
* - be informed of connection and disconnection events to the tunnel server
* - perform auto-detection whether tunneling is required, based on a test of sending/receiving a flow of UDP packets.
*
*
* It takes in charge automatically the SIP registration procedure when connecting or disconnecting to a tunnel server.
* No other action on LinphoneCore is required to enable full operation in tunnel mode.
**/
class TunnelManager : public TunnelClientController{
class TunnelManager {
public:
/**
* Add a tunnel server. At least one should be provided to be able to connect.
@ -61,20 +61,8 @@ class UdpMirrorClient;
void addServer(const char *ip, int port,unsigned int udpMirrorPort,unsigned int delay);
/**
* Removes all tunnel server address previously entered with addServer()
**/
void cleanServers();
/**
* Register a state callback to be notified whenever the tunnel client is connected or disconnected to the tunnel server.
* @param cb application callback function to use for notifying of connection/disconnection events.
* @param userdata An opaque pointer passed to the callback, used optionally by the application to retrieve a context.
**/
void setCallback(StateCallback cb, void *userdata);
/**
* Start connecting to a tunnel server.
* At this step, nothing is tunneled yet. The enable() method must be used to state whether SIP and RTP traffic
* need to be tunneled or not.
**/
void start();
void cleanServers();
/**
* Forces reconnection to the tunnel server.
* This method is useful when the device switches from wifi to Edge/3G or vice versa. In most cases the tunnel client socket
@ -83,22 +71,15 @@ class UdpMirrorClient;
**/
void reconnect();
/**
* Sets whether tunneling of SIP and RTP is required.
* @param isEnabled If true enter in tunneled mode, if false exits from tunneled mode.
* The TunnelManager takes care of refreshing SIP registration when switching on or off the tunneled mode.
*
**/
void enable(bool isEnabled);
/**
* In auto detect mode, the tunnel manager try to establish a real time rtp cummunication with the tunnel server on specified port.
*<br>In case of success, the tunnel is automatically turned off. Otherwise, if no udp commmunication is feasible, tunnel mode is turned on.
*<br> Call this method each time to run the auto detection algorithm
* @brief setMode
* @param mode
*/
void autoDetect();
void setMode(LinphoneTunnelMode mode);
/**
* Returns a boolean indicating whether tunneled operation is enabled.
**/
bool isEnabled();
* @brief Return the tunnel mode
* @return #LinphoneTunnelMode
*/
LinphoneTunnelMode getMode() const;
/**
* Enables debug logs of the Tunnel subsystem.
**/
@ -115,24 +96,52 @@ class UdpMirrorClient;
* @param passwd The password.
**/
void setHttpProxyAuthInfo(const char* username,const char* passwd);
~TunnelManager();
void setHttpProxy(const char *host,int port, const char *username, const char *passwd);
/**
* Indicate to the tunnel manager whether SIP packets must pass
* through the tunnel. That featurte is automatically enabled at
* the creation of the TunnelManager instance.
* @param enable If set to TRUE, SIP packets will pass through the tunnel.
* If set to FALSE, SIP packets will pass by the configured proxies.
*/
void tunnelizeSipPackets(bool enable);
/**
* @brief Check whether the tunnel manager is set to tunnelize SIP packets
* @return True, SIP packets pass through the tunnel
*/
bool tunnelizeSipPacketsEnabled() const;
/**
* @brief Constructor
* @param lc The LinphoneCore instance of which the TunnelManager will be associated to.
*/
TunnelManager(LinphoneCore* lc);
/**
* Destroy the given RtpTransport.
* @brief Destructor
*/
void closeRtpTransport(RtpTransport *t, TunnelSocket *s);
~TunnelManager();
/**
* Create an RtpTransport.
* @brief Create an RtpTransport
* @param port
* @return
*/
RtpTransport *createRtpTransport(int port);
/**
* Get associated Linphone Core.
* @brief Destroy the given RtpTransport
* @param t
* @param s
*/
LinphoneCore *getLinphoneCore();
virtual void setHttpProxy(const char *host,int port, const char *username, const char *passwd);
virtual bool isReady() const;
void closeRtpTransport(RtpTransport *t, TunnelSocket *s);
/**
* @brief Get associated Linphone Core
* @return pointer on the associated LinphoneCore
*/
LinphoneCore *getLinphoneCore() const;
/**
* @brief Check wehter the tunnel is connected
* @return True whether the tunnel is connected
*/
bool isConnected() const;
private:
enum EventType{
UdpMirrorClientEvent,
@ -146,8 +155,6 @@ class UdpMirrorClient;
}mData;
};
typedef std::list<UdpMirrorClient> UdpMirrorClientList;
virtual bool isStarted();
void onIterate();
static int customSendto(struct _RtpTransport *t, mblk_t *msg , int flags, const struct sockaddr *to, socklen_t tolen);
static int customRecvfrom(struct _RtpTransport *t, mblk_t *msg, int flags, struct sockaddr *from, socklen_t *fromlen);
static int eXosipSendto(int fd,const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen,void* userdata);
@ -156,35 +163,41 @@ class UdpMirrorClient;
static void tunnelCallback(bool connected, TunnelManager *zis);
static void sOnIterate(TunnelManager *zis);
static void sUdpMirrorClientCallback(bool result, void* data);
static void networkReachableCb(LinphoneCore *lc, bool_t reachable);
private:
void onIterate();
void registration();
void waitUnRegistration();
void processTunnelEvent(const Event &ev);
void processUdpMirrorEvent(const Event &ev);
void postEvent(const Event &ev);
void startClient();
void stopClient();
void autoDetect();
private:
LinphoneCore* mCore;
LCSipTransports mRegularTransport;
#ifndef USE_BELLESIP
TunnelSocket *mSipSocket;
eXosip_transport_hooks_t mExosipTransport;
#endif
StateCallback mCallback;
void * mCallbackData;
bool mEnabled;
LinphoneTunnelMode mMode;
std::queue<Event> mEvq;
std::list <ServerAddr> mServerAddrs;
UdpMirrorClientList mUdpMirrorClients;
UdpMirrorClientList::iterator mCurrentUdpMirrorClient;
TunnelClient* mTunnelClient;
void stopClient();
Mutex mMutex;
static Mutex sMutex;
bool mAutoDetectStarted;
bool mReady;
bool mIsConnected;
LinphoneRtpTransportFactories mTransportFactories;
std::string mHttpUserName;
std::string mHttpPasswd;
std::string mHttpProxyHost;
int mHttpProxyPort;
LinphoneFirewallPolicy mPreviousFirewallPolicy;
bool mPreviousRegistrationEnabled;
bool mTunnelizeSipPackets;
LinphoneCoreVTable *mVTable;
};
/**

View file

@ -184,6 +184,7 @@ bool_t linphone_address_weak_equal(const LinphoneAddress *a1, const LinphoneAddr
/**
* Destroys a LinphoneAddress object (actually calls linphone_address_unref()).
* @deprecated Use linphone_address_unref() instead
**/
void linphone_address_destroy(LinphoneAddress *u){
sal_address_unref(u);

View file

@ -21,7 +21,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "linphonecore.h"
#include "private.h"
#include "lpconfig.h"
@ -143,7 +143,7 @@ void linphone_auth_info_write_config(LpConfig *config, LinphoneAuthInfo *obj, in
char key[50];
sprintf(key,"auth_info_%i",pos);
lp_config_clean_section(config,key);
if (obj==NULL || lp_config_get_int(config, "sip", "store_auth_info", 1) == 0){
return;
}
@ -176,12 +176,12 @@ LinphoneAuthInfo *linphone_auth_info_new_from_config_file(LpConfig * config, int
char key[50];
const char *username,*userid,*passwd,*ha1,*realm,*domain;
LinphoneAuthInfo *ret;
sprintf(key,"auth_info_%i",pos);
if (!lp_config_has_section(config,key)){
return NULL;
}
username=lp_config_get_string(config,key,"username",NULL);
userid=lp_config_get_string(config,key,"userid",NULL);
passwd=lp_config_get_string(config,key,"passwd",NULL);
@ -221,7 +221,7 @@ static int realm_match(const char *realm1, const char *realm2){
static const LinphoneAuthInfo *find_auth_info(LinphoneCore *lc, const char *username, const char *realm, const char *domain){
MSList *elem;
const LinphoneAuthInfo *ret=NULL;
for (elem=lc->auth_info;elem!=NULL;elem=elem->next) {
LinphoneAuthInfo *pinfo = (LinphoneAuthInfo*)elem->data;
if (username && pinfo->username && strcmp(username,pinfo->username)==0) {
@ -240,7 +240,7 @@ static const LinphoneAuthInfo *find_auth_info(LinphoneCore *lc, const char *user
}
} else if (domain && pinfo->domain && strcmp(domain,pinfo->domain)==0) {
return pinfo;
} else if (!domain) {
} else if (!domain) {
return pinfo;
}
}
@ -249,7 +249,7 @@ static const LinphoneAuthInfo *find_auth_info(LinphoneCore *lc, const char *user
}
/**
* Find authentication info matching realm, username, domain criterias.
* Find authentication info matching realm, username, domain criteria.
* First of all, (realm,username) pair are searched. If multiple results (which should not happen because realm are supposed to be unique), then domain is added to the search.
* @param lc the LinphoneCore
* @param realm the authentication 'realm' (optional)
@ -264,7 +264,7 @@ const LinphoneAuthInfo *linphone_core_find_auth_info(LinphoneCore *lc, const cha
if (ai==NULL && domain){
ai=find_auth_info(lc,username,realm,domain);
}
}
}
if (ai == NULL && domain != NULL) {
ai=find_auth_info(lc,username,NULL,domain);
}
@ -292,8 +292,8 @@ LinphoneAuthInfo * linphone_core_create_auth_info(LinphoneCore *lc, const char *
/**
* Adds authentication information to the LinphoneCore.
*
* This information will be used during all SIP transacations that require authentication.
*
* This information will be used during all SIP transactions that require authentication.
**/
void linphone_core_add_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *info){
LinphoneAuthInfo *ai;
@ -301,7 +301,7 @@ void linphone_core_add_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *info)
MSList *l;
int restarted_op_count=0;
bool_t updating=FALSE;
if (info->ha1==NULL && info->passwd==NULL){
ms_error("linphone_core_add_auth_info(): info supplied with empty password or ha1.");
return;
@ -371,7 +371,6 @@ void linphone_core_remove_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *in
r=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,info->realm,info->username,info->domain);
if (r){
lc->auth_info=ms_list_remove(lc->auth_info,r);
/*printf("len=%i newlen=%i\n",len,newlen);*/
linphone_auth_info_destroy(r);
write_auth_infos(lc);
}
@ -379,6 +378,8 @@ void linphone_core_remove_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *in
/**
* Returns an unmodifiable list of currently entered LinphoneAuthInfo.
* @param[in] lc The LinphoneCore object
* @return \mslist{LinphoneAuthInfo}
**/
const MSList *linphone_core_get_auth_info_list(const LinphoneCore *lc){
return lc->auth_info;

View file

@ -98,12 +98,16 @@ void sal_disable_logs() {
void sal_add_pending_auth(Sal *sal, SalOp *op){
if (ms_list_find(sal->pending_auths,op)==NULL){
sal->pending_auths=ms_list_append(sal->pending_auths,op);
op->has_auth_pending=TRUE;
}
}
void sal_remove_pending_auth(Sal *sal, SalOp *op){
if (ms_list_find(sal->pending_auths,op)){
sal->pending_auths=ms_list_remove(sal->pending_auths,op);
if (op->has_auth_pending){
op->has_auth_pending=FALSE;
if (ms_list_find(sal->pending_auths,op)){
sal->pending_auths=ms_list_remove(sal->pending_auths,op);
}
}
}
@ -137,7 +141,7 @@ void sal_process_authentication(SalOp *op) {
return;
}
if (belle_sip_provider_add_authorization(op->base.root->prov,new_request,response,from_uri,&auth_list)) {
if (belle_sip_provider_add_authorization(op->base.root->prov,new_request,response,from_uri,&auth_list,op->base.realm)) {
if (is_within_dialog) {
sal_op_send_request(op,new_request);
} else {
@ -432,8 +436,8 @@ Sal * sal_init(){
sal->stack = belle_sip_stack_new(NULL);
sal->user_agent=belle_sip_header_user_agent_new();
#if defined(PACKAGE_NAME) && defined(LINPHONE_VERSION)
belle_sip_header_user_agent_add_product(sal->user_agent, PACKAGE_NAME "/" LINPHONE_VERSION);
#if defined(PACKAGE_NAME) && defined(LIBLINPHONE_VERSION)
belle_sip_header_user_agent_add_product(sal->user_agent, PACKAGE_NAME "/" LIBLINPHONE_VERSION);
#endif
sal_append_stack_string_to_user_agent(sal);
belle_sip_object_ref(sal->user_agent);
@ -530,6 +534,8 @@ void sal_uninit(Sal* sal){
belle_sip_object_unref(sal->prov);
belle_sip_object_unref(sal->stack);
belle_sip_object_unref(sal->listener);
if (sal->supported) belle_sip_object_unref(sal->supported);
ms_list_free_with_data(sal->supported_tags,ms_free);
if (sal->uuid) ms_free(sal->uuid);
if (sal->root_ca) ms_free(sal->root_ca);
ms_free(sal);
@ -555,7 +561,7 @@ int sal_add_listen_port(Sal *ctx, SalAddress* addr){
sal_address_get_port(addr),
sal_transport_to_string(sal_address_get_transport(addr)));
if (sal_address_get_port(addr)==-1 && lp==NULL){
int random_port=(0xDFFF&random())+1024;
int random_port=(0xDFFF&ortp_random())+1024;
ms_warning("This version of belle-sip doesn't support random port, choosing one here.");
lp = belle_sip_stack_create_listening_point(ctx->stack,
sal_address_get_domain(addr),
@ -639,28 +645,42 @@ void sal_set_keepalive_period(Sal *ctx,unsigned int value){
belle_sip_listening_point_set_keep_alive(lp,ctx->keep_alive);
}
}
return ;
}
int sal_enable_tunnel(Sal *ctx, void *tunnelclient) {
#ifdef TUNNEL_ENABLED
belle_sip_listening_point_t *lp;
int result;
sal_unlisten_ports(ctx);
lp = belle_sip_tunnel_listening_point_new(ctx->stack, tunnelclient);
if (lp == NULL) return -1;
belle_sip_listening_point_set_keep_alive(lp, ctx->keep_alive);
result = belle_sip_provider_add_listening_point(ctx->prov, lp);
set_tls_properties(ctx);
return result;
belle_sip_listening_point_t *lp_udp = NULL;
if(ctx->lp_tunnel != NULL) {
ortp_error("sal_enable_tunnel(): tunnel is already enabled");
return -1;
}
while((lp_udp = belle_sip_provider_get_listening_point(ctx->prov, "udp")) != NULL) {
belle_sip_object_ref(lp_udp);
belle_sip_provider_remove_listening_point(ctx->prov, lp_udp);
ctx->udp_listening_points = ms_list_append(ctx->udp_listening_points, lp_udp);
}
ctx->lp_tunnel = belle_sip_tunnel_listening_point_new(ctx->stack, tunnelclient);
if(ctx->lp_tunnel == NULL) return -1;
belle_sip_listening_point_set_keep_alive(ctx->lp_tunnel, ctx->keep_alive);
belle_sip_provider_add_listening_point(ctx->prov, ctx->lp_tunnel);
belle_sip_object_ref(ctx->lp_tunnel);
return 0;
#else
return 0;
#endif
}
void sal_disable_tunnel(Sal *ctx) {
#ifdef TUNNEL_ENABLED
sal_unlisten_ports(ctx);
MSList *it;
if(ctx->lp_tunnel) {
belle_sip_provider_remove_listening_point(ctx->prov, ctx->lp_tunnel);
belle_sip_object_unref(ctx->lp_tunnel);
ctx->lp_tunnel = NULL;
for(it=ctx->udp_listening_points; it!=NULL; it=it->next) {
belle_sip_provider_add_listening_point(ctx->prov, (belle_sip_listening_point_t *)it->data);
}
ms_list_free_with_data(ctx->udp_listening_points, belle_sip_object_unref);
ctx->udp_listening_points = NULL;
}
#endif
}
/**
@ -928,10 +948,79 @@ int sal_create_uuid(Sal*ctx, char *uuid, size_t len){
return 0;
}
static void make_supported_header(Sal *sal){
MSList *it;
char *alltags=NULL;
size_t buflen=64;
size_t written=0;
if (sal->supported){
belle_sip_object_unref(sal->supported);
sal->supported=NULL;
}
for(it=sal->supported_tags;it!=NULL;it=it->next){
const char *tag=(const char*)it->data;
size_t taglen=strlen(tag);
if (alltags==NULL || (written+taglen+1>=buflen)) alltags=ms_realloc(alltags,(buflen=buflen*2));
snprintf(alltags+written,buflen-written,it->next ? "%s, " : "%s",tag);
}
if (alltags){
sal->supported=belle_sip_header_create("Supported",alltags);
if (sal->supported){
belle_sip_object_ref(sal->supported);
}
ms_free(alltags);
}
}
void sal_set_supported_tags(Sal *ctx, const char* tags){
ctx->supported_tags=ms_list_free_with_data(ctx->supported_tags,ms_free);
if (tags){
char *iter;
char *buffer=ms_strdup(tags);
char *tag;
char *context=NULL;
iter=buffer;
while((tag=strtok_r(iter,", ",&context))!=NULL){
iter=NULL;
ctx->supported_tags=ms_list_append(ctx->supported_tags,ms_strdup(tag));
}
ms_free(buffer);
}
make_supported_header(ctx);
}
const char *sal_get_supported_tags(Sal *ctx){
if (ctx->supported){
return belle_sip_header_get_unparsed_value(ctx->supported);
}
return NULL;
}
void sal_add_supported_tag(Sal *ctx, const char* tag){
MSList *elem=ms_list_find_custom(ctx->supported_tags,(MSCompareFunc)strcasecmp,tag);
if (!elem){
ctx->supported_tags=ms_list_append(ctx->supported_tags,ms_strdup(tag));
make_supported_header(ctx);
}
}
void sal_remove_supported_tag(Sal *ctx, const char* tag){
MSList *elem=ms_list_find_custom(ctx->supported_tags,(MSCompareFunc)strcasecmp,tag);
if (elem){
ms_free(elem->data);
ctx->supported_tags=ms_list_remove_link(ctx->supported_tags,elem);
make_supported_header(ctx);
}
}
belle_sip_response_t* sal_create_response_from_request ( Sal* sal, belle_sip_request_t* req, int code ) {
belle_sip_response_t *resp=belle_sip_response_create_from_request(req,code);
belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp),BELLE_SIP_HEADER(sal->user_agent));
belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp),sal_make_supported_header(sal));
belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp),sal->supported);
return resp;
}

View file

@ -33,12 +33,16 @@ struct Sal{
belle_sip_provider_t *prov;
belle_sip_header_user_agent_t* user_agent;
belle_sip_listener_t *listener;
belle_sip_listening_point_t *lp_tunnel;
MSList *udp_listening_points;
void *up; /*user pointer*/
int session_expires;
unsigned int keep_alive;
char *root_ca;
char *uuid;
int refresher_retry_after; /*retry after value for refresher*/
MSList *supported_tags;/*list of char * */
belle_sip_header_t *supported;
bool_t one_matching_codec;
bool_t use_tcp_tls_keep_alive;
bool_t nat_helper_enabled;
@ -102,6 +106,7 @@ struct SalOp{
bool_t sdp_offering;
bool_t call_released;
bool_t manual_refresher;
bool_t has_auth_pending;
int auth_requests; /*number of auth requested for this op*/
};
@ -164,8 +169,6 @@ bool_t sal_op_get_body(SalOp *op, belle_sip_message_t *msg, SalBody *salbody);
SalReason sal_reason_to_sip_code(SalReason r);
belle_sip_header_t * sal_make_supported_header(Sal *sal);
void _sal_op_add_custom_headers(SalOp *op, belle_sip_message_t *msg);
#endif /* SAL_IMPL_H_ */

View file

@ -185,6 +185,7 @@ static void call_process_response(void *op_base, const belle_sip_response_event_
int code = belle_sip_response_get_status_code(response);
belle_sip_header_content_type_t *header_content_type=NULL;
belle_sip_dialog_t *dialog=belle_sip_response_event_get_dialog(event);
const char *method;
if (!client_transaction) {
ms_warning("Discarding stateless response [%i] on op [%p]",code,op);
@ -193,13 +194,13 @@ static void call_process_response(void *op_base, const belle_sip_response_event_
req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction));
set_or_update_dialog(op,dialog);
dialog_state=dialog ? belle_sip_dialog_get_state(dialog) : BELLE_SIP_DIALOG_NULL;
method=belle_sip_request_get_method(req);
ms_message("Op [%p] receiving call response [%i], dialog is [%p] in state [%s]",op,code,dialog,belle_sip_dialog_state_to_string(dialog_state));
switch(dialog_state) {
case BELLE_SIP_DIALOG_NULL:
case BELLE_SIP_DIALOG_EARLY: {
if (strcmp("INVITE",belle_sip_request_get_method(req))==0 ) {
if (strcmp("INVITE",method)==0 ) {
if (op->state == SalOpStateTerminating) {
/*check if CANCEL was sent before*/
if (strcmp("CANCEL",belle_sip_request_get_method(belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_client_trans))))!=0) {
@ -238,28 +239,28 @@ static void call_process_response(void *op_base, const belle_sip_response_event_
case BELLE_SIP_DIALOG_CONFIRMED: {
switch (op->state) {
case SalOpStateEarly:/*invite case*/
case SalOpStateActive: /*re-invite case*/
if (code >=200
&& code<300
&& strcmp("INVITE",belle_sip_request_get_method(req))==0) {
handle_sdp_from_response(op,response);
ack=belle_sip_dialog_create_ack(op->dialog,belle_sip_dialog_get_local_seq_number(op->dialog));
if (ack==NULL) {
ms_error("This call has been already terminated.");
return ;
case SalOpStateActive: /*re-invite, INFO, UPDATE case*/
if (strcmp("INVITE",method)==0){
if (code >=200 && code<300) {
handle_sdp_from_response(op,response);
ack=belle_sip_dialog_create_ack(op->dialog,belle_sip_dialog_get_local_seq_number(op->dialog));
if (ack==NULL) {
ms_error("This call has been already terminated.");
return ;
}
if (op->sdp_answer){
set_sdp(BELLE_SIP_MESSAGE(ack),op->sdp_answer);
belle_sip_object_unref(op->sdp_answer);
op->sdp_answer=NULL;
}
belle_sip_dialog_send_ack(op->dialog,ack);
op->base.root->callbacks.call_accepted(op); /*INVITE*/
op->state=SalOpStateActive;
}else if (code >= 300){
call_set_error(op,response);
}
if (op->sdp_answer){
set_sdp(BELLE_SIP_MESSAGE(ack),op->sdp_answer);
belle_sip_object_unref(op->sdp_answer);
op->sdp_answer=NULL;
}
belle_sip_dialog_send_ack(op->dialog,ack);
op->base.root->callbacks.call_accepted(op); /*INVITE*/
op->state=SalOpStateActive;
} else if (code >= 300 && strcmp("INVITE",belle_sip_request_get_method(req))==0){
call_set_error(op,response);
} else if (code == 491
&& strcmp("INFO",belle_sip_request_get_method(req)) == 0
}else if (strcmp("INFO",method)==0){
if (code == 491
&& (header_content_type = belle_sip_message_get_header_by_type(req,belle_sip_header_content_type_t))
&& strcmp("application",belle_sip_header_content_type_get_type(header_content_type))==0
&& strcmp("media_control+xml",belle_sip_header_content_type_get_subtype(header_content_type))==0) {
@ -267,8 +268,11 @@ static void call_process_response(void *op_base, const belle_sip_response_event_
belle_sip_source_t *s=sal_create_timer(op->base.root,vfu_retry,sal_op_ref(op), retry_in, "vfu request retry");
ms_message("Rejected vfu request on op [%p], just retry in [%ui] ms",op,retry_in);
belle_sip_object_unref(s);
}else {
/*ignoring*/
}else {
/*ignoring*/
}
}else if (strcmp("UPDATE",method)==0){
op->base.root->callbacks.call_accepted(op); /*INVITE*/
}
break;
case SalOpStateTerminating:
@ -419,6 +423,7 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t
belle_sip_response_t* resp;
belle_sip_header_t* call_info;
const char *method=belle_sip_request_get_method(req);
bool_t is_update=FALSE;
if (strcmp("ACK",method)!=0){ /*ACK does'nt create srv transaction*/
server_transaction = belle_sip_provider_create_server_transaction(op->base.root->prov,belle_sip_request_event_get_request(event));
@ -490,7 +495,7 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t
} else if (strcmp("UPDATE",method)==0) {
sal_op_reset_descriptions(op);
if (process_sdp_for_invite(op,req)==0)
op->base.root->callbacks.call_updating(op);
op->base.root->callbacks.call_updating(op,TRUE);
} else {
belle_sip_error("Unexpected method [%s] for dialog state BELLE_SIP_DIALOG_EARLY",belle_sip_request_get_method(req));
unsupported_method(server_transaction,req);
@ -522,11 +527,20 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t
op->base.root->callbacks.call_terminated(op,op->dir==SalOpDirIncoming?sal_op_get_from(op):sal_op_get_to(op));
op->state=SalOpStateTerminating;
/*call end not notified by dialog deletion because transaction can end before dialog*/
} else if(strcmp("INVITE",method)==0) {
/*re-invite*/
sal_op_reset_descriptions(op);
if (process_sdp_for_invite(op,req)==0)
op->base.root->callbacks.call_updating(op);
} else if(strcmp("INVITE",method)==0 || (is_update=(strcmp("UPDATE",method)==0)) ) {
if (is_update && !belle_sip_message_get_body(BELLE_SIP_MESSAGE(req))) {
/*session timer case*/
/*session expire should be handled. to be done when real session timer (rfc4028) will be implemented*/
resp=sal_op_create_response_from_request(op,req,200);
belle_sip_server_transaction_send_response(server_transaction,resp);
belle_sip_object_unref(op->pending_update_server_trans);
op->pending_update_server_trans=NULL;
} else {
/*re-invite*/
sal_op_reset_descriptions(op);
if (process_sdp_for_invite(op,req)==0)
op->base.root->callbacks.call_updating(op,is_update);
}
} else if (strcmp("INFO",method)==0){
if (belle_sip_message_get_body(BELLE_SIP_MESSAGE(req))
&& strstr(belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)),"picture_fast_update")) {
@ -564,22 +578,6 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t
belle_sip_server_transaction_send_response(server_transaction,sal_op_create_response_from_request(op,req,481));
} else if (strcmp("MESSAGE",method)==0){
sal_process_incoming_message(op,event);
} else if (strcmp("UPDATE",method)==0) {
/*FIXME jehan: It might be better to silently accept UPDATE which do not modify either the number or the nature of streams*/
/*rfc 3311
* 5.2 Receiving an UPDATE
* ...
* If the UAS cannot change the session parameters without prompting the user, it SHOULD reject
* the request with a 504 response.
*/
resp=sal_op_create_response_from_request(op,req,504);
belle_sip_response_set_reason_phrase(resp,"Cannot change the session parameters without prompting the user");
/*belle_sip_message_add_header( BELLE_SIP_MESSAGE(resp)
,belle_sip_header_create( "Warning", "Cannot change the session parameters without prompting the user"));*/
belle_sip_server_transaction_send_response(server_transaction,resp);
return;
}else{
ms_error("unexpected method [%s] for dialog [%p]",belle_sip_request_get_method(req),op->dialog);
unsupported_method(server_transaction,req);
@ -796,13 +794,15 @@ int sal_call_decline(SalOp *op, SalReason reason, const char *redirection /*opti
return 0;
}
int sal_call_update(SalOp *op, const char *subject){
int sal_call_update(SalOp *op, const char *subject, bool_t no_user_consent){
belle_sip_request_t *update;
belle_sip_dialog_state_t state=belle_sip_dialog_get_state(op->dialog);
/*check for dialog state*/
if ( state == BELLE_SIP_DIALOG_CONFIRMED) {
update=belle_sip_dialog_create_request(op->dialog,"INVITE");
if (no_user_consent)
update=belle_sip_dialog_create_request(op->dialog,"UPDATE");
else
update=belle_sip_dialog_create_request(op->dialog,"INVITE");
} else if (state == BELLE_SIP_DIALOG_EARLY) {
update=belle_sip_dialog_create_request(op->dialog,"UPDATE");
} else {

View file

@ -118,9 +118,7 @@ belle_sip_header_contact_t* sal_op_create_contact(SalOp *op){
return contact_header;
}
belle_sip_header_t * sal_make_supported_header(Sal *sal){
return belle_sip_header_create("Supported","replaces, outbound");
}
static void add_initial_route_set(belle_sip_request_t *request, const MSList *list){
const MSList *elem;
@ -137,7 +135,7 @@ static void add_initial_route_set(belle_sip_request_t *request, const MSList *li
continue;
}
}
route=belle_sip_header_route_create((belle_sip_header_address_t*)addr);
uri=belle_sip_header_address_get_uri((belle_sip_header_address_t*)route);
belle_sip_uri_set_lr_param(uri,1);
@ -180,11 +178,11 @@ belle_sip_request_t* sal_op_build_request(SalOp *op,const char* method) {
belle_sip_header_p_preferred_identity_t* p_preferred_identity=belle_sip_header_p_preferred_identity_create(BELLE_SIP_HEADER_ADDRESS(sal_op_get_from_address(op)));
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(p_preferred_identity));
}
if (elem && strcmp(method,"REGISTER")!=0 && !op->base.root->no_initial_route){
add_initial_route_set(req,elem);
}
if (strcmp("REGISTER",method)!=0 && op->privacy!=SalPrivacyNone ){
belle_sip_header_privacy_t* privacy_header=belle_sip_header_privacy_new();
if (op->privacy&SalPrivacyCritical)
@ -201,7 +199,7 @@ belle_sip_request_t* sal_op_build_request(SalOp *op,const char* method) {
belle_sip_header_privacy_add_privacy(privacy_header,sal_privacy_to_string(SalPrivacyUser));
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(privacy_header));
}
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),sal_make_supported_header(op->base.root));
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),op->base.root->supported);
return req;
}
@ -332,7 +330,7 @@ static int _sal_op_send_request_with_contact(SalOp* op, belle_sip_request_t* req
if (!belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_AUTHORIZATION)
&& !belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_PROXY_AUTHORIZATION)) {
/*hmm just in case we already have authentication param in cache*/
belle_sip_provider_add_authorization(op->base.root->prov,request,NULL,NULL,NULL);
belle_sip_provider_add_authorization(op->base.root->prov,request,NULL,NULL,NULL,op->base.realm);
}
result = belle_sip_client_transaction_send_request_to(client_transaction,next_hop_uri/*might be null*/);
@ -608,7 +606,7 @@ int sal_op_send_and_create_refresher(SalOp* op,belle_sip_request_t* req, int exp
belle_sip_object_unref(op->refresher);
}
if ((op->refresher = belle_sip_client_transaction_create_refresher(op->pending_client_trans))) {
/*since refresher acquires the transaction, we should remove our context from the transaction, because we won't be notified
/*since refresher acquires the transaction, we should remove our context from the transaction, because we won't be notified
* that it is terminated anymore.*/
sal_op_unref(op);/*loose the reference that was given to the transaction when creating it*/
/* Note that the refresher will replace our data with belle_sip_transaction_set_application_data().
@ -617,6 +615,7 @@ int sal_op_send_and_create_refresher(SalOp* op,belle_sip_request_t* req, int exp
notify the user as a normal transaction*/
belle_sip_refresher_set_listener(op->refresher,listener,op);
belle_sip_refresher_set_retry_after(op->refresher,op->base.root->refresher_retry_after);
belle_sip_refresher_set_realm(op->refresher,op->base.realm);
belle_sip_refresher_enable_manual_mode(op->refresher,op->manual_refresher);
return 0;
} else {

View file

@ -35,7 +35,7 @@ void sal_add_presence_info(SalOp *op, belle_sip_message_t *notify, SalPresenceMo
belle_sip_message_remove_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_CONTENT_TYPE);
belle_sip_message_remove_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_CONTENT_LENGTH);
belle_sip_message_set_body(BELLE_SIP_MESSAGE(notify),NULL,0);
if (content){
belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify)
,BELLE_SIP_HEADER(belle_sip_header_content_type_create("application","pidf+xml")));
@ -95,7 +95,7 @@ static void presence_response_event(void *op_base, const belle_sip_response_even
belle_sip_request_t* request=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction));
int code = belle_sip_response_get_status_code(response);
belle_sip_header_expires_t* expires;
sal_op_set_error_info_from_response(op,response);
if (code>=300) {
@ -127,6 +127,7 @@ static void presence_response_event(void *op_base, const belle_sip_response_even
if (expires>0){
op->refresher=belle_sip_client_transaction_create_refresher(client_transaction);
belle_sip_refresher_set_listener(op->refresher,presence_refresher_listener,op);
belle_sip_refresher_set_realm(op->refresher,op->base.realm);
}
}
break;
@ -164,7 +165,7 @@ static SalPresenceModel * process_presence_notification(SalOp *op, belle_sip_req
return NULL;
if (belle_sip_header_content_length_get_content_length(content_length) == 0)
return NULL;
if (body==NULL) return NULL;
op->base.root->callbacks.parse_presence_requested(op,
@ -181,7 +182,7 @@ static void handle_notify(SalOp *op, belle_sip_request_t *req){
belle_sip_server_transaction_t* server_transaction=op->pending_server_trans;
belle_sip_header_subscription_state_t* subscription_state_header=belle_sip_message_get_header_by_type(req,belle_sip_header_subscription_state_t);
SalSubscribeStatus sub_state;
if (strcmp("NOTIFY",belle_sip_request_get_method(req))==0) {
SalPresenceModel *presence_model = NULL;
const char* body = belle_sip_message_get_body(BELLE_SIP_MESSAGE(req));
@ -194,7 +195,7 @@ static void handle_notify(SalOp *op, belle_sip_request_t *req){
presence_model = process_presence_notification(op, req);
if (presence_model != NULL || body==NULL) {
/* Presence notification body parsed successfully. */
resp = sal_op_create_response_from_request(op, req, 200); /*create first because the op may be destroyed by notify_presence */
op->base.root->callbacks.notify_presence(op, sub_state, presence_model, NULL);
} else if (body){
@ -214,7 +215,7 @@ static void presence_process_request_event(void *op_base, const belle_sip_reques
belle_sip_header_expires_t* expires = belle_sip_message_get_header_by_type(req,belle_sip_header_expires_t);
belle_sip_response_t* resp;
const char *method=belle_sip_request_get_method(req);
belle_sip_object_ref(server_transaction);
if (op->pending_server_trans) belle_sip_object_unref(op->pending_server_trans);
op->pending_server_trans=server_transaction;
@ -256,7 +257,7 @@ static void presence_process_request_event(void *op_base, const belle_sip_reques
}
}
break;
default:
default:
ms_error("unexpected dialog state [%s]",belle_sip_dialog_state_to_string(dialog_state));
break;
}

299
coreapi/call_log.c Normal file
View file

@ -0,0 +1,299 @@
/*
linphone
Copyright (C) 2010-2014 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.
*/
#define _XOPEN_SOURCE 700 /*required for strptime of GNU libc*/
#include <time.h>
#include "private.h"
/*******************************************************************************
* Internal functions *
******************************************************************************/
/*prevent a gcc bug with %c*/
static size_t my_strftime(char *s, size_t max, const char *fmt, const struct tm *tm){
return strftime(s, max, fmt, tm);
}
static time_t string_to_time(const char *date){
#ifndef WIN32
struct tm tmtime={0};
strptime(date,"%c",&tmtime);
return mktime(&tmtime);
#else
return 0;
#endif
}
static void set_call_log_date(LinphoneCallLog *cl, time_t start_time){
struct tm loctime;
#ifdef WIN32
#if !defined(_WIN32_WCE)
loctime=*localtime(&start_time);
/*FIXME*/
#endif /*_WIN32_WCE*/
#else
localtime_r(&start_time,&loctime);
#endif
my_strftime(cl->start_date,sizeof(cl->start_date),"%c",&loctime);
}
/*******************************************************************************
* Private functions *
******************************************************************************/
void call_logs_write_to_config_file(LinphoneCore *lc){
MSList *elem;
char logsection[32];
int i;
char *tmp;
LpConfig *cfg=lc->config;
if (linphone_core_get_global_state (lc)==LinphoneGlobalStartup) return;
for(i=0,elem=lc->call_logs;elem!=NULL;elem=elem->next,++i){
LinphoneCallLog *cl=(LinphoneCallLog*)elem->data;
snprintf(logsection,sizeof(logsection),"call_log_%i",i);
lp_config_clean_section(cfg,logsection);
lp_config_set_int(cfg,logsection,"dir",cl->dir);
lp_config_set_int(cfg,logsection,"status",cl->status);
tmp=linphone_address_as_string(cl->from);
lp_config_set_string(cfg,logsection,"from",tmp);
ms_free(tmp);
tmp=linphone_address_as_string(cl->to);
lp_config_set_string(cfg,logsection,"to",tmp);
ms_free(tmp);
if (cl->start_date_time)
lp_config_set_int64(cfg,logsection,"start_date_time",(int64_t)cl->start_date_time);
else lp_config_set_string(cfg,logsection,"start_date",cl->start_date);
lp_config_set_int(cfg,logsection,"duration",cl->duration);
if (cl->refkey) lp_config_set_string(cfg,logsection,"refkey",cl->refkey);
lp_config_set_float(cfg,logsection,"quality",cl->quality);
lp_config_set_int(cfg,logsection,"video_enabled", cl->video_enabled);
lp_config_set_string(cfg,logsection,"call_id",cl->call_id);
}
for(;i<lc->max_call_logs;++i){
snprintf(logsection,sizeof(logsection),"call_log_%i",i);
lp_config_clean_section(cfg,logsection);
}
}
void call_logs_read_from_config_file(LinphoneCore *lc){
char logsection[32];
int i;
const char *tmp;
uint64_t sec;
LpConfig *cfg=lc->config;
for(i=0;;++i){
snprintf(logsection,sizeof(logsection),"call_log_%i",i);
if (lp_config_has_section(cfg,logsection)){
LinphoneCallLog *cl;
LinphoneAddress *from=NULL,*to=NULL;
tmp=lp_config_get_string(cfg,logsection,"from",NULL);
if (tmp) from=linphone_address_new(tmp);
tmp=lp_config_get_string(cfg,logsection,"to",NULL);
if (tmp) to=linphone_address_new(tmp);
if (!from || !to)
continue;
cl=linphone_call_log_new(lp_config_get_int(cfg,logsection,"dir",0),from,to);
cl->status=lp_config_get_int(cfg,logsection,"status",0);
sec=lp_config_get_int64(cfg,logsection,"start_date_time",0);
if (sec) {
/*new call log format with date expressed in seconds */
cl->start_date_time=(time_t)sec;
set_call_log_date(cl,cl->start_date_time);
}else{
tmp=lp_config_get_string(cfg,logsection,"start_date",NULL);
if (tmp) {
strncpy(cl->start_date,tmp,sizeof(cl->start_date));
cl->start_date_time=string_to_time(cl->start_date);
}
}
cl->duration=lp_config_get_int(cfg,logsection,"duration",0);
tmp=lp_config_get_string(cfg,logsection,"refkey",NULL);
if (tmp) cl->refkey=ms_strdup(tmp);
cl->quality=lp_config_get_float(cfg,logsection,"quality",-1);
cl->video_enabled=lp_config_get_int(cfg,logsection,"video_enabled",0);
tmp=lp_config_get_string(cfg,logsection,"call_id",NULL);
if (tmp) cl->call_id=ms_strdup(tmp);
lc->call_logs=ms_list_append(lc->call_logs,cl);
}else break;
}
}
/*******************************************************************************
* Public functions *
******************************************************************************/
const char *linphone_call_log_get_call_id(const LinphoneCallLog *cl){
return cl->call_id;
}
LinphoneCallDir linphone_call_log_get_dir(LinphoneCallLog *cl){
return cl->dir;
}
int linphone_call_log_get_duration(LinphoneCallLog *cl){
return cl->duration;
}
LinphoneAddress *linphone_call_log_get_from_address(LinphoneCallLog *cl){
return cl->from;
}
const rtp_stats_t *linphone_call_log_get_local_stats(const LinphoneCallLog *cl){
return &cl->local_stats;
}
float linphone_call_log_get_quality(LinphoneCallLog *cl){
return cl->quality;
}
const char *linphone_call_log_get_ref_key(const LinphoneCallLog *cl){
return cl->refkey;
}
LinphoneAddress *linphone_call_log_get_remote_address(LinphoneCallLog *cl){
return (cl->dir == LinphoneCallIncoming) ? cl->from : cl->to;
}
const rtp_stats_t *linphone_call_log_get_remote_stats(const LinphoneCallLog *cl){
return &cl->remote_stats;
}
time_t linphone_call_log_get_start_date(LinphoneCallLog *cl){
return cl->start_date_time;
}
LinphoneCallStatus linphone_call_log_get_status(LinphoneCallLog *cl){
return cl->status;
}
LinphoneAddress *linphone_call_log_get_to_address(LinphoneCallLog *cl){
return cl->to;
}
void linphone_call_log_set_ref_key(LinphoneCallLog *cl, const char *refkey){
if (cl->refkey!=NULL){
ms_free(cl->refkey);
cl->refkey=NULL;
}
if (refkey) cl->refkey=ms_strdup(refkey);
}
char * linphone_call_log_to_str(LinphoneCallLog *cl){
char *status;
char *tmp;
char *from=linphone_address_as_string (cl->from);
char *to=linphone_address_as_string (cl->to);
switch(cl->status){
case LinphoneCallAborted:
status=_("aborted");
break;
case LinphoneCallSuccess:
status=_("completed");
break;
case LinphoneCallMissed:
status=_("missed");
break;
default:
status="unknown";
}
tmp=ortp_strdup_printf(_("%s at %s\nFrom: %s\nTo: %s\nStatus: %s\nDuration: %i mn %i sec\n"),
(cl->dir==LinphoneCallIncoming) ? _("Incoming call") : _("Outgoing call"),
cl->start_date,
from,
to,
status,
cl->duration/60,
cl->duration%60);
ms_free(from);
ms_free(to);
return tmp;
}
bool_t linphone_call_log_video_enabled(LinphoneCallLog *cl) {
return cl->video_enabled;
}
/*******************************************************************************
* Reference and user data handling functions *
******************************************************************************/
void *linphone_call_log_get_user_data(const LinphoneCallLog *cl) {
return cl->user_data;
}
void linphone_call_log_set_user_data(LinphoneCallLog *cl, void *ud) {
cl->user_data = ud;
}
LinphoneCallLog * linphone_call_log_ref(LinphoneCallLog *cl) {
belle_sip_object_ref(cl);
return cl;
}
void linphone_call_log_unref(LinphoneCallLog *cl) {
belle_sip_object_unref(cl);
}
/*******************************************************************************
* Constructor and destructor functions *
******************************************************************************/
static void _linphone_call_log_destroy(LinphoneCallLog *cl){
if (cl->from!=NULL) linphone_address_destroy(cl->from);
if (cl->to!=NULL) linphone_address_destroy(cl->to);
if (cl->refkey!=NULL) ms_free(cl->refkey);
if (cl->call_id) ms_free(cl->call_id);
if (cl->reporting.reports[LINPHONE_CALL_STATS_AUDIO]!=NULL) linphone_reporting_destroy(cl->reporting.reports[LINPHONE_CALL_STATS_AUDIO]);
if (cl->reporting.reports[LINPHONE_CALL_STATS_VIDEO]!=NULL) linphone_reporting_destroy(cl->reporting.reports[LINPHONE_CALL_STATS_VIDEO]);
}
LinphoneCallLog * linphone_call_log_new(LinphoneCallDir dir, LinphoneAddress *from, LinphoneAddress *to){
LinphoneCallLog *cl=belle_sip_object_new(LinphoneCallLog);
cl->dir=dir;
cl->start_date_time=time(NULL);
set_call_log_date(cl,cl->start_date_time);
cl->from=from;
cl->to=to;
cl->status=LinphoneCallAborted; /*default status*/
cl->quality=-1;
cl->reporting.reports[LINPHONE_CALL_STATS_AUDIO]=linphone_reporting_new();
cl->reporting.reports[LINPHONE_CALL_STATS_VIDEO]=linphone_reporting_new();
return cl;
}
/* DEPRECATED */
void linphone_call_log_destroy(LinphoneCallLog *cl) {
belle_sip_object_unref(cl);
}
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneCallLog);
BELLE_SIP_INSTANCIATE_VPTR(LinphoneCallLog, belle_sip_object_t,
(belle_sip_object_destroy_t)_linphone_call_log_destroy,
NULL, // clone
NULL, // marshal
FALSE
);

244
coreapi/call_log.h Normal file
View file

@ -0,0 +1,244 @@
/*
linphone
Copyright (C) 2010-2014 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_CALL_LOG_H__
#define __LINPHONE_CALL_LOG_H__
/**
* @addtogroup call_logs
* @{
**/
/*******************************************************************************
* Structures and enums *
******************************************************************************/
/**
* Enum representing the direction of a call.
**/
enum _LinphoneCallDir {
LinphoneCallOutgoing, /**< outgoing calls*/
LinphoneCallIncoming /**< incoming calls*/
};
/**
* Typedef for enum
**/
typedef enum _LinphoneCallDir LinphoneCallDir;
/**
* Enum representing the status of a call
**/
typedef enum _LinphoneCallStatus {
LinphoneCallSuccess, /**< The call was sucessful */
LinphoneCallAborted, /**< The call was aborted */
LinphoneCallMissed, /**< The call was missed (unanswered) */
LinphoneCallDeclined /**< The call was declined, either locally or by remote end */
} LinphoneCallStatus;
/**
* Structure representing a call log.
**/
typedef struct _LinphoneCallLog LinphoneCallLog;
/*******************************************************************************
* Public functions *
******************************************************************************/
/**
* Get the call ID used by the call.
* @param[in] cl LinphoneCallLog object
* @return The call ID used by the call as a string.
**/
LINPHONE_PUBLIC const char * linphone_call_log_get_call_id(const LinphoneCallLog *cl);
/**
* Get the direction of the call.
* @param[in] cl LinphoneCallLog object
* @return The direction of the call.
**/
LINPHONE_PUBLIC LinphoneCallDir linphone_call_log_get_dir(LinphoneCallLog *cl);
/**
* Get the duration of the call.
* @param[in] cl LinphoneCallLog object
* @return The duration of the call in seconds.
**/
LINPHONE_PUBLIC int linphone_call_log_get_duration(LinphoneCallLog *cl);
/**
* Get the origin address (ie from) of the call.
* @param[in] cl LinphoneCallLog object
* @return The origin address (ie from) of the call.
**/
LINPHONE_PUBLIC LinphoneAddress * linphone_call_log_get_from_address(LinphoneCallLog *cl);
/**
* Get the RTP statistics computed locally regarding the call.
* @param[in] cl LinphoneCallLog object
* @return The RTP statistics that have been computed locally for the call.
**/
LINPHONE_PUBLIC const rtp_stats_t * linphone_call_log_get_local_stats(const LinphoneCallLog *cl);
/**
* Get the overall quality indication of the call.
* @param[in] cl LinphoneCallLog object
* @return The overall quality indication of the call.
**/
LINPHONE_PUBLIC float linphone_call_log_get_quality(LinphoneCallLog *cl);
/**
* Get the persistent reference key associated to the call log.
*
* The reference key can be for example an id to an external database.
* It is stored in the config file, thus can survive to process exits/restarts.
*
* @param[in] cl LinphoneCallLog object
* @return The reference key string that has been associated to the call log, or NULL if none has been associated.
**/
LINPHONE_PUBLIC const char * linphone_call_log_get_ref_key(const LinphoneCallLog *cl);
/**
* Get the remote address (that is from or to depending on call direction).
* @param[in] cl LinphoneCallLog object
* @return The remote address of the call.
**/
LINPHONE_PUBLIC LinphoneAddress * linphone_call_log_get_remote_address(LinphoneCallLog *cl);
/**
* Get the RTP statistics computed by the remote end and sent back via RTCP.
* @note Not implemented yet.
* @param[in] cl LinphoneCallLog object
* @return The RTP statistics that have been computed by the remote end for the call.
**/
LINPHONE_PUBLIC const rtp_stats_t * linphone_call_log_get_remote_stats(const LinphoneCallLog *cl);
/**
* Get the start date of the call.
* @param[in] cl LinphoneCallLog object
* @return The date of the beginning of the call.
**/
LINPHONE_PUBLIC time_t linphone_call_log_get_start_date(LinphoneCallLog *cl);
/**
* Get the status of the call.
* @param[in] cl LinphoneCallLog object
* @return The status of the call.
**/
LINPHONE_PUBLIC LinphoneCallStatus linphone_call_log_get_status(LinphoneCallLog *cl);
/**
* Get the destination address (ie to) of the call.
* @param[in] cl LinphoneCallLog object
* @return The destination address (ie to) of the call.
**/
LINPHONE_PUBLIC LinphoneAddress * linphone_call_log_get_to_address(LinphoneCallLog *cl);
/**
* Associate a persistent reference key to the call log.
*
* The reference key can be for example an id to an external database.
* It is stored in the config file, thus can survive to process exits/restarts.
*
* @param[in] cl LinphoneCallLog object
* @param[in] refkey The reference key string to associate to the call log.
**/
LINPHONE_PUBLIC void linphone_call_log_set_ref_key(LinphoneCallLog *cl, const char *refkey);
/**
* Tell whether video was enabled at the end of the call or not.
* @param[in] cl LinphoneCallLog object
* @return A boolean value telling whether video was enabled at the end of the call.
**/
LINPHONE_PUBLIC bool_t linphone_call_log_video_enabled(LinphoneCallLog *cl);
/**
* Get a human readable string describing the call.
* @note: the returned string must be freed by the application (use ms_free()).
* @param[in] cl LinphoneCallLog object
* @return A human readable string describing the call.
**/
LINPHONE_PUBLIC char * linphone_call_log_to_str(LinphoneCallLog *cl);
/*******************************************************************************
* Reference and user data handling functions *
******************************************************************************/
/**
* Get the user data associated with the call log.
* @param[in] cl LinphoneCallLog object
* @return The user data associated with the call log.
**/
LINPHONE_PUBLIC void *linphone_call_log_get_user_data(const LinphoneCallLog *cl);
/**
* Assign a user data to the call log.
* @param[in] cl LinphoneCallLog object
* @param[in] ud The user data to associate with the call log.
**/
LINPHONE_PUBLIC void linphone_call_log_set_user_data(LinphoneCallLog *cl, void *ud);
/**
* Acquire a reference to the call log.
* @param[in] cl LinphoneCallLog object
* @return The same LinphoneCallLog object
**/
LINPHONE_PUBLIC LinphoneCallLog * linphone_call_log_ref(LinphoneCallLog *cl);
/**
* Release a reference to the call log.
* @param[in] cl LinphoneCallLog object
**/
LINPHONE_PUBLIC void linphone_call_log_unref(LinphoneCallLog *cl);
/*******************************************************************************
* DEPRECATED *
******************************************************************************/
/** @deprecated Use linphone_call_log_get_from_address() instead. */
#define linphone_call_log_get_from(cl) linphone_call_log_get_from_address(cl)
/** @deprecated Use linphone_call_log_get_to_address() instead. */
#define linphone_call_log_get_to(cl) linphone_call_log_get_to_address(cl)
/** @deprecated Use linphone_call_log_set_user_data() instead. */
#define linphone_call_log_set_user_pointer(cl, ud) linphone_call_log_set_user_data(cl, ud)
/** @deprecated Use linphone_call_log_get_user_data() instead. */
#define linphone_call_log_get_user_pointer(cl) linphone_call_log_get_user_data(cl)
/**
* Destroy a LinphoneCallLog.
* @param cl LinphoneCallLog object
* @deprecated Use linphone_call_log_unref() instead.
*/
LINPHONE_PUBLIC void linphone_call_log_destroy(LinphoneCallLog *cl);
/**
* @}
**/
#endif /* __LINPHONE_CALL_LOG_H__ */

207
coreapi/call_params.c Normal file
View file

@ -0,0 +1,207 @@
/*
linphone
Copyright (C) 2010-2014 Belledonne Communications SARL
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "private.h"
/*******************************************************************************
* Internal functions *
******************************************************************************/
SalMediaProto get_proto_from_call_params(const LinphoneCallParams *params) {
if ((params->media_encryption == LinphoneMediaEncryptionSRTP) && params->avpf_enabled) return SalProtoRtpSavpf;
if (params->media_encryption == LinphoneMediaEncryptionSRTP) return SalProtoRtpSavp;
if (params->avpf_enabled) return SalProtoRtpAvpf;
return SalProtoRtpAvp;
}
/*******************************************************************************
* Public functions *
******************************************************************************/
void linphone_call_params_add_custom_header(LinphoneCallParams *params, const char *header_name, const char *header_value){
params->custom_headers=sal_custom_header_append(params->custom_headers,header_name,header_value);
}
LinphoneCallParams * linphone_call_params_copy(const LinphoneCallParams *cp){
LinphoneCallParams *ncp=linphone_call_params_new();
memcpy(ncp,cp,sizeof(LinphoneCallParams));
if (cp->record_file) ncp->record_file=ms_strdup(cp->record_file);
if (cp->session_name) ncp->session_name=ms_strdup(cp->session_name);
/*
* The management of the custom headers is not optimal. We copy everything while ref counting would be more efficient.
*/
if (cp->custom_headers) ncp->custom_headers=sal_custom_header_clone(cp->custom_headers);
return ncp;
}
bool_t linphone_call_params_early_media_sending_enabled(const LinphoneCallParams *cp){
return cp->real_early_media;
}
void linphone_call_params_enable_early_media_sending(LinphoneCallParams *cp, bool_t enabled){
cp->real_early_media=enabled;
}
void linphone_call_params_enable_low_bandwidth(LinphoneCallParams *cp, bool_t enabled){
cp->low_bandwidth=enabled;
}
void linphone_call_params_enable_video(LinphoneCallParams *cp, bool_t enabled){
cp->has_video=enabled;
}
const char *linphone_call_params_get_custom_header(const LinphoneCallParams *params, const char *header_name){
return sal_custom_header_find(params->custom_headers,header_name);
}
bool_t linphone_call_params_get_local_conference_mode(const LinphoneCallParams *cp){
return cp->in_conference;
}
LinphoneMediaEncryption linphone_call_params_get_media_encryption(const LinphoneCallParams *cp) {
return cp->media_encryption;
}
LinphonePrivacyMask linphone_call_params_get_privacy(const LinphoneCallParams *params) {
return params->privacy;
}
float linphone_call_params_get_received_framerate(const LinphoneCallParams *cp){
return cp->received_fps;
}
MSVideoSize linphone_call_params_get_received_video_size(const LinphoneCallParams *cp) {
return cp->recv_vsize;
}
const char *linphone_call_params_get_record_file(const LinphoneCallParams *cp){
return cp->record_file;
}
const char * linphone_call_params_get_rtp_profile(const LinphoneCallParams *cp) {
return sal_media_proto_to_string(get_proto_from_call_params(cp));
}
float linphone_call_params_get_sent_framerate(const LinphoneCallParams *cp){
return cp->sent_fps;
}
MSVideoSize linphone_call_params_get_sent_video_size(const LinphoneCallParams *cp) {
return cp->sent_vsize;
}
const char *linphone_call_params_get_session_name(const LinphoneCallParams *cp){
return cp->session_name;
}
const LinphonePayloadType* linphone_call_params_get_used_audio_codec(const LinphoneCallParams *cp) {
return cp->audio_codec;
}
const LinphonePayloadType* linphone_call_params_get_used_video_codec(const LinphoneCallParams *cp) {
return cp->video_codec;
}
bool_t linphone_call_params_low_bandwidth_enabled(const LinphoneCallParams *cp) {
return cp->low_bandwidth;
}
void linphone_call_params_set_audio_bandwidth_limit(LinphoneCallParams *cp, int bandwidth){
cp->audio_bw=bandwidth;
}
void linphone_call_params_set_media_encryption(LinphoneCallParams *cp, LinphoneMediaEncryption e) {
cp->media_encryption = e;
}
void linphone_call_params_set_privacy(LinphoneCallParams *params, LinphonePrivacyMask privacy) {
params->privacy=privacy;
}
void linphone_call_params_set_record_file(LinphoneCallParams *cp, const char *path){
if (cp->record_file){
ms_free(cp->record_file);
cp->record_file=NULL;
}
if (path) cp->record_file=ms_strdup(path);
}
void linphone_call_params_set_session_name(LinphoneCallParams *cp, const char *name){
if (cp->session_name){
ms_free(cp->session_name);
cp->session_name=NULL;
}
if (name) cp->session_name=ms_strdup(name);
}
bool_t linphone_call_params_video_enabled(const LinphoneCallParams *cp){
return cp->has_video;
}
/*******************************************************************************
* Reference and user data handling functions *
******************************************************************************/
void *linphone_call_params_get_user_data(const LinphoneCallParams *cp) {
return cp->user_data;
}
void linphone_call_params_set_user_data(LinphoneCallParams *cp, void *ud) {
cp->user_data = ud;
}
LinphoneCallParams * linphone_call_params_ref(LinphoneCallParams *cp) {
belle_sip_object_ref(cp);
return cp;
}
void linphone_call_params_unref(LinphoneCallParams *cp) {
belle_sip_object_unref(cp);
}
/*******************************************************************************
* Constructor and destructor functions *
******************************************************************************/
static void _linphone_call_params_destroy(LinphoneCallParams *cp){
if (cp->record_file) ms_free(cp->record_file);
if (cp->custom_headers) sal_custom_header_free(cp->custom_headers);
}
LinphoneCallParams * linphone_call_params_new(void) {
return belle_sip_object_new(LinphoneCallParams);
}
/* DEPRECATED */
void linphone_call_params_destroy(LinphoneCallParams *cp) {
linphone_call_params_unref(cp);
}
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneCallParams);
BELLE_SIP_INSTANCIATE_VPTR(LinphoneCallParams, belle_sip_object_t,
(belle_sip_object_destroy_t)_linphone_call_params_destroy,
NULL, // clone
NULL, // marshal
FALSE
);

303
coreapi/call_params.h Normal file
View file

@ -0,0 +1,303 @@
/*
linphone
Copyright (C) 2010-2014 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_CALL_PARAMS_H__
#define __LINPHONE_CALL_PARAMS_H__
/**
* @addtogroup call_control
* @{
**/
/*******************************************************************************
* Structures and enums *
******************************************************************************/
/**
* Private structure definition for LinphoneCallParams.
**/
struct _LinphoneCallParams;
/**
* The LinphoneCallParams is an object containing various call related parameters.
* It can be used to retrieve parameters from a currently running call or modify
* the call's characteristics dynamically.
**/
typedef struct _LinphoneCallParams LinphoneCallParams;
/*******************************************************************************
* Public functions *
******************************************************************************/
/**
* Add a custom SIP header in the INVITE for a call.
* @param[in] cp The #LinphoneCallParams to add a custom SIP header to.
* @param[in] header_name The name of the header to add.
* @param[in] header_value The content of the header to add.
**/
LINPHONE_PUBLIC void linphone_call_params_add_custom_header(LinphoneCallParams *cp, const char *header_name, const char *header_value);
/**
* Copy an existing LinphoneCallParams object to a new LinphoneCallParams object.
* @param[in] cp The LinphoneCallParams object to copy.
* @return A copy of the LinphoneCallParams object.
**/
LINPHONE_PUBLIC LinphoneCallParams * linphone_call_params_copy(const LinphoneCallParams *cp);
/**
* Indicate whether sending of early media was enabled.
* @param[in] cp LinphoneCallParams object
* @return A boolean value telling whether sending of early media was enabled.
**/
LINPHONE_PUBLIC bool_t linphone_call_params_early_media_sending_enabled(const LinphoneCallParams *cp);
/**
* Enable sending of real early media (during outgoing calls).
* @param[in] cp LinphoneCallParams object
* @param[in] enabled A boolean value telling whether to enable early media sending or not.
**/
LINPHONE_PUBLIC void linphone_call_params_enable_early_media_sending(LinphoneCallParams *cp, bool_t enabled);
/**
* Indicate low bandwith mode.
* Configuring a call to low bandwidth mode will result in the core to activate several settings for the call in order to ensure that bitrate usage
* is lowered to the minimum possible. Typically, ptime (packetization time) will be increased, audio codec's output bitrate will be targetted to 20kbit/s provided
* that it is achievable by the codec selected after SDP handshake. Video is automatically disabled.
* @param[in] cp LinphoneCallParams object
* @param[in] enabled A boolean value telling whether to activate the low bandwidth mode or not.
**/
LINPHONE_PUBLIC void linphone_call_params_enable_low_bandwidth(LinphoneCallParams *cp, bool_t enabled);
/**
* Enable video stream.
* @param[in] cp LinphoneCallParams object
* @param[in] enabled A boolean value telling whether to enable video or not.
**/
LINPHONE_PUBLIC void linphone_call_params_enable_video(LinphoneCallParams *cp, bool_t enabled);
/**
* Get a custom SIP header.
* @param[in] cp The #LinphoneCallParams to get the custom SIP header from.
* @param[in] header_name The name of the header to get.
* @return The content of the header or NULL if not found.
**/
LINPHONE_PUBLIC const char *linphone_call_params_get_custom_header(const LinphoneCallParams *cp, const char *header_name);
/**
* Tell whether the call is part of the locally managed conference.
* @param[in] cp LinphoneCallParams object
* @return A boolean value telling whether the call is part of the locally managed conference.
**/
LINPHONE_PUBLIC bool_t linphone_call_params_get_local_conference_mode(const LinphoneCallParams *cp);
/**
* Get the kind of media encryption selected for the call.
* @param[in] cp LinphoneCallParams object
* @return The kind of media encryption selected for the call.
**/
LINPHONE_PUBLIC LinphoneMediaEncryption linphone_call_params_get_media_encryption(const LinphoneCallParams *cp);
/**
* Get requested level of privacy for the call.
* @param[in] cp LinphoneCallParams object
* @return The privacy mode used for the call.
**/
LINPHONE_PUBLIC LinphonePrivacyMask linphone_call_params_get_privacy(const LinphoneCallParams *cp);
/**
* Get the framerate of the video that is received.
* @param[in] cp LinphoneCallParams object
* @return The actual received framerate in frames per seconds, 0 if not available.
*/
LINPHONE_PUBLIC float linphone_call_params_get_received_framerate(const LinphoneCallParams *cp);
/**
* Get the size of the video that is received.
* @param[in] cp LinphoneCallParams object
* @return The received video size or MS_VIDEO_SIZE_UNKNOWN if not available.
*/
LINPHONE_PUBLIC MSVideoSize linphone_call_params_get_received_video_size(const LinphoneCallParams *cp);
/**
* Get the path for the audio recording of the call.
* @param[in] cp LinphoneCallParams object
* @return The path to the audio recording of the call.
**/
LINPHONE_PUBLIC const char *linphone_call_params_get_record_file(const LinphoneCallParams *cp);
/**
* Get the RTP profile being used.
* @param[in] cp #LinphoneCallParams object
* @return The RTP profile.
*/
LINPHONE_PUBLIC const char * linphone_call_params_get_rtp_profile(const LinphoneCallParams *cp);
/**
* Get the framerate of the video that is sent.
* @param[in] cp LinphoneCallParams object
* @return The actual sent framerate in frames per seconds, 0 if not available.
*/
LINPHONE_PUBLIC float linphone_call_params_get_sent_framerate(const LinphoneCallParams *cp);
/**
* Gets the size of the video that is sent.
* @param[in] cp LinphoneCalParams object
* @return The sent video size or MS_VIDEO_SIZE_UNKNOWN if not available.
*/
LINPHONE_PUBLIC MSVideoSize linphone_call_params_get_sent_video_size(const LinphoneCallParams *cp);
/**
* Get the session name of the media session (ie in SDP).
* Subject from the SIP message can be retrieved using linphone_call_params_get_custom_header() and is different.
* @param[in] cp LinphoneCallParams object
* @return The session name of the media session.
**/
LINPHONE_PUBLIC const char *linphone_call_params_get_session_name(const LinphoneCallParams *cp);
/**
* Get the audio codec used in the call, described as a LinphonePayloadType object.
* @param[in] cp LinphoneCallParams object
* @return The LinphonePayloadType object corresponding to the audio codec being used in the call.
**/
LINPHONE_PUBLIC const LinphonePayloadType* linphone_call_params_get_used_audio_codec(const LinphoneCallParams *cp);
/**
* Get the video codec used in the call, described as a LinphonePayloadType structure.
* @param[in] cp LinphoneCallParams object
* @return The LinphonePayloadType object corresponding to the video codec being used in the call.
**/
LINPHONE_PUBLIC const LinphonePayloadType* linphone_call_params_get_used_video_codec(const LinphoneCallParams *cp);
/**
* Tell whether the call has been configured in low bandwidth mode or not.
* This mode can be automatically discovered thanks to a stun server when activate_edge_workarounds=1 in section [net] of configuration file.
* An application that would have reliable way to know network capacity may not use activate_edge_workarounds=1 but instead manually configure
* low bandwidth mode with linphone_call_params_enable_low_bandwidth().
* When enabled, this param may transform a call request with video in audio only mode.
* @param[in] cp LinphoneCallParams object
* @return A boolean value telling whether the low bandwidth mode has been configured/detected.
*/
LINPHONE_PUBLIC bool_t linphone_call_params_low_bandwidth_enabled(const LinphoneCallParams *cp);
/**
* Refine bandwidth settings for this call by setting a bandwidth limit for audio streams.
* As a consequence, codecs whose bitrates are not compatible with this limit won't be used.
* @param[in] cp LinphoneCallParams object
* @param[in] bw The audio bandwidth limit to set in kbit/s.
**/
LINPHONE_PUBLIC void linphone_call_params_set_audio_bandwidth_limit(LinphoneCallParams *cp, int bw);
/**
* Set requested media encryption for a call.
* @param[in] cp LinphoneCallParams object
* @param[in] enc The media encryption to use for the call.
**/
LINPHONE_PUBLIC void linphone_call_params_set_media_encryption(LinphoneCallParams *cp, LinphoneMediaEncryption enc);
/**
* Set requested level of privacy for the call.
* \xmlonly <language-tags>javascript</language-tags> \endxmlonly
* @param[in] cp LinphoneCallParams object
* @param[in] privacy The privacy mode to used for the call.
**/
LINPHONE_PUBLIC void linphone_call_params_set_privacy(LinphoneCallParams *params, LinphonePrivacyMask privacy);
/**
* Enable recording of the call.
* This function must be used before the call parameters are assigned to the call.
* The call recording can be started and paused after the call is established with
* linphone_call_start_recording() and linphone_call_pause_recording().
* @param[in] cp LinphoneCallParams object
* @param[in] path A string containing the path and filename of the file where audio/video streams are to be written.
* The filename must have either .mkv or .wav extention. The video stream will be written only if a MKV file is given.
**/
LINPHONE_PUBLIC void linphone_call_params_set_record_file(LinphoneCallParams *cp, const char *path);
/**
* Set the session name of the media session (ie in SDP).
* Subject from the SIP message (which is different) can be set using linphone_call_params_set_custom_header().
* @param[in] cp LinphoneCallParams object
* @param[in] name The session name to be used.
**/
LINPHONE_PUBLIC void linphone_call_params_set_session_name(LinphoneCallParams *cp, const char *name);
/**
* Tell whether video is enabled or not.
* @param[in] cp LinphoneCallParams object
* @return A boolean value telling whether video is enabled or not.
**/
LINPHONE_PUBLIC bool_t linphone_call_params_video_enabled(const LinphoneCallParams *cp);
/*******************************************************************************
* Reference and user data handling functions *
******************************************************************************/
/**
* Get the user data associated with the call params.
* @param[in] cl LinphoneCallParams object
* @return The user data associated with the call params.
**/
LINPHONE_PUBLIC void *linphone_call_params_get_user_data(const LinphoneCallParams *cp);
/**
* Assign a user data to the call params.
* @param[in] cl LinphoneCallParams object
* @param[in] ud The user data to associate with the call params.
**/
LINPHONE_PUBLIC void linphone_call_params_set_user_data(LinphoneCallParams *cp, void *ud);
/**
* Acquire a reference to the call params.
* @param[in] cl LinphoneCallParams object
* @return The same LinphoneCallParams object
**/
LINPHONE_PUBLIC LinphoneCallParams * linphone_call_params_ref(LinphoneCallParams *cp);
/**
* Release a reference to the call params.
* @param[in] cl LinphoneCallParams object
**/
LINPHONE_PUBLIC void linphone_call_params_unref(LinphoneCallParams *cp);
/*******************************************************************************
* DEPRECATED *
******************************************************************************/
/** @deprecated Use linphone_call_params_get_local_conference_mode() instead. */
#define linphone_call_params_local_conference_mode linphone_call_params_get_local_conference_mode
/**
* Destroy a LinphoneCallParams object.
* @param[in] cp LinphoneCallParams object
* @deprecated Use linphone_call_params_unref() instead.
**/
LINPHONE_PUBLIC void linphone_call_params_destroy(LinphoneCallParams *cp);
/**
* @}
**/
#endif /* __LINPHONE_CALL_PARAMS_H__ */

View file

@ -35,7 +35,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
static void register_failure(SalOp *op);
static int media_parameters_changed(LinphoneCall *call, SalMediaDescription *oldmd, SalMediaDescription *newmd) {
if (call->params.in_conference != call->current_params.in_conference) return SAL_MEDIA_DESCRIPTION_CHANGED;
if (call->params->in_conference != call->current_params->in_conference) return SAL_MEDIA_DESCRIPTION_CHANGED;
if (call->up_bw != linphone_core_get_upload_bandwidth(call->core)) return SAL_MEDIA_DESCRIPTION_CHANGED;
if (call->localdesc_changed) ms_message("Local description has changed: %i", call->localdesc_changed);
return call->localdesc_changed | sal_media_description_equals(oldmd, newmd);
@ -96,7 +96,7 @@ static void prepare_early_media_forking(LinphoneCall *call){
if (call->videostream){
rtp_session_set_symmetric_rtp(call->videostream->ms.sessions.rtp_session,FALSE);
}
}
void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMediaDescription *new_md){
@ -163,7 +163,7 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia
linphone_call_stop_media_streams (call);
linphone_call_init_media_streams (call);
}
if (call->audiostream==NULL){
/*this happens after pausing the call locally. The streams are destroyed and then we wait the 200Ok to recreate them*/
linphone_call_init_media_streams (call);
@ -171,10 +171,10 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia
if (call->state==LinphoneCallIncomingEarlyMedia && linphone_core_get_remote_ringback_tone (lc)!=NULL){
send_ringbacktone=TRUE;
}
if ((call->state==LinphoneCallIncomingEarlyMedia || call->state==LinphoneCallOutgoingEarlyMedia) && !call->params.real_early_media){
if ((call->state==LinphoneCallIncomingEarlyMedia || call->state==LinphoneCallOutgoingEarlyMedia) && !call->params->real_early_media){
all_muted=TRUE;
}
if (call->params.real_early_media && call->state==LinphoneCallOutgoingEarlyMedia){
if (call->params->real_early_media && call->state==LinphoneCallOutgoingEarlyMedia){
prepare_early_media_forking(call);
}
linphone_call_start_media_streams(call,all_muted,send_ringbacktone);
@ -182,9 +182,9 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia
linphone_core_play_named_tone(lc,LinphoneToneCallOnHold);
}
end:
if (oldmd)
if (oldmd)
sal_media_description_unref(oldmd);
}
#if 0
static bool_t is_duplicate_call(LinphoneCore *lc, const LinphoneAddress *from, const LinphoneAddress *to){
@ -192,7 +192,7 @@ static bool_t is_duplicate_call(LinphoneCore *lc, const LinphoneAddress *from, c
for(elem=lc->calls;elem!=NULL;elem=elem->next){
LinphoneCall *call=(LinphoneCall*)elem->data;
if (linphone_address_weak_equal(call->log->from,from) &&
linphone_address_weak_equal(call->log->to, to)){
linphone_address_weak_equal(call->log->to, to)){
return TRUE;
}
}
@ -220,11 +220,11 @@ static bool_t already_a_call_pending(LinphoneCore *lc){
for(elem=lc->calls;elem!=NULL;elem=elem->next){
LinphoneCall *call=(LinphoneCall*)elem->data;
if (call->state==LinphoneCallIncomingReceived
|| call->state==LinphoneCallIncomingEarlyMedia
|| call->state==LinphoneCallOutgoingInit
|| call->state==LinphoneCallOutgoingProgress
|| call->state==LinphoneCallOutgoingEarlyMedia
|| call->state==LinphoneCallOutgoingRinging){
|| call->state==LinphoneCallIncomingEarlyMedia
|| call->state==LinphoneCallOutgoingInit
|| call->state==LinphoneCallOutgoingProgress
|| call->state==LinphoneCallOutgoingEarlyMedia
|| call->state==LinphoneCallOutgoingRinging){
return TRUE;
}
}
@ -239,7 +239,7 @@ static void call_received(SalOp *h){
LinphoneAddress *from_addr, *to_addr;
/*this mode is deprcated because probably useless*/
bool_t prevent_colliding_calls=lp_config_get_int(lc->config,"sip","prevent_colliding_calls",FALSE);
/* first check if we can answer successfully to this invite */
if (linphone_presence_model_get_basic_status(lc->presence_model) == LinphonePresenceBasicStatusClosed) {
LinphonePresenceActivity *activity = linphone_presence_model_get_activity(lc->presence_model);
@ -285,14 +285,14 @@ static void call_received(SalOp *h){
linphone_address_destroy(to_addr);
return;
}
call=linphone_call_new_incoming(lc,from_addr,to_addr,h);
/* the call is acceptable so we can now add it to our list */
linphone_core_add_call(lc,call);
linphone_call_ref(call); /*prevent the call from being destroyed while we are notifying, if the user declines within the state callback */
if ((linphone_core_get_firewall_policy(lc) == LinphonePolicyUseIce) && (call->ice_session != NULL)) {
if ((_linphone_core_get_firewall_policy(lc) == LinphonePolicyUseIce) && (call->ice_session != NULL)) {
/* Defer ringing until the end of the ICE candidates gathering process. */
ms_message("Defer ringing to gather ICE candidates");
return;
@ -313,7 +313,7 @@ static void try_early_media_forking(LinphoneCall *call, SalMediaDescription *md)
int i;
SalStreamDescription *ref_stream,*new_stream;
ms_message("Early media response received from another branch, checking if media can be forked to this new destination.");
for (i=0;i<cur_md->nb_streams;++i){
if (!sal_stream_description_active(&cur_md->streams[i])) continue;
ref_stream=&cur_md->streams[i];
@ -345,15 +345,14 @@ static void call_ringing(SalOp *h){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(h));
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(h);
SalMediaDescription *md;
if (call==NULL) return;
/*set privacy*/
call->current_params.privacy=(LinphonePrivacyMask)sal_op_get_privacy(call->op);
if (lc->vtable.display_status)
lc->vtable.display_status(lc,_("Remote ringing."));
if (call==NULL) return;
/*set privacy*/
call->current_params->privacy=(LinphonePrivacyMask)sal_op_get_privacy(call->op);
linphone_core_notify_display_status(lc,_("Remote ringing."));
md=sal_call_get_final_media_description(h);
if (md==NULL){
linphone_core_stop_dtmf_stream(lc);
@ -364,11 +363,12 @@ static void call_ringing(SalOp *h){
/*we release sound before playing ringback tone*/
if (call->audiostream)
audio_stream_unprepare_sound(call->audiostream);
lc->ringstream=ring_start(lc->sound_conf.remote_ring,2000,ringcard);
if( lc->sound_conf.remote_ring ){
lc->ringstream=ring_start(lc->sound_conf.remote_ring,2000,ringcard);
}
}
ms_message("Remote ringing...");
if (lc->vtable.display_status)
lc->vtable.display_status(lc,_("Remote ringing..."));
linphone_core_notify_display_status(lc,_("Remote ringing..."));
linphone_call_set_state(call,LinphoneCallOutgoingRinging,"Remote ringing");
}else{
/*accept early media */
@ -377,9 +377,8 @@ static void call_ringing(SalOp *h){
try_early_media_forking(call,md);
return;
}
if (lc->vtable.show) lc->vtable.show(lc);
if (lc->vtable.display_status)
lc->vtable.display_status(lc,_("Early media."));
linphone_core_notify_show_interface(lc);
linphone_core_notify_display_status(lc,_("Early media."));
linphone_call_set_state(call,LinphoneCallOutgoingEarlyMedia,"Early media");
linphone_core_stop_ringing(lc);
ms_message("Doing early media...");
@ -396,13 +395,13 @@ static void call_accepted(SalOp *op){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
SalMediaDescription *md;
if (call==NULL){
ms_warning("No call to accept.");
return ;
}
/*set privacy*/
call->current_params.privacy=(LinphonePrivacyMask)sal_op_get_privacy(call->op);
call->current_params->privacy=(LinphonePrivacyMask)sal_op_get_privacy(call->op);
/* Handle remote ICE attributes if any. */
if (call->ice_session != NULL) {
@ -416,22 +415,22 @@ static void call_accepted(SalOp *op){
md=sal_call_get_final_media_description(op);
if (md) /*make sure re-invite will not propose video again*/
call->params.has_video &= linphone_core_media_description_contains_video_stream(md);
call->params->has_video &= linphone_core_media_description_contains_video_stream(md);
if (call->state==LinphoneCallOutgoingProgress ||
call->state==LinphoneCallOutgoingRinging ||
call->state==LinphoneCallOutgoingEarlyMedia){
call->state==LinphoneCallOutgoingRinging ||
call->state==LinphoneCallOutgoingEarlyMedia){
linphone_call_set_state(call,LinphoneCallConnected,"Connected");
if (call->referer) linphone_core_notify_refer_state(lc,call->referer,call);
}
if (md && !sal_media_description_empty(md) && !linphone_core_incompatible_security(lc,md)){
linphone_call_update_remote_session_id_and_ver(call);
if (sal_media_description_has_dir(md,SalStreamSendOnly) ||
sal_media_description_has_dir(md,SalStreamInactive)){
if (lc->vtable.display_status){
sal_media_description_has_dir(md,SalStreamInactive)){
{
char *tmp=linphone_call_get_remote_address_as_string (call);
char *msg=ms_strdup_printf(_("Call with %s is paused."),tmp);
lc->vtable.display_status(lc,msg);
linphone_core_notify_display_status(lc,msg);
ms_free(tmp);
ms_free(msg);
}
@ -441,10 +440,10 @@ static void call_accepted(SalOp *op){
linphone_core_start_refered_call(lc,call,NULL);
}else if (sal_media_description_has_dir(md,SalStreamRecvOnly)){
/*we are put on hold when the call is initially accepted */
if (lc->vtable.display_status){
{
char *tmp=linphone_call_get_remote_address_as_string (call);
char *msg=ms_strdup_printf(_("Call answered by %s - on hold."),tmp);
lc->vtable.display_status(lc,msg);
linphone_core_notify_display_status(lc,msg);
ms_free(tmp);
ms_free(msg);
}
@ -453,14 +452,12 @@ static void call_accepted(SalOp *op){
}else{
if (call->state!=LinphoneCallUpdating){
if (call->state==LinphoneCallResuming){
if (lc->vtable.display_status){
lc->vtable.display_status(lc,_("Call resumed."));
}
linphone_core_notify_display_status(lc,_("Call resumed."));
}else{
if (lc->vtable.display_status){
{
char *tmp=linphone_call_get_remote_address_as_string (call);
char *msg=ms_strdup_printf(_("Call answered by %s."),tmp);
lc->vtable.display_status(lc,msg);
linphone_core_notify_display_status(lc,msg);
ms_free(tmp);
ms_free(msg);
}
@ -470,7 +467,7 @@ static void call_accepted(SalOp *op){
/*also reflect the change if the "wished" params, in order to avoid to propose SAVP or video again
* further in the call, for example during pause,resume, conferencing reINVITEs*/
linphone_call_fix_call_parameters(call);
if (!call->current_params.in_conference)
if (!call->current_params->in_conference)
lc->current_call=call;
if (call->prevstate != LinphoneCallIncomingEarlyMedia) /*don't change state in aswer to a SIP UPDATE in early media*/
linphone_call_set_state(call, LinphoneCallStreamsRunning, "Streams running");
@ -503,81 +500,73 @@ static void call_ack(SalOp *op){
}
}
static void call_accept_update(LinphoneCore *lc, LinphoneCall *call){
SalMediaDescription *md;
SalMediaDescription *rmd=sal_call_get_remote_media_description(call->op);
if (rmd!=NULL && call->ice_session!=NULL) {
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);
if (md && !sal_media_description_empty(md)){
linphone_core_update_streams(lc,call,md);
}
}
static void call_resumed(LinphoneCore *lc, LinphoneCall *call){
/*when we are resumed, increment session id, because sdp is changed (a=recvonly disapears)*/
linphone_call_increment_local_media_description(call);
call_accept_update(lc,call);
if(lc->vtable.display_status)
lc->vtable.display_status(lc,_("We have been resumed."));
linphone_call_set_state(call,LinphoneCallStreamsRunning,"Connected (streams running)");
linphone_core_notify_display_status(lc,_("We have been resumed."));
_linphone_core_accept_call_update(lc,call,NULL,LinphoneCallStreamsRunning,"Connected (streams running)");
}
static void call_paused_by_remote(LinphoneCore *lc, LinphoneCall *call){
/*when we are resumed, increment session id, because sdp is changed (a=recvonly appears)*/
/*when we are paused, increment session id, because sdp is changed (a=recvonly appears)*/
linphone_call_increment_local_media_description(call);
call_accept_update(lc,call);
/* we are being paused */
if(lc->vtable.display_status)
lc->vtable.display_status(lc,_("We are paused by other party."));
linphone_call_set_state (call,LinphoneCallPausedByRemote,"Call paused by remote");
linphone_core_notify_display_status(lc,_("We are paused by other party."));
_linphone_core_accept_call_update(lc,call,NULL,LinphoneCallPausedByRemote,"Call paused by remote");
}
static void call_updated_by_remote(LinphoneCore *lc, LinphoneCall *call,bool_t notify_application){
static void call_updated_by_remote(LinphoneCore *lc, LinphoneCall *call, bool_t is_update){
/*first check if media capabilities are compatible*/
SalMediaDescription* md;
linphone_call_make_local_media_description(lc,call);
sal_call_set_local_media_description(call->op,call->localdesc);
md=sal_call_get_final_media_description(call->op);
if (md && (sal_media_description_empty(md) || linphone_core_incompatible_security(lc,md))){
sal_call_decline(call->op,SalReasonNotAcceptable,NULL);
return;
SalMediaDescription *md;
SalMediaDescription *rmd=sal_call_get_remote_media_description(call->op);
SalMediaDescription *prev_result_desc=call->resultdesc;
if (rmd!=NULL){
if (call->state!=LinphoneCallPaused){
/*in paused state, we must stay in paused state.*/
linphone_call_make_local_media_description(lc,call);
sal_call_set_local_media_description(call->op,call->localdesc);
}
md=sal_call_get_final_media_description(call->op);
if (md && (sal_media_description_empty(md) || linphone_core_incompatible_security(lc,md))){
sal_call_decline(call->op,SalReasonNotAcceptable,NULL);
return;
}
if (is_update && prev_result_desc && md){
int diff=sal_media_description_equals(prev_result_desc,md);
if (diff & (SAL_MEDIA_DESCRIPTION_CRYPTO_CHANGED|SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED)){
ms_warning("Cannot accept this update, it is changing parameters that require user approval");
sal_call_decline(call->op,SalReasonNotAcceptable,NULL); /*FIXME should send 504 Cannot change the session parameters without prompting the user"*/
return;
}
}
}
if (notify_application) {
if(lc->vtable.display_status)
lc->vtable.display_status(lc,_("Call is updated by remote."));
if (call->state==LinphoneCallStreamsRunning) {
/*reINVITE and in-dialogs UPDATE go here*/
linphone_core_notify_display_status(lc,_("Call is updated by remote."));
call->defer_update=FALSE;
linphone_call_set_state(call, LinphoneCallUpdatedByRemote,"Call updated by remote");
if (call->defer_update==FALSE){
linphone_core_accept_call_update(lc,call,NULL);
}
} else { /*SIP UPDATE case*/
/*can be call from any state*/
_linphone_core_accept_call_update(lc,call,NULL);
if (rmd==NULL)
call->expect_media_in_ack=TRUE;
} else if (is_update){ /*SIP UPDATE case, can occur in early states*/
_linphone_core_accept_call_update(lc,call,NULL,call->state,linphone_call_state_to_string(call->state));
}
}
/* this callback is called when an incoming re-INVITE/ SIP UPDATE modifies the session*/
static void call_updating(SalOp *op){
static void call_updating(SalOp *op, bool_t is_update){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
SalMediaDescription *rmd=sal_call_get_remote_media_description(op);
if (rmd==NULL){
/* case of a reINVITE without SDP */
call_accept_update(lc,call);
call->expect_media_in_ack=TRUE;
/* case of a reINVITE or UPDATE without SDP */
call_updated_by_remote(lc,call,is_update);
return;
}
@ -585,22 +574,45 @@ static void call_updating(SalOp *op){
case LinphoneCallPausedByRemote:
if (sal_media_description_has_dir(rmd,SalStreamSendRecv) || sal_media_description_has_dir(rmd,SalStreamRecvOnly)){
call_resumed(lc,call);
}else call_paused_by_remote(lc,call);
}else call_updated_by_remote(lc,call,is_update);
break;
/*SIP UPDATE CASE*/
case LinphoneCallOutgoingRinging:
case LinphoneCallOutgoingEarlyMedia:
call_updated_by_remote(lc,call,FALSE);
case LinphoneCallIncomingEarlyMedia:
if (is_update) call_updated_by_remote(lc,call,is_update);
break;
case LinphoneCallStreamsRunning:
case LinphoneCallConnected:
if (sal_media_description_has_dir(rmd,SalStreamSendOnly) || sal_media_description_has_dir(rmd,SalStreamInactive)){
call_paused_by_remote(lc,call);
}else{
call_updated_by_remote(lc,call,TRUE);
call_updated_by_remote(lc,call,is_update);
}
break;
default:
call_accept_update(lc,call);
case LinphoneCallPaused:
if (sal_media_description_has_dir(rmd,SalStreamSendOnly) || sal_media_description_has_dir(rmd,SalStreamInactive)){
call_paused_by_remote(lc,call);
}else{
call_updated_by_remote(lc,call,is_update);
}
break;
case LinphoneCallUpdating:
case LinphoneCallPausing:
case LinphoneCallResuming:
case LinphoneCallUpdatedByRemote:
sal_call_decline(call->op,SalReasonNotImplemented,NULL);
/*no break*/
case LinphoneCallIdle:
case LinphoneCallOutgoingInit:
case LinphoneCallEnd:
case LinphoneCallIncomingReceived:
case LinphoneCallOutgoingProgress:
case LinphoneCallRefered:
case LinphoneCallError:
case LinphoneCallReleased:
ms_warning("Receiving reINVITE or UPDATE while in state [%s], should not happen.",linphone_call_state_to_string(call->state));
break;
}
}
@ -609,7 +621,7 @@ static void call_terminated(SalOp *op, const char *from){
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
if (call==NULL) return;
switch(linphone_call_get_state(call)){
case LinphoneCallEnd:
case LinphoneCallError:
@ -632,10 +644,8 @@ static void call_terminated(SalOp *op, const char *from){
linphone_core_stop_ringing(lc);
}
linphone_call_stop_media_streams(call);
if (lc->vtable.show!=NULL)
lc->vtable.show(lc);
if (lc->vtable.display_status!=NULL)
lc->vtable.display_status(lc,_("Call terminated."));
linphone_core_notify_show_interface(lc);
linphone_core_notify_display_status(lc,_("Call terminated."));
#ifdef BUILD_UPNP
linphone_call_delete_upnp_session(call);
@ -648,7 +658,7 @@ static int resume_call_after_failed_transfer(LinphoneCall *call){
ms_message("!!!!!!!!!!resume_call_after_failed_transfer");
if (call->was_automatically_paused && call->state==LinphoneCallPausing)
return BELLE_SIP_CONTINUE; /*was still in pausing state*/
if (call->was_automatically_paused && call->state==LinphoneCallPaused){
if (sal_op_is_idle(call->op)){
linphone_core_resume_call(call->core,call);
@ -677,25 +687,22 @@ static void call_failure(SalOp *op){
ms_warning("Call faillure reported on already terminated call.");
return ;
}
if (lc->vtable.show) lc->vtable.show(lc);
linphone_core_notify_show_interface(lc);
switch(ei->reason){
case SalReasonNone:
break;
case SalReasonRequestTimeout:
msg=_("Request timeout.");
if (lc->vtable.display_status)
lc->vtable.display_status(lc,msg);
linphone_core_notify_display_status(lc,msg);
break;
case SalReasonDeclined:
msg=msg603;
if (lc->vtable.display_status)
lc->vtable.display_status(lc,msg603);
linphone_core_notify_display_status(lc,msg603);
break;
case SalReasonBusy:
msg=msg486;
if (lc->vtable.display_status)
lc->vtable.display_status(lc,msg486);
linphone_core_notify_display_status(lc,msg486);
break;
case SalReasonRedirect:
{
@ -715,23 +722,19 @@ static void call_failure(SalOp *op){
}
}
msg=_("Redirected");
if (lc->vtable.display_status)
lc->vtable.display_status(lc,msg);
linphone_core_notify_display_status(lc,msg);
}
break;
case SalReasonTemporarilyUnavailable:
msg=msg480;
if (lc->vtable.display_status)
lc->vtable.display_status(lc,msg480);
linphone_core_notify_display_status(lc,msg480);
break;
case SalReasonNotFound:
if (lc->vtable.display_status)
lc->vtable.display_status(lc,msg);
linphone_core_notify_display_status(lc,msg);
break;
case SalReasonDoNotDisturb:
msg=msg600;
if (lc->vtable.display_status)
lc->vtable.display_status(lc,msg600);
linphone_core_notify_display_status(lc,msg600);
break;
case SalReasonUnsupportedContent: /*<this is for compatibility: linphone sent 415 because of SDP offer answer failure*/
case SalReasonNotAcceptable:
@ -743,30 +746,29 @@ static void call_failure(SalOp *op){
int i;
for (i = 0; i < call->localdesc->nb_streams; i++) {
if (!sal_stream_description_active(&call->localdesc->streams[i])) continue;
if (call->params.media_encryption == LinphoneMediaEncryptionSRTP) {
if (call->params.avpf_enabled == TRUE) {
if (call->params->media_encryption == LinphoneMediaEncryptionSRTP) {
if (call->params->avpf_enabled == TRUE) {
if (i == 0) ms_message("Retrying call [%p] with SAVP", call);
call->params.avpf_enabled = FALSE;
call->params->avpf_enabled = FALSE;
linphone_core_restart_invite(lc, call);
return;
} else if (!linphone_core_is_media_encryption_mandatory(lc)) {
if (i == 0) ms_message("Retrying call [%p] with AVP", call);
call->params.media_encryption = LinphoneMediaEncryptionNone;
call->params->media_encryption = LinphoneMediaEncryptionNone;
memset(call->localdesc->streams[i].crypto, 0, sizeof(call->localdesc->streams[i].crypto));
linphone_core_restart_invite(lc, call);
return;
}
} else if (call->params.avpf_enabled == TRUE) {
} else if (call->params->avpf_enabled == TRUE) {
if (i == 0) ms_message("Retrying call [%p] with AVP", call);
call->params.avpf_enabled = FALSE;
call->params->avpf_enabled = FALSE;
linphone_core_restart_invite(lc, call);
return;
}
}
}
msg=_("Incompatible media parameters.");
if (lc->vtable.display_status)
lc->vtable.display_status(lc,msg);
linphone_core_notify_display_status(lc,msg);
break;
case SalReasonRequestPending:
/*restore previous state, the application will decide to resubmit the action if relevant*/
@ -774,8 +776,7 @@ static void call_failure(SalOp *op){
return;
break;
default:
if (lc->vtable.display_status)
lc->vtable.display_status(lc,_("Call failed."));
linphone_core_notify_display_status(lc,_("Call failed."));
}
/*some call error are not fatal*/
@ -796,7 +797,7 @@ static void call_failure(SalOp *op){
#ifdef BUILD_UPNP
linphone_call_delete_upnp_session(call);
#endif //BUILD_UPNP
if (call->state!=LinphoneCallEnd && call->state!=LinphoneCallError){
if (ei->reason==SalReasonDeclined){
linphone_call_set_state(call,LinphoneCallEnd,"Call declined.");
@ -805,7 +806,7 @@ static void call_failure(SalOp *op){
}
if (ei->reason!=SalReasonNone) linphone_core_play_call_error_tone(lc,linphone_reason_from_sal(ei->reason));
}
if (referer){
/*notify referer of the failure*/
linphone_core_notify_refer_state(lc,referer,call);
@ -827,35 +828,38 @@ static void call_released(SalOp *op){
static void auth_failure(SalOp *op, SalAuthInfo* info) {
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
LinphoneAuthInfo *ai=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,info->realm,info->username,info->domain);
if (ai){
ms_message("%s/%s/%s authentication fails.",info->realm,info->username,info->domain);
/*ask again for password if auth info was already supplied but apparently not working*/
if (lc->vtable.auth_info_requested) {
lc->vtable.auth_info_requested(lc,info->realm,info->username,info->domain);
LinphoneAuthInfo *ai=NULL;
if( info != NULL ){
ai = (LinphoneAuthInfo*)linphone_core_find_auth_info(lc,info->realm,info->username,info->domain);
if (ai){
ms_message("%s/%s/%s authentication fails.",info->realm,info->username,info->domain);
/*ask again for password if auth info was already supplied but apparently not working*/
linphone_core_notify_auth_info_requested(lc,info->realm,info->username,info->domain);
}
}
}
static void register_success(SalOp *op, bool_t registered){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)sal_op_get_user_pointer(op);
char *msg;
if (!cfg || cfg->deletion_date!=0){
ms_message("Registration success for removed proxy config, ignored");
if (!cfg){
ms_message("Registration success for deleted proxy config, ignored");
return;
}
linphone_proxy_config_set_state(cfg, registered ? LinphoneRegistrationOk : LinphoneRegistrationCleared ,
registered ? "Registration successful" : "Unregistration done");
if (lc->vtable.display_status){
registered ? "Registration successful" : "Unregistration done");
{
if (registered) msg=ms_strdup_printf(_("Registration on %s successful."),sal_op_get_proxy(op));
else msg=ms_strdup_printf(_("Unregistration on %s done."),sal_op_get_proxy(op));
lc->vtable.display_status(lc,msg);
linphone_core_notify_display_status(lc,msg);
ms_free(msg);
}
}
static void register_failure(SalOp *op){
@ -868,16 +872,12 @@ static void register_failure(SalOp *op){
ms_warning("Registration failed for unknown proxy config.");
return ;
}
if (cfg->deletion_date!=0){
ms_message("Registration failed for removed proxy config, ignored");
return;
}
if (details==NULL)
details=_("no response timeout");
if (lc->vtable.display_status) {
{
char *msg=ortp_strdup_printf(_("Registration on %s failed: %s"),sal_op_get_proxy(op), details);
lc->vtable.display_status(lc,msg);
linphone_core_notify_display_status(lc,msg);
ms_free(msg);
}
@ -910,8 +910,7 @@ static void vfu_request(SalOp *op){
static void dtmf_received(SalOp *op, char dtmf){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
if (lc->vtable.dtmf_received != NULL)
lc->vtable.dtmf_received(lc, call, dtmf);
linphone_core_notify_dtmf_received(lc, call, dtmf);
}
static void refer_received(Sal *sal, SalOp *op, const char *referto){
@ -924,14 +923,14 @@ static void refer_received(Sal *sal, SalOp *op, const char *referto){
call->refer_to=ms_strdup(referto);
call->refer_pending=TRUE;
linphone_call_set_state(call,LinphoneCallRefered,"Refered");
if (lc->vtable.display_status){
{
char *msg=ms_strdup_printf(_("We are transferred to %s"),referto);
lc->vtable.display_status(lc,msg);
linphone_core_notify_display_status(lc,msg);
ms_free(msg);
}
if (call->refer_pending) linphone_core_start_refered_call(lc,call,NULL);
}else if (lc->vtable.refer_received){
lc->vtable.refer_received(lc,referto);
}else {
linphone_core_notify_refer_received(lc,referto);
}
}
@ -1051,8 +1050,8 @@ static bool_t auth_requested(Sal* sal, SalAuthInfo* sai) {
if (fill_auth_info(lc,sai)) {
return TRUE;
} else {
if (lc->vtable.auth_info_requested) {
lc->vtable.auth_info_requested(lc,sai->realm,sai->username,sai->domain);
{
linphone_core_notify_auth_info_requested(lc,sai->realm,sai->username,sai->domain);
if (fill_auth_info(lc,sai)) {
return TRUE;
}
@ -1135,9 +1134,9 @@ static void info_received(SalOp *op, const SalBody *body){
static void subscribe_response(SalOp *op, SalSubscribeStatus status){
LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op);
const SalErrorInfo *ei=sal_op_get_error_info(op);
if (lev==NULL) return;
if (status==SalSubscribeActive){
linphone_event_set_state(lev,LinphoneSubscriptionActive);
}else if (status==SalSubscribePending){
@ -1153,15 +1152,15 @@ static void subscribe_response(SalOp *op, SalSubscribeStatus status){
static void notify(SalOp *op, SalSubscribeStatus st, const char *eventname, const SalBody *body){
LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op);
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
LinphoneContent content;
LinphoneContent content={0};
if (lev==NULL) {
/*out of subscribe notify */
lev=linphone_event_new_with_out_of_dialog_op(lc,op,LinphoneSubscriptionOutgoing,eventname);
}
if (lc->vtable.notify_received){
{
const LinphoneContent *ct=linphone_content_from_sal_body(&content,body);
if (ct) lc->vtable.notify_received(lc,lev,eventname,ct);
if (ct) linphone_core_notify_notify_received(lc,lev,eventname,ct);
}
if (st!=SalSubscribeNone){
linphone_event_set_state(lev,linphone_subscription_state_from_sal(st));
@ -1171,31 +1170,31 @@ static void notify(SalOp *op, SalSubscribeStatus st, const char *eventname, cons
static void subscribe_received(SalOp *op, const char *eventname, const SalBody *body){
LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op);
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
if (lev==NULL) {
lev=linphone_event_new_with_op(lc,op,LinphoneSubscriptionIncoming,eventname);
linphone_event_set_state(lev,LinphoneSubscriptionIncomingReceived);
}else{
/*subscribe refresh, unhandled*/
}
}
static void subscribe_closed(SalOp *op){
LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op);
linphone_event_set_state(lev,LinphoneSubscriptionTerminated);
}
static void on_publish_response(SalOp* op){
LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op);
const SalErrorInfo *ei=sal_op_get_error_info(op);
if (lev==NULL) return;
if (ei->reason==SalReasonNone){
if (!lev->terminating)
linphone_event_set_publish_state(lev,LinphonePublishOk);
else
else
linphone_event_set_publish_state(lev,LinphonePublishCleared);
}else{
if (lev->publish_state==LinphonePublishOk){
@ -1208,9 +1207,9 @@ static void on_publish_response(SalOp* op){
static void on_expire(SalOp *op){
LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op);
if (lev==NULL) return;
if (linphone_event_get_publish_state(lev)==LinphonePublishOk){
linphone_event_set_publish_state(lev,LinphonePublishExpiring);
}else if (linphone_event_get_subscription_state(lev)==LinphoneSubscriptionActive){

View file

@ -39,22 +39,37 @@
static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatMessage* msg);
#define MULTIPART_BOUNDARY "---------------------------14737809831466499882746641449"
#define FILEPART_HEADER_1 "Content-Disposition: form-data; name=\"File\"; filename=\""
#define FILEPART_HEADER_2 "\"\r\n" \
"Content-Type: "
#define FILEPART_HEADER_3 "\r\n\r\n"
const char *multipart_boundary=MULTIPART_BOUNDARY;
#define FILE_TRANSFER_KEY_SIZE 32
static size_t linphone_chat_message_compute_filepart_header_size(const char *filename, const char *content_type) {
return strlen(FILEPART_HEADER_1)+strlen(filename)+strlen(FILEPART_HEADER_2)+strlen(content_type)+strlen(FILEPART_HEADER_3);
}
static void process_io_error(void *data, const belle_sip_io_error_event_t *event){
static void process_io_error_upload(void *data, const belle_sip_io_error_event_t *event){
LinphoneChatMessage* msg=(LinphoneChatMessage *)data;
msg->cb(msg, LinphoneChatMessageStateNotDelivered, msg->chat_room->lc);
ms_error("I/O Error during file upload to %s - msg [%p] chat room[%p]", msg->chat_room->lc->file_transfer_server, msg, msg->chat_room);
if (msg->cb) {
msg->cb(msg, LinphoneChatMessageStateNotDelivered, msg->chat_room->lc);
}
#define FILE_TRANSFER_KEY_SIZE 32
}
static void process_auth_requested(void *data, belle_sip_auth_event_t *event){
printf("We have a auth requested!\n");
static void process_auth_requested_upload(void *data, belle_sip_auth_event_t *event){
LinphoneChatMessage* msg=(LinphoneChatMessage *)data;
ms_error("Error during file upload : auth requested to connect %s - msg [%p] chat room[%p]", msg->chat_room->lc->file_transfer_server, msg, msg->chat_room);
if (msg->cb) {
msg->cb(msg, LinphoneChatMessageStateNotDelivered, msg->chat_room->lc);
}
}
static void process_io_error_download(void *data, const belle_sip_io_error_event_t *event){
LinphoneChatMessage* msg=(LinphoneChatMessage *)data;
ms_error("I/O Error during file download %s - msg [%p] chat room[%p]", msg->external_body_url, msg, msg->chat_room);
if (msg->cb) {
msg->cb(msg, LinphoneChatMessageStateFileTransferError, msg->chat_room->lc);
}
}
static void process_auth_requested_download(void *data, belle_sip_auth_event_t *event){
LinphoneChatMessage* msg=(LinphoneChatMessage *)data;
ms_error("Error during file download : auth requested to get %s - msg [%p] chat room[%p]", msg->external_body_url, msg, msg->chat_room);
if (msg->cb) {
msg->cb(msg, LinphoneChatMessageStateFileTransferError, msg->chat_room->lc);
}
}
/**
@ -65,9 +80,7 @@ static void linphone_chat_message_file_transfer_on_progress(belle_sip_body_handl
LinphoneChatMessage* chatMsg=(LinphoneChatMessage *)data;
LinphoneCore *lc = chatMsg->chat_room->lc;
/* call back given by application level */
if (lc->vtable.file_transfer_progress_indication != NULL) {
lc->vtable.file_transfer_progress_indication(lc, chatMsg, chatMsg->file_transfer_information, (size_t)(((double)offset/(double)total)*100.0));
}
linphone_core_notify_file_transfer_progress_indication(lc, chatMsg, chatMsg->file_transfer_information, (size_t)(((double)offset/(double)total)*100.0));
return;
}
@ -86,24 +99,11 @@ static int linphone_chat_message_file_transfer_on_send_body(belle_sip_user_body_
LinphoneChatMessage* chatMsg=(LinphoneChatMessage *)data;
LinphoneCore *lc = chatMsg->chat_room->lc;
char *buf = (char *)buffer;
char *content_type=belle_sip_strdup_printf("%s/%s", chatMsg->file_transfer_information->type, chatMsg->file_transfer_information->subtype);
size_t end_of_file=linphone_chat_message_compute_filepart_header_size(chatMsg->file_transfer_information->name, content_type)+chatMsg->file_transfer_information->size;
if (offset==0){
int partlen=linphone_chat_message_compute_filepart_header_size(chatMsg->file_transfer_information->name, content_type);
memcpy(buf,FILEPART_HEADER_1,strlen(FILEPART_HEADER_1));
buf += strlen(FILEPART_HEADER_1);
memcpy(buf,chatMsg->file_transfer_information->name,strlen(chatMsg->file_transfer_information->name));
buf += strlen(chatMsg->file_transfer_information->name);
memcpy(buf,FILEPART_HEADER_2,strlen(FILEPART_HEADER_2));
buf += strlen(FILEPART_HEADER_2);
memcpy(buf,content_type,strlen(content_type));
buf += strlen(content_type);
memcpy(buf,FILEPART_HEADER_3,strlen(FILEPART_HEADER_3));
*size=partlen;
}else if (offset<end_of_file){
/* if we've not reach the end of file yet, ask for more data*/
if (offset<chatMsg->file_transfer_information->size){
if (chatMsg->file_transfer_information->key != NULL) { /* if we have a key to cipher the message, use it! */
/* get data from callback to a plainBuffer */
/* if this chunk is not the last one, the lenght must be a multiple of block cipher size(16 bytes)*/
@ -111,12 +111,12 @@ static int linphone_chat_message_file_transfer_on_send_body(belle_sip_user_body_
*size -=(*size%16);
}
char *plainBuffer = (char *)malloc(*size);
lc->vtable.file_transfer_send(lc, chatMsg, chatMsg->file_transfer_information, plainBuffer, size);
linphone_core_notify_file_transfer_send(lc, chatMsg, chatMsg->file_transfer_information, buf, size);
lime_encryptFile(&(chatMsg->file_transfer_information->cryptoContext), chatMsg->file_transfer_information->key, *size, plainBuffer, (char*)buffer);
free(plainBuffer);
} else {
/* get data from call back directly to the output buffer */
lc->vtable.file_transfer_send(lc, chatMsg, chatMsg->file_transfer_information, (char*)buffer, size);
linphone_core_notify_file_transfer_send(lc, chatMsg, chatMsg->file_transfer_information, buf, size);
}
/* DEBUG DEBUG : THIS SHALL NEVER HAPPEND */
if (*size == 0) {
@ -129,7 +129,6 @@ static int linphone_chat_message_file_transfer_on_send_body(belle_sip_user_body_
}
}
belle_sip_free(content_type);
return BELLE_SIP_CONTINUE;
}
@ -159,18 +158,26 @@ static void linphone_chat_message_process_response_from_post_file(void *data, co
belle_http_request_listener_t *l;
belle_generic_uri_t *uri;
belle_http_request_t *req;
char *content_type=belle_sip_strdup_printf("%s/%s", msg->file_transfer_information->type, msg->file_transfer_information->subtype);
belle_sip_multipart_body_handler_t *bh;
char* ua;
char *content_type;
char *first_part_header;
belle_sip_user_body_handler_t *first_part_bh;
/* create a user body handler to take care of the file */
size_t body_size = msg->file_transfer_information->size+linphone_chat_message_compute_filepart_header_size(msg->file_transfer_information->name, content_type);
/* temporary storage for the Content-disposition header value */
first_part_header = belle_sip_strdup_printf("form-data; name=\"File\"; filename=\"%s\"", msg->file_transfer_information->name);
/* create a user body handler to take care of the file and add the content disposition and content-type headers */
first_part_bh=belle_sip_user_body_handler_new(msg->file_transfer_information->size,NULL,NULL,linphone_chat_message_file_transfer_on_send_body,msg);
belle_sip_body_handler_add_header((belle_sip_body_handler_t *)first_part_bh, belle_sip_header_create("Content-disposition", first_part_header));
belle_sip_free(first_part_header);
belle_sip_body_handler_add_header((belle_sip_body_handler_t *)first_part_bh, (belle_sip_header_t *)belle_sip_header_content_type_create(msg->file_transfer_information->type, msg->file_transfer_information->subtype));
belle_sip_user_body_handler_t *first_part_bh=belle_sip_user_body_handler_new(body_size,NULL,NULL,linphone_chat_message_file_transfer_on_send_body,msg);
/* insert it in a multipart body handler which will manage the boundaries of multipart message */
belle_sip_multipart_body_handler_t *bh=belle_sip_multipart_body_handler_new(linphone_chat_message_file_transfer_on_progress, msg, (belle_sip_body_handler_t *)first_part_bh);
bh=belle_sip_multipart_body_handler_new(linphone_chat_message_file_transfer_on_progress, msg, (belle_sip_body_handler_t *)first_part_bh);
char* ua = ms_strdup_printf("%s/%s", linphone_core_get_user_agent_name(), linphone_core_get_user_agent_version());
ua = ms_strdup_printf("%s/%s", linphone_core_get_user_agent_name(), linphone_core_get_user_agent_version());
belle_sip_free(content_type);
content_type=belle_sip_strdup_printf("multipart/form-data; boundary=%s",multipart_boundary);
uri=belle_generic_uri_parse(msg->chat_room->lc->file_transfer_server);
@ -184,13 +191,19 @@ static void linphone_chat_message_process_response_from_post_file(void *data, co
belle_sip_free(content_type);
belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(req),BELLE_SIP_BODY_HANDLER(bh));
cbs.process_response=linphone_chat_message_process_response_from_post_file;
cbs.process_io_error=process_io_error;
cbs.process_auth_requested=process_auth_requested;
cbs.process_io_error=process_io_error_upload;
cbs.process_auth_requested=process_auth_requested_upload;
l=belle_http_request_listener_create_from_callbacks(&cbs,msg);
msg->http_request=req; /* update the reference to the http request to be able to cancel it during upload */
belle_http_provider_send_request(msg->chat_room->lc->http_provider,req,l);
}
if (code == 200 ) { /* file has been uplaoded correctly, get server reply and send it */
const char *body = belle_sip_message_get_body((belle_sip_message_t *)event->response);
/* TODO Check that the transfer has not been cancelled, note this shall be removed once the belle sip API will provide a cancel request as we shall never reach this part if the transfer is actually cancelled */
if (msg->http_request == NULL) {
return;
/* if we have an encryption key for the file, we must insert it into the message */
if (msg->file_transfer_information->key != NULL) {
@ -230,10 +243,6 @@ static void linphone_chat_message_process_response_from_post_file(void *data, co
} else { /* no encryption key, transfer in plain, just copy the message sent by server */
msg->message = ms_strdup(body);
}
linphone_content_uninit(msg->file_transfer_information);
ms_free(msg->file_transfer_information);
msg->file_transfer_information = NULL;
msg->content_type = ms_strdup("application/vnd.gsma.rcs-ft-http+xml");
_linphone_chat_room_send_message(msg->chat_room, msg);
}
@ -286,44 +295,59 @@ bool_t linphone_core_chat_enabled(const LinphoneCore *lc){
/**
* Returns an list of chat rooms
* @param lc #LinphoneCore object
* @return A list of #LinphoneChatRoom
* @param[in] lc #LinphoneCore object
* @return \mslist{LinphoneChatRoom}
**/
MSList* linphone_core_get_chat_rooms(LinphoneCore *lc) {
return lc->chatrooms;
}
/**
* Create a new chat room for messaging from a sip uri like sip:joe@sip.linphone.org
* @param lc #LinphoneCore object
* @param to destination address for messages
* @return #LinphoneChatRoom where messaging can take place.
*/
LinphoneChatRoom * linphone_core_create_chat_room(LinphoneCore *lc, const char *to){
LinphoneAddress *parsed_url=NULL;
static bool_t linphone_chat_room_matches(LinphoneChatRoom *cr, const LinphoneAddress *from){
return linphone_address_weak_equal(cr->peer_url,from);
}
if ((parsed_url=linphone_core_interpret_url(lc,to))!=NULL){
LinphoneChatRoom *cr=ms_new0(LinphoneChatRoom,1);
cr->lc=lc;
cr->peer=linphone_address_as_string(parsed_url);
cr->peer_url=parsed_url;
lc->chatrooms=ms_list_append(lc->chatrooms,(void *)cr);
return cr;
static void _linphone_chat_room_destroy(LinphoneChatRoom *obj);
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneChatRoom);
BELLE_SIP_INSTANCIATE_VPTR(LinphoneChatRoom, belle_sip_object_t,
(belle_sip_object_destroy_t)_linphone_chat_room_destroy,
NULL, // clone
NULL, // marshal
FALSE
);
static LinphoneChatRoom * _linphone_core_create_chat_room(LinphoneCore *lc, LinphoneAddress *addr) {
LinphoneChatRoom *cr = belle_sip_object_new(LinphoneChatRoom);
cr->lc = lc;
cr->peer = linphone_address_as_string(addr);
cr->peer_url = addr;
lc->chatrooms = ms_list_append(lc->chatrooms, (void *)cr);
return cr;
}
static LinphoneChatRoom * _linphone_core_create_chat_room_from_url(LinphoneCore *lc, const char *to) {
LinphoneAddress *parsed_url = NULL;
if ((parsed_url = linphone_core_interpret_url(lc, to)) != NULL) {
return _linphone_core_create_chat_room(lc, parsed_url);
}
return NULL;
}
bool_t linphone_chat_room_matches(LinphoneChatRoom *cr, const LinphoneAddress *from){
return linphone_address_weak_equal(cr->peer_url,from);
LinphoneChatRoom * _linphone_core_get_chat_room(LinphoneCore *lc, const LinphoneAddress *addr){
LinphoneChatRoom *cr=NULL;
MSList *elem;
for(elem=lc->chatrooms;elem!=NULL;elem=ms_list_next(elem)){
cr=(LinphoneChatRoom*)elem->data;
if (linphone_chat_room_matches(cr,addr)){
break;
}
cr=NULL;
}
return cr;
}
/**
* Create a new chat room for messaging from a sip uri like sip:joe@sip.linphone.org if not already existing, else return exisiting one
* @param lc #LinphoneCore object
* @param to destination address for messages
* @return #LinphoneChatRoom where messaging can take place.
*/
LinphoneChatRoom* linphone_core_get_or_create_chat_room(LinphoneCore* lc, const char* to) {
static LinphoneChatRoom * _linphone_core_get_or_create_chat_room(LinphoneCore* lc, const char* to) {
LinphoneAddress *to_addr=linphone_core_interpret_url(lc,to);
LinphoneChatRoom *ret;
@ -331,17 +355,64 @@ LinphoneChatRoom* linphone_core_get_or_create_chat_room(LinphoneCore* lc, const
ms_error("linphone_core_get_or_create_chat_room(): Cannot make a valid address with %s",to);
return NULL;
}
ret=linphone_core_get_chat_room(lc,to_addr);
ret=_linphone_core_get_chat_room(lc,to_addr);
linphone_address_destroy(to_addr);
if (!ret){
ret=linphone_core_create_chat_room(lc,to);
ret=_linphone_core_create_chat_room_from_url(lc,to);
}
return ret;
}
/**
* Create a new chat room for messaging from a sip uri like sip:joe@sip.linphone.org if not already existing, else return exisiting one
* @param lc #LinphoneCore object
* @param to destination address for messages
* @return #LinphoneChatRoom where messaging can take place.
* @deprecated Use linphone_core_get_chat_room() or linphone_core_get_chat_room_from_uri() instead.
*/
LinphoneChatRoom* linphone_core_get_or_create_chat_room(LinphoneCore* lc, const char* to) {
return _linphone_core_get_or_create_chat_room(lc, to);
}
/**
* Create a new chat room for messaging from a sip uri like sip:joe@sip.linphone.org
* @param lc #LinphoneCore object
* @param to destination address for messages
* @return #LinphoneChatRoom where messaging can take place.
* @deprecated Use linphone_core_get_chat_room() or linphone_core_get_chat_room_from_uri() instead.
*/
LinphoneChatRoom * linphone_core_create_chat_room(LinphoneCore *lc, const char *to) {
return _linphone_core_get_or_create_chat_room(lc, to);
}
/**
* Get a chat room whose peer is the supplied address. If it does not exist yet, it will be created.
* @param lc the linphone core
* @param addr a linphone address.
* @returns #LinphoneChatRoom where messaging can take place.
**/
LinphoneChatRoom *linphone_core_get_chat_room(LinphoneCore *lc, const LinphoneAddress *addr){
LinphoneChatRoom *ret = _linphone_core_get_chat_room(lc, addr);
if (!ret) {
ret = _linphone_core_create_chat_room(lc, linphone_address_clone(addr));
}
return ret;
}
/**
* Get a chat room for messaging from a sip uri like sip:joe@sip.linphone.org. If it does not exist yet, it will be created.
* @param lc The linphone core
* @param to The destination address for messages.
* @returns #LinphoneChatRoom where messaging can take place.
**/
LinphoneChatRoom * linphone_core_get_chat_room_from_uri(LinphoneCore *lc, const char *to) {
return _linphone_core_get_or_create_chat_room(lc, to);
}
static void linphone_chat_room_delete_composing_idle_timer(LinphoneChatRoom *cr) {
if (cr->composing_idle_timer) {
sal_cancel_timer(cr->lc->sal, cr->composing_idle_timer);
if(cr->lc->sal)
sal_cancel_timer(cr->lc->sal, cr->composing_idle_timer);
belle_sip_object_unref(cr->composing_idle_timer);
cr->composing_idle_timer = NULL;
}
@ -349,7 +420,8 @@ static void linphone_chat_room_delete_composing_idle_timer(LinphoneChatRoom *cr)
static void linphone_chat_room_delete_composing_refresh_timer(LinphoneChatRoom *cr) {
if (cr->composing_refresh_timer) {
sal_cancel_timer(cr->lc->sal, cr->composing_refresh_timer);
if(cr->lc->sal)
sal_cancel_timer(cr->lc->sal, cr->composing_refresh_timer);
belle_sip_object_unref(cr->composing_refresh_timer);
cr->composing_refresh_timer = NULL;
}
@ -357,28 +429,55 @@ static void linphone_chat_room_delete_composing_refresh_timer(LinphoneChatRoom *
static void linphone_chat_room_delete_remote_composing_refresh_timer(LinphoneChatRoom *cr) {
if (cr->remote_composing_refresh_timer) {
sal_cancel_timer(cr->lc->sal, cr->remote_composing_refresh_timer);
if(cr->lc->sal)
sal_cancel_timer(cr->lc->sal, cr->remote_composing_refresh_timer);
belle_sip_object_unref(cr->remote_composing_refresh_timer);
cr->remote_composing_refresh_timer = NULL;
}
}
/**
* Destroy a LinphoneChatRoom.
* @param cr #LinphoneChatRoom object
*/
void linphone_chat_room_destroy(LinphoneChatRoom *cr){
LinphoneCore *lc=cr->lc;
static void _linphone_chat_room_destroy(LinphoneChatRoom *cr){
ms_list_free_with_data(cr->transient_messages, (void (*)(void*))linphone_chat_message_unref);
linphone_chat_room_delete_composing_idle_timer(cr);
linphone_chat_room_delete_composing_refresh_timer(cr);
linphone_chat_room_delete_remote_composing_refresh_timer(cr);
lc->chatrooms=ms_list_remove(lc->chatrooms,(void *) cr);
if (cr->lc != NULL) {
cr->lc->chatrooms=ms_list_remove(cr->lc->chatrooms,(void *) cr);
}
linphone_address_destroy(cr->peer_url);
ms_free(cr->peer);
ms_free(cr);
}
/**
* Destroy a LinphoneChatRoom.
* @param cr #LinphoneChatRoom object
* @deprecated Use linphone_chat_room_unref() instead.
*/
void linphone_chat_room_destroy(LinphoneChatRoom *cr) {
linphone_chat_room_unref(cr);
}
void linphone_chat_room_release(LinphoneChatRoom *cr) {
cr->lc = NULL;
linphone_chat_room_unref(cr);
}
LinphoneChatRoom * linphone_chat_room_ref(LinphoneChatRoom *cr) {
belle_sip_object_ref(cr);
return cr;
}
void linphone_chat_room_unref(LinphoneChatRoom *cr) {
belle_sip_object_unref(cr);
}
void * linphone_chat_room_get_user_data(const LinphoneChatRoom *cr) {
return cr->user_data;
}
void linphone_chat_room_set_user_data(LinphoneChatRoom *cr, void *ud) {
cr->user_data = ud;
}
static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatMessage* msg){
@ -389,7 +488,7 @@ static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatM
time_t t=time(NULL);
linphone_chat_message_ref(msg);
/* Check if we shall upload a file to a server */
if (msg->file_transfer_information != NULL) {
if (msg->file_transfer_information != NULL && msg->content_type == NULL) {
/* open a transaction with the server and send an empty request(RCS5.1 section 3.5.4.8.3.1) */
belle_http_request_listener_callbacks_t cbs={0};
belle_http_request_listener_t *l;
@ -404,9 +503,10 @@ static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatM
NULL,
NULL);
cbs.process_response=linphone_chat_message_process_response_from_post_file;
cbs.process_io_error=process_io_error;
cbs.process_auth_requested=process_auth_requested;
cbs.process_io_error=process_io_error_upload;
cbs.process_auth_requested=process_auth_requested_upload;
l=belle_http_request_listener_create_from_callbacks(&cbs,msg); /* give msg to listener to be able to start the actual file upload when server answer a 204 No content */
msg->http_request = req; /* keep a reference on the request to be able to cancel it */
belle_http_provider_send_request(cr->lc->http_provider,req,l);
linphone_chat_message_unref(msg);
return;
@ -487,31 +587,10 @@ void linphone_chat_room_send_message(LinphoneChatRoom *cr, const char *msg) {
void linphone_chat_room_message_received(LinphoneChatRoom *cr, LinphoneCore *lc, LinphoneChatMessage *msg){
if (msg->message)
//legacy API
if (lc->vtable.text_received!=NULL) lc->vtable.text_received(lc, cr, msg->from, msg->message);
if (lc->vtable.message_received!=NULL) lc->vtable.message_received(lc, cr,msg);
if (cr->lc->vtable.is_composing_received != NULL) {
cr->remote_is_composing = LinphoneIsComposingIdle;
cr->lc->vtable.is_composing_received(cr->lc, cr);
}
}
/**
* Retrieve an existing chat room whose peer is the supplied address, if exists.
* @param lc the linphone core
* @param addr a linphone address.
* @returns the matching chatroom, or NULL if no such chatroom exists.
**/
LinphoneChatRoom *linphone_core_get_chat_room(LinphoneCore *lc, const LinphoneAddress *addr){
LinphoneChatRoom *cr=NULL;
MSList *elem;
for(elem=lc->chatrooms;elem!=NULL;elem=ms_list_next(elem)){
cr=(LinphoneChatRoom*)elem->data;
if (linphone_chat_room_matches(cr,addr)){
break;
}
cr=NULL;
}
return cr;
linphone_core_notify_text_message_received(lc, cr, msg->from, msg->message);
linphone_core_notify_message_received(lc, cr,msg);
cr->remote_is_composing = LinphoneIsComposingIdle;
linphone_core_notify_is_composing_received(cr->lc, cr);
}
void linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessage *sal_msg){
@ -529,8 +608,7 @@ void linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessag
/* create a new chat room */
cr=linphone_core_create_chat_room(lc,cleanfrom);
}
if (sal_msg->content_type != NULL) { /* content_type field is, for now, used only for rcs file transfer bu twe shall strcmp it with "application/vnd.gsma.rcs-ft-http+xml" */
if (sal_msg->content_type != NULL) { /* content_type field is, for now, used only for rcs file transfer but we shall strcmp it with "application/vnd.gsma.rcs-ft-http+xml" */
xmlChar *file_url = NULL;
xmlDocPtr xmlMessageBody;
xmlNodePtr cur;
@ -623,6 +701,7 @@ void linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessag
linphone_address_destroy(addr);
msg->storage_id=linphone_chat_message_store(msg);
linphone_chat_room_message_received(cr,lc,msg);
linphone_chat_message_unref(msg);
ms_free(cleanfrom);
}
@ -631,8 +710,7 @@ static int linphone_chat_room_remote_refresh_composing_expired(void *data, unsig
belle_sip_object_unref(cr->remote_composing_refresh_timer);
cr->remote_composing_refresh_timer = NULL;
cr->remote_is_composing = LinphoneIsComposingIdle;
if (cr->lc->vtable.is_composing_received != NULL)
cr->lc->vtable.is_composing_received(cr->lc, cr);
linphone_core_notify_is_composing_received(cr->lc, cr);
return BELLE_SIP_STOP;
}
@ -677,8 +755,7 @@ static void process_im_is_composing_notification(LinphoneChatRoom *cr, xmlparsin
}
cr->remote_is_composing = state;
if (cr->lc->vtable.is_composing_received != NULL)
cr->lc->vtable.is_composing_received(cr->lc, cr);
linphone_core_notify_is_composing_received(cr->lc, cr);
}
}
@ -720,20 +797,6 @@ LinphoneCore* linphone_chat_room_get_core(LinphoneChatRoom *cr){
return cr->lc;
}
/**
* Assign a user pointer to the chat room.
**/
void linphone_chat_room_set_user_data(LinphoneChatRoom *cr, void * ud){
cr->user_data=ud;
}
/**
* Retrieve the user pointer associated with the chat room.
**/
void * linphone_chat_room_get_user_data(LinphoneChatRoom *cr){
return cr->user_data;
}
/**
* get peer address \link linphone_core_create_chat_room() associated to \endlink this #LinphoneChatRoom
* @param cr #LinphoneChatRoom object
@ -756,6 +819,7 @@ LinphoneChatMessage* linphone_chat_room_create_message(LinphoneChatRoom *cr, con
msg->is_read=TRUE;
msg->content_type = NULL; /* this property is used only when transfering file */
msg->file_transfer_information = NULL; /* this property is used only when transfering file */
msg->http_request = NULL;
return msg;
}
@ -945,6 +1009,7 @@ const char* linphone_chat_message_state_to_string(const LinphoneChatMessageState
case LinphoneChatMessageStateInProgress:return "LinphoneChatMessageStateInProgress";
case LinphoneChatMessageStateDelivered:return "LinphoneChatMessageStateDelivered";
case LinphoneChatMessageStateNotDelivered:return "LinphoneChatMessageStateNotDelivered";
case LinphoneChatMessageStateFileTransferError:return "LinphoneChatMessageStateFileTransferError";
default: return "Unknown state";
}
@ -1047,22 +1112,22 @@ static void on_recv_body(belle_sip_user_body_handler_t *bh, belle_sip_message_t
}
LinphoneChatMessage* chatMsg=(LinphoneChatMessage *)data;
LinphoneCore *lc = chatMsg->chat_room->lc;
/* TODO: while belle sip doesn't implement the cancel http request method, test if a request is still linked to the message before forwarding the data to callback */
if (chatMsg->http_request == NULL) {
return;
if (chatMsg->file_transfer_information->key != NULL) { /* we have a key, we must decrypt the file */
/* get data from callback to a plainBuffer */
char *plainBuffer = (char *)malloc(size);
lime_decryptFile(&(chatMsg->file_transfer_information->cryptoContext), chatMsg->file_transfer_information->key, size, plainBuffer, (char *)buffer);
/* call back given by application level */
if (lc->vtable.file_transfer_received != NULL) {
lc->vtable.file_transfer_received(lc, chatMsg, chatMsg->file_transfer_information, plainBuffer, size);
}
linphone_core_notify_file_transfer_rec(lc, chatMsg, chatMsg->file_transfer_information, plainBuffer, size);
free(plainBuffer);
} else { /* regular file, no deciphering */
/* call back given by application level */
if (lc->vtable.file_transfer_received != NULL) {
lc->vtable.file_transfer_received(lc, chatMsg, chatMsg->file_transfer_information, (char *)buffer, size);
}
linphone_core_notify_file_transfer_recd(lc, chatMsg, chatMsg->file_transfer_information, (char *)buffer, size);
}
return;
}
@ -1131,9 +1196,7 @@ static void linphone_chat_process_response_from_get_file(void *data, const belle
lime_decryptFile(&(chatMsg->file_transfer_information->cryptoContext), NULL, 0, NULL, NULL);
}
/* file downloaded succesfully, call again the callback with size at zero */
if (lc->vtable.file_transfer_received != NULL) {
lc->vtable.file_transfer_received(lc, chatMsg, chatMsg->file_transfer_information, NULL, 0);
}
linphone_core_notify_file_transfer_recv(lc, chatMsg, chatMsg->file_transfer_information, NULL, 0);
}
}
}
@ -1142,8 +1205,9 @@ static void linphone_chat_process_response_from_get_file(void *data, const belle
* Start the download of the file from remote server
*
* @param message #LinphoneChatMessage
* @param status_cb LinphoneChatMessageStateChangeCb status callback invoked when file is downloaded or could not be downloaded
*/
void linphone_chat_message_start_file_download(const LinphoneChatMessage *message) {
void linphone_chat_message_start_file_download(LinphoneChatMessage *message, LinphoneChatMessageStateChangedCb status_cb) {
belle_http_request_listener_callbacks_t cbs={0};
belle_http_request_listener_t *l;
belle_generic_uri_t *uri;
@ -1162,47 +1226,66 @@ void linphone_chat_message_start_file_download(const LinphoneChatMessage *messag
cbs.process_response_headers=linphone_chat_process_response_headers_from_get_file;
cbs.process_response=linphone_chat_process_response_from_get_file;
cbs.process_io_error=process_io_error;
cbs.process_auth_requested=process_auth_requested;
cbs.process_io_error=process_io_error_download;
cbs.process_auth_requested=process_auth_requested_download;
l=belle_http_request_listener_create_from_callbacks(&cbs, (void *)message);
belle_sip_object_data_set(BELLE_SIP_OBJECT(req),"message",(void *)message,NULL);
message->http_request = req; /* keep a reference on the request to be able to cancel the download */
message->cb = status_cb;
message->state = LinphoneChatMessageStateInProgress; /* start the download, status is In Progress */
belle_http_provider_send_request(message->chat_room->lc->http_provider,req,l);
}
/**
* Cancel an ongoing file transfer attached to this message.(upload or download)
* @param msg #LinphoneChatMessage
*/
void linphone_chat_room_cancel_file_transfer(LinphoneChatMessage *msg) {
ms_message("Cancelled file transfer %s - msg [%p] chat room[%p]", (msg->external_body_url==NULL)?msg->chat_room->lc->file_transfer_server:msg->external_body_url, msg, msg->chat_room);
/* TODO: here we shall call the cancel http request from bellesip API when it is available passing msg->http_request */
/* waiting for this API, just set to NULL the reference to the request in the message and any request */
msg->http_request = NULL;
if (msg->cb) {
msg->cb(msg, LinphoneChatMessageStateNotDelivered, msg->chat_room->lc);
}
}
/**
* Set origin of the message
*@param message #LinphoneChatMessage obj
*@param from #LinphoneAddress origin of this message (copied)
* @param[in] message #LinphoneChatMessage obj
* @param[in] from #LinphoneAddress origin of this message (copied)
*/
void linphone_chat_message_set_from(LinphoneChatMessage* message, const LinphoneAddress* from) {
void linphone_chat_message_set_from_address(LinphoneChatMessage* message, const LinphoneAddress* from) {
if(message->from) linphone_address_destroy(message->from);
message->from=linphone_address_clone(from);
}
/**
* Get origin of the message
*@param message #LinphoneChatMessage obj
*@return #LinphoneAddress
* @param[in] message #LinphoneChatMessage obj
* @return #LinphoneAddress
*/
const LinphoneAddress* linphone_chat_message_get_from(const LinphoneChatMessage* message) {
const LinphoneAddress* linphone_chat_message_get_from_address(const LinphoneChatMessage* message) {
return message->from;
}
/**
* Set destination of the message
*@param message #LinphoneChatMessage obj
*@param to #LinphoneAddress destination of this message (copied)
* @param[in] message #LinphoneChatMessage obj
* @param[in] to #LinphoneAddress destination of this message (copied)
*/
void linphone_chat_message_set_to(LinphoneChatMessage* message, const LinphoneAddress* to) {
void linphone_chat_message_set_to_address(LinphoneChatMessage* message, const LinphoneAddress* to) {
if(message->to) linphone_address_destroy(message->to);
message->to=linphone_address_clone(to);
}
/**
* Get destination of the message
*@param message #LinphoneChatMessage obj
*@return #LinphoneAddress
* @param[in] message #LinphoneChatMessage obj
* @return #LinphoneAddress
*/
const LinphoneAddress* linphone_chat_message_get_to(const LinphoneChatMessage* message){
const LinphoneAddress* linphone_chat_message_get_to_address(const LinphoneChatMessage* message){
if (message->to) return message->to;
if (message->dir==LinphoneChatMessageOutgoing){
return message->chat_room->peer_url;
@ -1341,6 +1424,7 @@ static void _linphone_chat_message_destroy(LinphoneChatMessage* msg) {
linphone_content_uninit(msg->file_transfer_information);
ms_free(msg->file_transfer_information);
}
ms_message("LinphoneChatMessage [%p] destroyed.",msg);
}
@ -1395,11 +1479,10 @@ LinphoneChatMessage* linphone_chat_room_create_file_transfer_message(LinphoneCha
linphone_chat_message_set_to(msg, linphone_chat_room_get_peer_address(cr));
linphone_chat_message_set_from(msg, linphone_address_new(linphone_core_get_identity(cr->lc)));
msg->content_type=NULL; /* this will be set to application/vnd.gsma.rcs-ft-http+xml when we will transfer the xml reply from server to the peers */
msg->http_request=NULL; /* this will store the http request during file upload to the server */
return msg;
}
/**
* @}
*/

View file

@ -41,6 +41,7 @@ static void conference_check_init(LinphoneConference *ctx, int samplerate){
MSAudioConferenceParams params;
params.samplerate=samplerate;
ctx->conf=ms_audio_conference_new(&params);
ctx->terminated=FALSE;
}
}
@ -74,7 +75,7 @@ void linphone_core_conference_check_uninit(LinphoneCore *lc){
if (ctx->conf){
int remote_count=remote_participants_count(ctx);
ms_message("conference_check_uninit(): size=%i",linphone_conference_get_size(ctx));
if (remote_count==1){
if (remote_count==1 && !ctx->terminated){
convert_conference_to_call(lc);
}
if (remote_count==0){
@ -98,7 +99,7 @@ void linphone_call_add_to_conf(LinphoneCall *call, bool_t muted){
LinphoneCore *lc=call->core;
LinphoneConference *conf=&lc->conf_ctx;
MSAudioEndpoint *ep;
call->params.has_video = FALSE;
call->params->has_video = FALSE;
call->camera_enabled = FALSE;
ep=ms_audio_endpoint_get_from_stream(call->audiostream,TRUE);
ms_audio_conference_add_member(conf->conf,ep);
@ -184,15 +185,15 @@ float linphone_core_get_conference_local_input_volume(LinphoneCore *lc){
int linphone_core_add_to_conference(LinphoneCore *lc, LinphoneCall *call){
LinphoneConference *conf=&lc->conf_ctx;
if (call->current_params.in_conference){
if (call->current_params->in_conference){
ms_error("Already in conference");
return -1;
}
conference_check_init(&lc->conf_ctx, lp_config_get_int(lc->config, "sound","conference_rate",16000));
if (call->state==LinphoneCallPaused){
call->params.in_conference=TRUE;
call->params.has_video=FALSE;
call->params->in_conference=TRUE;
call->params->has_video=FALSE;
linphone_core_resume_call(lc,call);
}else if (call->state==LinphoneCallStreamsRunning){
LinphoneCallParams *params=linphone_call_params_copy(linphone_call_get_current_params(call));
@ -222,8 +223,8 @@ static int remove_from_conference(LinphoneCore *lc, LinphoneCall *call, bool_t a
int err=0;
char *str;
if (!call->current_params.in_conference){
if (call->params.in_conference){
if (!call->current_params->in_conference){
if (call->params->in_conference){
ms_warning("Not (yet) in conference, be patient");
return -1;
}else{
@ -231,7 +232,7 @@ static int remove_from_conference(LinphoneCore *lc, LinphoneCall *call, bool_t a
return -1;
}
}
call->params.in_conference=FALSE;
call->params->in_conference=FALSE;
str=linphone_call_get_remote_address_as_string(call);
ms_message("%s will be removed from conference", str);
@ -251,7 +252,6 @@ static int remove_from_conference(LinphoneCore *lc, LinphoneCall *call, bool_t a
ms_message("Pausing call to actually remove from conference");
err=_linphone_core_pause_call(lc,call);
}
return err;
}
@ -267,7 +267,7 @@ static int convert_conference_to_call(LinphoneCore *lc){
while (calls) {
LinphoneCall *rc=(LinphoneCall*)calls->data;
calls=calls->next;
if (rc->params.in_conference) { // not using current_param
if (rc->params->in_conference) { // not using current_param
bool_t active_after_removed=linphone_core_is_in_conference(lc);
err=remove_from_conference(lc, rc, active_after_removed);
break;
@ -370,7 +370,7 @@ int linphone_core_add_all_to_conference(LinphoneCore *lc) {
while (calls) {
LinphoneCall *call=(LinphoneCall*)calls->data;
calls=calls->next;
if (!call->current_params.in_conference) {
if (!call->current_params->in_conference) {
linphone_core_add_to_conference(lc, call);
}
}
@ -388,10 +388,13 @@ int linphone_core_add_all_to_conference(LinphoneCore *lc) {
**/
int linphone_core_terminate_conference(LinphoneCore *lc) {
MSList *calls=lc->calls;
LinphoneConference *conf=&lc->conf_ctx;
conf->terminated=TRUE;
while (calls) {
LinphoneCall *call=(LinphoneCall*)calls->data;
calls=calls->next;
if (call->current_params.in_conference) {
if (call->current_params->in_conference) {
linphone_core_terminate_call(lc, call);
}
}

View file

@ -89,13 +89,10 @@ LinphoneEvent *linphone_event_new_with_out_of_dialog_op(LinphoneCore *lc, SalOp
}
void linphone_event_set_state(LinphoneEvent *lev, LinphoneSubscriptionState state){
LinphoneCore *lc=lev->lc;
if (lev->subscription_state!=state){
ms_message("LinphoneEvent [%p] moving to subscription state %s",lev,linphone_subscription_state_to_string(state));
lev->subscription_state=state;
if (lc->vtable.subscription_state_changed){
lc->vtable.subscription_state_changed(lev->lc,lev,state);
}
linphone_core_notify_subscription_state_changed(lev->lc,lev,state);
if (state==LinphoneSubscriptionTerminated){
linphone_event_unref(lev);
}
@ -103,13 +100,10 @@ void linphone_event_set_state(LinphoneEvent *lev, LinphoneSubscriptionState stat
}
void linphone_event_set_publish_state(LinphoneEvent *lev, LinphonePublishState state){
LinphoneCore *lc=lev->lc;
if (lev->publish_state!=state){
ms_message("LinphoneEvent [%p] moving to publish state %s",lev,linphone_publish_state_to_string(state));
lev->publish_state=state;
if (lc->vtable.publish_state_changed){
lc->vtable.publish_state_changed(lev->lc,lev,state);
}
linphone_core_notify_publish_state_changed(lev->lc,lev,state);
switch(state){
case LinphonePublishCleared:
linphone_event_unref(lev);

View file

@ -253,8 +253,7 @@ static void linphone_friend_invalidate_subscription(LinphoneFriend *lf){
linphone_presence_model_unref(lf->presence);
}
lf->presence = linphone_presence_model_new_with_activity(LinphonePresenceActivityOffline,"unknown activity");
if (lc->vtable.notify_presence_received)
lc->vtable.notify_presence_received(lc,lf);
linphone_core_notify_notify_presence_received(lc,lf);
}
lf->initial_subscribes_sent=FALSE;
}

39
coreapi/gitversion.cmake Normal file
View file

@ -0,0 +1,39 @@
############################################################################
# CMakeLists.txt
# Copyright (C) 2014 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.
#
############################################################################
if(GIT_EXECUTABLE)
execute_process(
COMMAND ${GIT_EXECUTABLE} describe --always
WORKING_DIRECTORY ${WORK_DIR}
OUTPUT_VARIABLE GIT_REVISION
OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND ${CMAKE_COMMAND} -E echo "#define LIBLINPHONE_GIT_VERSION \"${GIT_REVISION}\""
OUTPUT_FILE ${OUTPUT_DIR}/liblinphone_gitversion.h
)
else()
execute_process(
COMMAND ${CMAKE_COMMAND} -E echo "#define LIBLINPHONE_GIT_VERSION \"unknown\""
OUTPUT_FILE ${OUTPUT_DIR}/liblinphone_gitversion.h
)
endif()

View file

@ -0,0 +1,45 @@
############################################################################
# CMakeLists.txt
# Copyright (C) 2014 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.
#
############################################################################
find_package(Doxygen)
if(DOXYGEN_FOUND)
if(DOXYGEN_DOT_FOUND)
set(top_srcdir ${CMAKE_SOURCE_DIR})
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
file(GLOB DOC_INPUT_FILES
[^.]*.c
[^.]*.dox
../[^.]*.h
../[^.]*.c
)
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/doc/html/index.html"
COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile ${DOC_INPUT_FILES}
)
add_custom_target(doc ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/doc/html/index.html")
install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/doc/html" "${CMAKE_CURRENT_BINARY_DIR}/doc/xml"
DESTINATION "${CMAKE_INSTALL_PREFIX}/share/doc/linphone-${LINPHONE_VERSION}")
else()
message(WARNING "The dot program is needed to generate the linphone documentation. You can get it from http://www.graphviz.org/.")
endif()
endif()

View file

@ -34,7 +34,7 @@ DETAILS_AT_TOP = NO
INHERIT_DOCS = YES
DISTRIBUTE_GROUP_DOC = NO
TAB_SIZE = 8
ALIASES =
ALIASES = mslist{1}="A list of \ref \1 objects. \xmlonly <mslist>\1</mslist> \endxmlonly"
OPTIMIZE_OUTPUT_FOR_C = YES
OPTIMIZE_OUTPUT_JAVA = NO
SUBGROUPING = YES

View file

@ -1,7 +1,7 @@
EXTRA_DIST=Doxyfile.in doxygen.dox
SOURCES=doxygen.dox $(top_srcdir)/coreapi/help/*.c $(top_srcdir)/coreapi/*.c $(top_srcdir)/coreapi/*.h
SOURCES=doxygen.dox $(top_srcdir)/coreapi/help/*.c $(top_srcdir)/coreapi/*.c $(top_srcdir)/coreapi/*.h
# html doc
@ -84,6 +84,7 @@ filetransfer_LDADD=$(helloworld_LDADD)
AM_CFLAGS=\
-I$(top_srcdir)/coreapi \
$(STRICT_OPTIONS) \
$(STRICT_OPTIONS_CC) \
-DIN_LINPHONE \
$(ORTP_CFLAGS) \
$(MEDIASTREAMER_CFLAGS) \
@ -98,4 +99,4 @@ AM_CFLAGS=\
tutodir=$(datadir)/tutorials/linphone
tuto_DATA=$(LINPHONE_TUTOS)
endif
endif

View file

@ -1,7 +1,7 @@
/*
buddy_status
Copyright (C) 2010 Belledonne Communications SARL
Copyright (C) 2010 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
@ -73,7 +73,7 @@ static void new_subscription_requested (LinphoneCore *lc, LinphoneFriend *frien
* Registration state notification callback
*/
static void registration_state_changed(struct _LinphoneCore *lc, LinphoneProxyConfig *cfg, LinphoneRegistrationState cstate, const char *message){
printf("New registration state %s for user id [%s] at proxy [%s]\n"
printf("New registration state %s for user id [%s] at proxy [%s]"
,linphone_registration_state_to_string(cstate)
,linphone_proxy_config_get_identity(cfg)
,linphone_proxy_config_get_addr(cfg));
@ -87,6 +87,8 @@ int main(int argc, char *argv[]){
char* identity=NULL;
char* password=NULL;
LinphoneFriend* my_friend=NULL;
/* takes sip uri identity from the command line arguments */
if (argc>1){
dest_friend=argv[1];
@ -104,7 +106,7 @@ int main(int argc, char *argv[]){
#ifdef DEBUG
linphone_core_enable_logs(NULL); /*enable liblinphone logs.*/
#endif
/*
/*
Fill the LinphoneCoreVTable with application callbacks.
All are optional. Here we only use the both notify_presence_received and new_subscription_requested callbacks
in order to get notifications about friend status.
@ -123,11 +125,11 @@ int main(int argc, char *argv[]){
LinphoneProxyConfig* proxy_cfg = linphone_proxy_config_new();
/*parse identity*/
LinphoneAddress *from = linphone_address_new(identity);
LinphoneAuthInfo *info;
if (from==NULL){
printf("%s not a valid sip uri, must be like sip:toto@sip.linphone.org \n",identity);
goto end;
}
LinphoneAuthInfo *info;
if (password!=NULL){
info=linphone_auth_info_new(linphone_address_get_username(from),NULL,password,NULL,NULL,NULL); /*create authentication structure from identity*/
linphone_core_add_auth_info(lc,info); /*add authentication info to LinphoneCore*/
@ -152,7 +154,6 @@ int main(int argc, char *argv[]){
while( running && linphone_proxy_config_get_state(proxy_cfg) == LinphoneRegistrationProgress);
}
LinphoneFriend* my_friend=NULL;
if (dest_friend) {
my_friend = linphone_friend_new_with_address(dest_friend); /*creates friend object from dest*/

View file

@ -1,7 +1,7 @@
/*
linphone
Copyright (C) 2010 Belledonne Communications SARL
Copyright (C) 2010 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
@ -55,7 +55,7 @@ int main(int argc, char *argv[]){
LinphoneCoreVTable vtable={0};
char* dest_friend=NULL;
LinphoneChatRoom* chat_room;
/* takes sip uri identity from the command line arguments */
if (argc>1){
@ -67,7 +67,7 @@ int main(int argc, char *argv[]){
#ifdef DEBUG
linphone_core_enable_logs(NULL); /*enable liblinphone logs.*/
#endif
/*
/*
Fill the LinphoneCoreVTable with application callbacks.
All are optional. Here we only use the text_received callback
in order to get notifications about incoming message.
@ -81,7 +81,7 @@ int main(int argc, char *argv[]){
/*Next step is to create a chat root*/
LinphoneChatRoom* chat_room = linphone_core_create_chat_room(lc,dest_friend);
chat_room = linphone_core_create_chat_room(lc,dest_friend);
linphone_chat_room_send_message(chat_room,"Hello world"); /*sending message*/

View file

@ -1,7 +1,7 @@
/*
linphone
Copyright (C) 2010 Belledonne Communications SARL
Copyright (C) 2010 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
@ -114,16 +114,6 @@ static void file_transfer_send(LinphoneCore *lc, LinphoneChatMessage *message,
}
/*
* Call back called when a message is received
*/
static void message_received(LinphoneCore *lc, LinphoneChatRoom *cr, LinphoneChatMessage *msg) {
const LinphoneContent *file_transfer_info = linphone_chat_message_get_file_transfer_information(msg);
printf ("Do you really want to download %s (size %ld)?[Y/n]\nOk, let's go\n", file_transfer_info->name, (long int)file_transfer_info->size);
linphone_chat_message_start_file_download(msg);
}
/*
* Call back to get delivery status of a message
* */
@ -135,6 +125,16 @@ static void linphone_file_transfer_state_changed(LinphoneChatMessage* msg,Linpho
free(to);
}
/*
* Call back called when a message is received
*/
static void message_received(LinphoneCore *lc, LinphoneChatRoom *cr, LinphoneChatMessage *msg) {
const LinphoneContent *file_transfer_info = linphone_chat_message_get_file_transfer_information(msg);
printf ("Do you really want to download %s (size %ld)?[Y/n]\nOk, let's go\n", file_transfer_info->name, (long int)file_transfer_info->size);
linphone_chat_message_start_file_download(msg, linphone_file_transfer_state_changed);
}
LinphoneCore *lc;
int main(int argc, char *argv[]){
@ -143,6 +143,10 @@ int main(int argc, char *argv[]){
const char* dest_friend=NULL;
int i;
const char* big_file_content="big file";
LinphoneChatRoom* chat_room;
LinphoneContent content;
LinphoneChatMessage* chat_message;
/*seting dummy file content to something*/
for (i=0;i<sizeof(big_file);i+=strlen(big_file_content))
memcpy(big_file+i, big_file_content, strlen(big_file_content));
@ -155,13 +159,13 @@ int main(int argc, char *argv[]){
#ifdef DEBUG
linphone_core_enable_logs(NULL); /*enable liblinphone logs.*/
#endif
/*
/*
Fill the LinphoneCoreVTable with application callbacks.
All are optional. Here we only use the file_transfer_received callback
in order to get notifications about incoming file receive, file_transfer_send to feed file to be transfered
and file_transfer_progress_indication to print progress.
*/
vtable.file_transfer_received=file_transfer_received;
vtable.file_transfer_recv=file_transfer_received;
vtable.file_transfer_send=file_transfer_send;
vtable.file_transfer_progress_indication=file_transfer_progress_indication;
vtable.message_received=message_received;
@ -182,9 +186,8 @@ int main(int argc, char *argv[]){
/*Next step is to create a chat room*/
LinphoneChatRoom* chat_room = linphone_core_create_chat_room(lc,dest_friend);
chat_room = linphone_core_create_chat_room(lc,dest_friend);
LinphoneContent content;
memset(&content,0,sizeof(content));
content.type="text";
content.subtype="plain";
@ -192,7 +195,10 @@ int main(int argc, char *argv[]){
content.name = "bigfile.txt";
/*now create a chat message with custom content*/
LinphoneChatMessage* chat_message = linphone_chat_room_create_file_transfer_message(chat_room,&content);
chat_message = linphone_chat_room_create_file_transfer_message(chat_room,&content);
if (chat_message == NULL) {
printf("returned message is null\n");
}
/*initiating file transfer*/
linphone_chat_room_send_message2(chat_room, chat_message, linphone_file_transfer_state_changed, NULL);

View file

@ -18,6 +18,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.linphone.core.tutorials;
import java.nio.ByteBuffer;
import org.linphone.core.LinphoneAddress;
import org.linphone.core.LinphoneCall;
import org.linphone.core.LinphoneCall.State;
@ -165,7 +167,7 @@ public class TutorialBuddyStatus implements LinphoneCoreListener {
}
// create proxy config
LinphoneProxyConfig proxyCfg = lcFactory.createProxyConfig(mySipAddress, domain, null, true);
LinphoneProxyConfig proxyCfg = lc.createProxyConfig(mySipAddress, domain, null, true);
proxyCfg.enablePublish(true);
lc.addProxyConfig(proxyCfg); // add it to linphone
lc.setDefaultProxyConfig(proxyCfg);
@ -300,5 +302,24 @@ public class TutorialBuddyStatus implements LinphoneCoreListener {
}
@Override
public void fileTransferProgressIndication(LinphoneCore lc,
LinphoneChatMessage message, LinphoneContent content, int progress) {
// TODO Auto-generated method stub
}
@Override
public void fileTransferRecv(LinphoneCore lc, LinphoneChatMessage message,
LinphoneContent content, byte[] buffer, int size) {
// TODO Auto-generated method stub
}
@Override
public int fileTransferSend(LinphoneCore lc, LinphoneChatMessage message,
LinphoneContent content, ByteBuffer buffer, int size) {
// TODO Auto-generated method stub
return 0;
}
}

View file

@ -18,6 +18,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.linphone.core.tutorials;
import java.nio.ByteBuffer;
import org.linphone.core.LinphoneAddress;
import org.linphone.core.LinphoneCall;
import org.linphone.core.LinphoneCall.State;
@ -218,5 +220,26 @@ public class TutorialChatRoom implements LinphoneCoreListener, LinphoneChatMessa
}
@Override
public void fileTransferProgressIndication(LinphoneCore lc,
LinphoneChatMessage message, LinphoneContent content, int progress) {
// TODO Auto-generated method stub
}
@Override
public void fileTransferRecv(LinphoneCore lc, LinphoneChatMessage message,
LinphoneContent content, byte[] buffer, int size) {
// TODO Auto-generated method stub
}
@Override
public int fileTransferSend(LinphoneCore lc, LinphoneChatMessage message,
LinphoneContent content, ByteBuffer buffer, int size) {
// TODO Auto-generated method stub
return 0;
}
}

View file

@ -18,6 +18,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.linphone.core.tutorials;
import java.nio.ByteBuffer;
import org.linphone.core.LinphoneAddress;
import org.linphone.core.LinphoneCall;
import org.linphone.core.LinphoneCallStats;
@ -220,5 +222,26 @@ public class TutorialHelloWorld implements LinphoneCoreListener {
}
@Override
public void fileTransferProgressIndication(LinphoneCore lc,
LinphoneChatMessage message, LinphoneContent content, int progress) {
// TODO Auto-generated method stub
}
@Override
public void fileTransferRecv(LinphoneCore lc, LinphoneChatMessage message,
LinphoneContent content, byte[] buffer, int size) {
// TODO Auto-generated method stub
}
@Override
public int fileTransferSend(LinphoneCore lc, LinphoneChatMessage message,
LinphoneContent content, ByteBuffer buffer, int size) {
// TODO Auto-generated method stub
return 0;
}
}

View file

@ -18,14 +18,19 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.linphone.core.tutorials;
import java.nio.ByteBuffer;
import org.linphone.core.LinphoneAddress;
import org.linphone.core.LinphoneCall;
import org.linphone.core.LinphoneCall.State;
import org.linphone.core.LinphoneCallStats;
import org.linphone.core.LinphoneChatMessage;
import org.linphone.core.LinphoneChatRoom;
import org.linphone.core.LinphoneContent;
import org.linphone.core.LinphoneCore;
import org.linphone.core.LinphoneCore.EcCalibratorStatus;
import org.linphone.core.LinphoneCore.GlobalState;
import org.linphone.core.LinphoneCore.RegistrationState;
import org.linphone.core.LinphoneCore.RemoteProvisioningState;
import org.linphone.core.LinphoneCoreException;
import org.linphone.core.LinphoneCoreFactory;
@ -34,9 +39,6 @@ import org.linphone.core.LinphoneEvent;
import org.linphone.core.LinphoneFriend;
import org.linphone.core.LinphoneInfoMessage;
import org.linphone.core.LinphoneProxyConfig;
import org.linphone.core.LinphoneCall.State;
import org.linphone.core.LinphoneCore.GlobalState;
import org.linphone.core.LinphoneCore.RegistrationState;
import org.linphone.core.PublishState;
import org.linphone.core.SubscriptionState;
@ -136,7 +138,7 @@ public class TutorialRegistration implements LinphoneCoreListener {
}
// create proxy config
LinphoneProxyConfig proxyCfg = lcFactory.createProxyConfig(sipAddress, domain, null, true);
LinphoneProxyConfig proxyCfg = lc.createProxyConfig(sipAddress, domain, null, true);
proxyCfg.setExpires(2000);
lc.addProxyConfig(proxyCfg); // add it to linphone
lc.setDefaultProxyConfig(proxyCfg);
@ -251,6 +253,27 @@ public class TutorialRegistration implements LinphoneCoreListener {
}
@Override
public void fileTransferProgressIndication(LinphoneCore lc,
LinphoneChatMessage message, LinphoneContent content, int progress) {
// TODO Auto-generated method stub
}
@Override
public void fileTransferRecv(LinphoneCore lc, LinphoneChatMessage message,
LinphoneContent content, byte[] buffer, int size) {
// TODO Auto-generated method stub
}
@Override
public int fileTransferSend(LinphoneCore lc, LinphoneChatMessage message,
LinphoneContent content, ByteBuffer buffer, int size) {
// TODO Auto-generated method stub
return 0;
}
}

View file

@ -1,7 +1,7 @@
/*
linphone
Copyright (C) 2013 Belledonne Communications SARL
Copyright (C) 2013 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
@ -89,6 +89,10 @@ int main(int argc, char *argv[]){
char* identity=NULL;
char* password=NULL;
int i;
LinphoneProxyConfig* proxy_cfg;
LinphoneAddress *from;
LinphoneAuthInfo *info;
const char* server_addr;
/* takes sip uri identity from the command line arguments */
if (argc>1){
@ -105,7 +109,7 @@ int main(int argc, char *argv[]){
#ifdef DEBUG
linphone_core_enable_logs(NULL); /*enable liblinphone logs.*/
#endif
/*
/*
Fill the LinphoneCoreVTable with application callbacks.
All are optional. Here we only use the registration_state_changed callbacks
in order to get notifications about the progress of the registration.
@ -118,30 +122,28 @@ int main(int argc, char *argv[]){
*/
lc=linphone_core_new(&vtable,NULL,NULL,data);
LinphoneProxyConfig* proxy_cfg;
/*create proxy config*/
proxy_cfg = linphone_proxy_config_new();
/*parse identity*/
LinphoneAddress *from = linphone_address_new(identity);
from = linphone_address_new(identity);
if (from==NULL){
printf("%s not a valid sip uri, must be like sip:toto@sip.linphone.org \n",identity);
goto end;
}
LinphoneAuthInfo *info;
if (password!=NULL){
info=linphone_auth_info_new(linphone_address_get_username(from),NULL,password,NULL,NULL,NULL); /*create authentication structure from identity*/
linphone_core_add_auth_info(lc,info); /*add authentication info to LinphoneCore*/
}
if (password!=NULL){
info=linphone_auth_info_new(linphone_address_get_username(from),NULL,password,NULL,NULL,NULL); /*create authentication structure from identity*/
linphone_core_add_auth_info(lc,info); /*add authentication info to LinphoneCore*/
}
// configure proxy entries
linphone_proxy_config_set_identity(proxy_cfg,identity); /*set identity with user name and domain*/
const char* server_addr = linphone_address_get_domain(from); /*extract domain address from identity*/
linphone_proxy_config_set_server_addr(proxy_cfg,server_addr); /* we assume domain = proxy server address*/
linphone_proxy_config_enable_register(proxy_cfg,TRUE); /*activate registration for this proxy config*/
linphone_address_destroy(from); /*release resource*/
// configure proxy entries
linphone_proxy_config_set_identity(proxy_cfg,identity); /*set identity with user name and domain*/
server_addr = linphone_address_get_domain(from); /*extract domain address from identity*/
linphone_proxy_config_set_server_addr(proxy_cfg,server_addr); /* we assume domain = proxy server address*/
linphone_proxy_config_enable_register(proxy_cfg,TRUE); /*activate registration for this proxy config*/
linphone_address_destroy(from); /*release resource*/
linphone_core_add_proxy_config(lc,proxy_cfg); /*add proxy config to linphone core*/
linphone_core_set_default_proxy(lc,proxy_cfg); /*set to default proxy*/
linphone_core_add_proxy_config(lc,proxy_cfg); /*add proxy config to linphone core*/
linphone_core_set_default_proxy(lc,proxy_cfg); /*set to default proxy*/
i=0;
/* main loop for receiving notifications and doing background linphonecore work: */
@ -163,7 +165,7 @@ int main(int argc, char *argv[]){
linphone_proxy_config_edit(proxy_cfg); /*start editing proxy configuration*/
linphone_proxy_config_enable_register(proxy_cfg,FALSE); /*de-activate registration for this proxy config*/
linphone_proxy_config_done(proxy_cfg); /*initiate REGISTER with expire = 0*/
if (data->ev){
linphone_event_terminate(data->ev);
}

View file

@ -1,7 +1,7 @@
/*
linphone
Copyright (C) 2010 Belledonne Communications SARL
Copyright (C) 2010 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
@ -60,9 +60,13 @@ static void registration_state_changed(struct _LinphoneCore *lc, LinphoneProxyCo
LinphoneCore *lc;
int main(int argc, char *argv[]){
LinphoneCoreVTable vtable={0};
LinphoneProxyConfig* proxy_cfg;
LinphoneAddress *from;
LinphoneAuthInfo *info;
char* identity=NULL;
char* password=NULL;
const char* server_addr;
/* takes sip uri identity from the command line arguments */
if (argc>1){
@ -79,7 +83,7 @@ int main(int argc, char *argv[]){
#ifdef DEBUG
linphone_core_enable_logs(NULL); /*enable liblinphone logs.*/
#endif
/*
/*
Fill the LinphoneCoreVTable with application callbacks.
All are optional. Here we only use the registration_state_changed callbacks
in order to get notifications about the progress of the registration.
@ -91,30 +95,28 @@ int main(int argc, char *argv[]){
*/
lc=linphone_core_new(&vtable,NULL,NULL,NULL);
LinphoneProxyConfig* proxy_cfg;
/*create proxy config*/
proxy_cfg = linphone_proxy_config_new();
/*parse identity*/
LinphoneAddress *from = linphone_address_new(identity);
from = linphone_address_new(identity);
if (from==NULL){
printf("%s not a valid sip uri, must be like sip:toto@sip.linphone.org \n",identity);
goto end;
}
LinphoneAuthInfo *info;
if (password!=NULL){
info=linphone_auth_info_new(linphone_address_get_username(from),NULL,password,NULL,NULL,NULL); /*create authentication structure from identity*/
linphone_core_add_auth_info(lc,info); /*add authentication info to LinphoneCore*/
}
if (password!=NULL){
info=linphone_auth_info_new(linphone_address_get_username(from),NULL,password,NULL,NULL,NULL); /*create authentication structure from identity*/
linphone_core_add_auth_info(lc,info); /*add authentication info to LinphoneCore*/
}
// configure proxy entries
linphone_proxy_config_set_identity(proxy_cfg,identity); /*set identity with user name and domain*/
const char* server_addr = linphone_address_get_domain(from); /*extract domain address from identity*/
linphone_proxy_config_set_server_addr(proxy_cfg,server_addr); /* we assume domain = proxy server address*/
linphone_proxy_config_enable_register(proxy_cfg,TRUE); /*activate registration for this proxy config*/
linphone_address_destroy(from); /*release resource*/
// configure proxy entries
linphone_proxy_config_set_identity(proxy_cfg,identity); /*set identity with user name and domain*/
server_addr = linphone_address_get_domain(from); /*extract domain address from identity*/
linphone_proxy_config_set_server_addr(proxy_cfg,server_addr); /* we assume domain = proxy server address*/
linphone_proxy_config_enable_register(proxy_cfg,TRUE); /*activate registration for this proxy config*/
linphone_address_destroy(from); /*release resource*/
linphone_core_add_proxy_config(lc,proxy_cfg); /*add proxy config to linphone core*/
linphone_core_set_default_proxy(lc,proxy_cfg); /*set to default proxy*/
linphone_core_add_proxy_config(lc,proxy_cfg); /*add proxy config to linphone core*/
linphone_core_set_default_proxy(lc,proxy_cfg); /*set to default proxy*/
/* main loop for receiving notifications and doing background linphonecore work: */

View file

@ -205,8 +205,7 @@ void linphone_core_notify_info_message(LinphoneCore* lc,SalOp *op, const SalBody
LinphoneInfoMessage *info=ms_new0(LinphoneInfoMessage,1);
info->headers=sal_custom_header_clone(sal_op_get_recv_custom_header(op));
if (body) linphone_content_copy_from_sal_body(&info->content,body);
if (lc->vtable.info_received)
lc->vtable.info_received(lc,call,info);
linphone_core_notify_info_received(lc,call,info);
linphone_info_message_destroy(info);
}
}

View file

@ -567,10 +567,11 @@ LinphoneLDAPContactProvider*linphone_ldap_contact_provider_create(LinphoneCore*
belle_sip_object_unref(obj);
obj = NULL;
} else {
int ret;
linphone_dictionary_foreach( config, linphone_ldap_contact_provider_config_dump_cb, 0 );
linphone_ldap_contact_provider_loadconfig(obj, config);
int ret = ldap_initialize(&(obj->ld),obj->server);
ret = ldap_initialize(&(obj->ld),obj->server);
if( ret != LDAP_SUCCESS ){
ms_error( "Problem initializing ldap on url '%s': %s", obj->server, ldap_err2string(ret));
@ -617,9 +618,10 @@ static int linphone_ldap_request_entry_compare_strong(const void*a, const void*
static inline LinphoneLDAPContactSearch* linphone_ldap_contact_provider_request_search( LinphoneLDAPContactProvider* obj, int msgid )
{
LinphoneLDAPContactSearch dummy = {};
MSList* list_entry;
dummy.msgid = msgid;
MSList* list_entry = ms_list_find_custom(obj->requests, linphone_ldap_request_entry_compare_weak, &dummy);
list_entry = ms_list_find_custom(obj->requests, linphone_ldap_request_entry_compare_weak, &dummy);
if( list_entry ) return list_entry->data;
else return NULL;
}
@ -680,13 +682,14 @@ static LinphoneLDAPContactSearch* linphone_ldap_contact_provider_begin_search (
void* cb_data )
{
bool_t connected = obj->connected;
LinphoneLDAPContactSearch* request;
// if we're not yet connected, bind
if( !connected ) {
if( !obj->bind_thread ) linphone_ldap_contact_provider_bind(obj);
}
LinphoneLDAPContactSearch* request = linphone_ldap_contact_search_create( obj, predicate, cb, cb_data );
request = linphone_ldap_contact_search_create( obj, predicate, cb, cb_data );
if( connected ){
int ret = linphone_ldap_contact_provider_perform_search(obj, request);
@ -711,6 +714,7 @@ static LinphoneLDAPContactSearch* linphone_ldap_contact_provider_begin_search (
static int linphone_ldap_contact_provider_marshal(LinphoneLDAPContactProvider* obj, char* buff, size_t buff_size, size_t *offset)
{
belle_sip_error_code error = BELLE_SIP_OK;
char **attr;
error = belle_sip_snprintf(buff, buff_size, offset, "ld:%p,\n", obj->ld);
if(error!= BELLE_SIP_OK) return error;
@ -741,7 +745,7 @@ static int linphone_ldap_contact_provider_marshal(LinphoneLDAPContactProvider* o
obj->sip_attr, obj->name_attr);
if(error!= BELLE_SIP_OK) return error;
char **attr = obj->attributes;
attr = obj->attributes;
while( *attr ){
error = belle_sip_snprintf(buff, buff_size, offset, "- %s\n", *attr);
if(error!= BELLE_SIP_OK) return error;

View file

@ -29,14 +29,18 @@
#include "private.h"
#include "lpconfig.h"
LinphoneTunnel* linphone_core_get_tunnel(LinphoneCore *lc){
static const char *_tunnel_mode_str[3] = { "disable", "enable", "auto" };
static LinphoneTunnelMode _string_to_tunnel_mode(const char *string);
static const char *_tunnel_mode_to_string(LinphoneTunnelMode mode);
LinphoneTunnel* linphone_core_get_tunnel(const LinphoneCore *lc){
return lc->tunnel;
}
struct _LinphoneTunnel {
belledonnecomm::TunnelManager *manager;
MSList *config_list;
bool_t auto_detect_enabled;
};
extern "C" LinphoneTunnel* linphone_core_tunnel_new(LinphoneCore *lc){
@ -45,31 +49,37 @@ extern "C" LinphoneTunnel* linphone_core_tunnel_new(LinphoneCore *lc){
return tunnel;
}
static inline belledonnecomm::TunnelManager *bcTunnel(LinphoneTunnel *tunnel){
belledonnecomm::TunnelManager *bcTunnel(const LinphoneTunnel *tunnel){
return tunnel->manager;
}
static inline _LpConfig *config(LinphoneTunnel *tunnel){
static inline _LpConfig *config(const LinphoneTunnel *tunnel){
return tunnel->manager->getLinphoneCore()->config;
}
void linphone_tunnel_destroy(LinphoneTunnel *tunnel){
delete tunnel->manager;
ms_list_free_with_data(tunnel->config_list, (void (*)(void *))linphone_tunnel_config_destroy);
ms_free(tunnel);
}
static char *linphone_tunnel_config_to_string(const LinphoneTunnelConfig *tunnel_config) {
char *str = NULL;
if(linphone_tunnel_config_get_remote_udp_mirror_port(tunnel_config) != -1) {
str = ms_strdup_printf("%s:%d:%d:%d",
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",
linphone_tunnel_config_get_host(tunnel_config),
linphone_tunnel_config_get_port(tunnel_config));
const char *host = linphone_tunnel_config_get_host(tunnel_config);
if(host != NULL) {
if(linphone_tunnel_config_get_remote_udp_mirror_port(tunnel_config) != -1) {
str = ms_strdup_printf("%s:%d:%d:%d",
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",
linphone_tunnel_config_get_host(tunnel_config),
linphone_tunnel_config_get_port(tunnel_config));
}
}
return str;
}
@ -97,12 +107,12 @@ static LinphoneTunnelConfig *linphone_tunnel_config_from_string(const char *str)
break;
case 3:
delay = atoi(pch);
break;
break;
default:
// Abort
pos = 0;
break;
}
++pos;
pch = strtok(NULL, ":");
@ -118,26 +128,27 @@ static LinphoneTunnelConfig *linphone_tunnel_config_from_string(const char *str)
if(pos == 4) {
linphone_tunnel_config_set_delay(tunnel_config, delay);
}
ms_free(dstr);
ms_free(dstr);
return tunnel_config;
}
static void linphone_tunnel_save_config(LinphoneTunnel *tunnel) {
MSList *elem = tunnel->config_list;
static void linphone_tunnel_save_config(const LinphoneTunnel *tunnel) {
MSList *elem = NULL;
char *tmp = NULL, *old_tmp = NULL, *tc_str = NULL;
while(elem != NULL) {
for(elem = tunnel->config_list; elem != NULL; elem = elem->next) {
LinphoneTunnelConfig *tunnel_config = (LinphoneTunnelConfig *)elem->data;
tc_str = linphone_tunnel_config_to_string(tunnel_config);
if(tmp != NULL) {
old_tmp = tmp;
tmp = ms_strdup_printf("%s %s", old_tmp, tc_str);
ms_free(old_tmp);
ms_free(tc_str);
} else {
tmp = tc_str;
if(tc_str != NULL) {
if(tmp != NULL) {
old_tmp = tmp;
tmp = ms_strdup_printf("%s %s", old_tmp, tc_str);
ms_free(old_tmp);
ms_free(tc_str);
} else {
tmp = tc_str;
}
}
elem = elem->next;
}
lp_config_set_string(config(tunnel), "tunnel", "server_addresses", tmp);
if(tmp != NULL) {
@ -148,12 +159,12 @@ static void linphone_tunnel_save_config(LinphoneTunnel *tunnel) {
static void linphone_tunnel_add_server_intern(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tunnel_config) {
if(linphone_tunnel_config_get_remote_udp_mirror_port(tunnel_config) == -1) {
bcTunnel(tunnel)->addServer(linphone_tunnel_config_get_host(tunnel_config),
bcTunnel(tunnel)->addServer(linphone_tunnel_config_get_host(tunnel_config),
linphone_tunnel_config_get_port(tunnel_config));
} else {
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),
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);
@ -205,38 +216,37 @@ void linphone_tunnel_remove_server(LinphoneTunnel *tunnel, LinphoneTunnelConfig
MSList *elem = ms_list_find(tunnel->config_list, tunnel_config);
if(elem != NULL) {
tunnel->config_list = ms_list_remove(tunnel->config_list, tunnel_config);
linphone_tunnel_config_destroy(tunnel_config);
linphone_tunnel_config_destroy(tunnel_config);
linphone_tunnel_refresh_config(tunnel);
linphone_tunnel_save_config(tunnel);
}
}
}
const MSList *linphone_tunnel_get_servers(LinphoneTunnel *tunnel){
const MSList *linphone_tunnel_get_servers(const LinphoneTunnel *tunnel){
return tunnel->config_list;
}
void linphone_tunnel_clean_servers(LinphoneTunnel *tunnel){
bcTunnel(tunnel)->cleanServers();
/* Free the list */
ms_list_for_each(tunnel->config_list, (void (*)(void *))linphone_tunnel_config_destroy);
tunnel->config_list = ms_list_free(tunnel->config_list);
ms_list_free_with_data(tunnel->config_list, (void (*)(void *))linphone_tunnel_config_destroy);
tunnel->config_list = NULL;
linphone_tunnel_save_config(tunnel);
}
void linphone_tunnel_enable(LinphoneTunnel *tunnel, bool_t enabled){
tunnel->auto_detect_enabled = FALSE;
lp_config_set_int(config(tunnel),"tunnel","enabled",(int)enabled);
bcTunnel(tunnel)->enable(enabled);
void linphone_tunnel_set_mode(LinphoneTunnel *tunnel, LinphoneTunnelMode mode){
lp_config_set_string(config(tunnel),"tunnel","mode", _tunnel_mode_to_string(mode));
bcTunnel(tunnel)->setMode(mode);
}
bool_t linphone_tunnel_enabled(LinphoneTunnel *tunnel){
return bcTunnel(tunnel)->isEnabled();
LinphoneTunnelMode linphone_tunnel_get_mode(const LinphoneTunnel *tunnel){
return bcTunnel(tunnel)->getMode();
}
bool_t linphone_tunnel_connected(LinphoneTunnel *tunnel){
return bcTunnel(tunnel)->isReady();
bool_t linphone_tunnel_connected(const LinphoneTunnel *tunnel){
return bcTunnel(tunnel)->isConnected();
}
static OrtpLogFunc tunnelOrtpLogHandler=NULL;
@ -312,27 +322,65 @@ void linphone_tunnel_reconnect(LinphoneTunnel *tunnel){
bcTunnel(tunnel)->reconnect();
}
void linphone_tunnel_auto_detect(LinphoneTunnel *tunnel){
tunnel->auto_detect_enabled = TRUE;
bcTunnel(tunnel)->autoDetect();
void linphone_tunnel_enable_sip(LinphoneTunnel *tunnel, bool_t enable) {
bcTunnel(tunnel)->tunnelizeSipPackets(enable);
lp_config_set_int(config(tunnel), "tunnel", "sip", (enable ? TRUE : FALSE));
}
bool_t linphone_tunnel_auto_detect_enabled(LinphoneTunnel *tunnel) {
return tunnel->auto_detect_enabled;
bool_t linphone_tunnel_sip_enabled(const LinphoneTunnel *tunnel) {
return bcTunnel(tunnel)->tunnelizeSipPacketsEnabled() ? TRUE : FALSE;
}
static void my_ortp_logv(OrtpLogLevel level, const char *fmt, va_list args){
ortp_logv(level,fmt,args);
}
static LinphoneTunnelMode _string_to_tunnel_mode(const char *string) {
if(string != NULL) {
int i;
for(i=0; i<3 && strcmp(string, _tunnel_mode_str[i]) != 0; i++);
if(i<3) {
return (LinphoneTunnelMode)i;
} else {
ms_error("Invalid tunnel mode '%s'", string);
return LinphoneTunnelModeDisable;
}
} else {
return LinphoneTunnelModeDisable;
}
}
static const char *_tunnel_mode_to_string(LinphoneTunnelMode mode) {
return _tunnel_mode_str[mode];
}
/**
* Startup tunnel using configuration.
* Called internally from linphonecore at startup.
*/
void linphone_tunnel_configure(LinphoneTunnel *tunnel){
bool_t enabled=(bool_t)lp_config_get_int(config(tunnel),"tunnel","enabled",FALSE);
LinphoneTunnelMode mode = _string_to_tunnel_mode(lp_config_get_string(config(tunnel), "tunnel", "mode", NULL));
bool_t tunnelizeSIPPackets = (bool_t)lp_config_get_int(config(tunnel), "tunnel", "sip", TRUE);
linphone_tunnel_enable_logs_with_handler(tunnel,TRUE,my_ortp_logv);
linphone_tunnel_load_config(tunnel);
linphone_tunnel_enable(tunnel, enabled);
linphone_tunnel_enable_sip(tunnel, tunnelizeSIPPackets);
linphone_tunnel_set_mode(tunnel, mode);
}
/* Deprecated functions */
void linphone_tunnel_enable(LinphoneTunnel *tunnel, bool_t enabled) {
if(enabled) linphone_tunnel_set_mode(tunnel, LinphoneTunnelModeEnable);
else linphone_tunnel_set_mode(tunnel, LinphoneTunnelModeDisable);
}
bool_t linphone_tunnel_enabled(const LinphoneTunnel *tunnel) {
return linphone_tunnel_get_mode(tunnel) == LinphoneTunnelModeEnable;
}
void linphone_tunnel_auto_detect(LinphoneTunnel *tunnel) {
linphone_tunnel_set_mode(tunnel, LinphoneTunnelModeAuto);
}
bool_t linphone_tunnel_auto_detect_enabled(LinphoneTunnel *tunnel) {
return linphone_tunnel_get_mode(tunnel) == LinphoneTunnelModeAuto;
}

View file

@ -50,10 +50,16 @@ extern "C"
typedef struct _LinphoneTunnelConfig LinphoneTunnelConfig;
typedef enum _LinphoneTunnelMode {
LinphoneTunnelModeDisable,
LinphoneTunnelModeEnable,
LinphoneTunnelModeAuto
} LinphoneTunnelMode;
/**
* Create a new tunnel configuration
*/
LINPHONE_PUBLIC LinphoneTunnelConfig *linphone_tunnel_config_new();
LINPHONE_PUBLIC LinphoneTunnelConfig *linphone_tunnel_config_new(void);
/**
* Set address of server.
@ -131,51 +137,49 @@ LINPHONE_PUBLIC void linphone_tunnel_config_destroy(LinphoneTunnelConfig *tunnel
LINPHONE_PUBLIC void linphone_tunnel_add_server(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tunnel_config);
/**
* Remove tunnel server configuration
*
* @brief Remove tunnel server configuration
* @param tunnel object
* @param tunnel_config object
*/
LINPHONE_PUBLIC void linphone_tunnel_remove_server(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tunnel_config);
/**
* @param tunnel object
* returns a string of space separated list of host:port of tunnel server addresses
* */
LINPHONE_PUBLIC const MSList *linphone_tunnel_get_servers(LinphoneTunnel *tunnel);
* @brief Get added servers
* @param tunnel A LinphoneTunnel object
* @return A list of LinphoneTunnelConfig objects
*/
LINPHONE_PUBLIC const MSList *linphone_tunnel_get_servers(const LinphoneTunnel *tunnel);
/**
* @param tunnel object
* Removes all tunnel server address previously entered with addServer()
* @brief Removes all tunnel server address previously entered with addServer()
* @param tunnel A LinphoneTunnel object
**/
LINPHONE_PUBLIC void linphone_tunnel_clean_servers(LinphoneTunnel *tunnel);
/**
* Sets whether tunneling of SIP and RTP is required.
* @brief Set tunnel mode
* The tunnel mode can be 'enable', 'disable' or 'auto'
* If the mode is set to 'auto', the tunnel manager will try to established an RTP session
* with the tunnel server on the UdpMirrorPort. If the connection fail, the tunnel is automatically
* activated whereas the tunnel is automatically disabled if the connection succeed.
* @param tunnel object
* @param enabled If true enter in tunneled mode, if false exits from tunneled mode.
* The TunnelManager takes care of refreshing SIP registration when switching on or off the tunneled mode.
*
* @param mode See #LinphoneTunnelMode
**/
LINPHONE_PUBLIC void linphone_tunnel_enable(LinphoneTunnel *tunnel, bool_t enabled);
LINPHONE_PUBLIC void linphone_tunnel_set_mode(LinphoneTunnel *tunnel, LinphoneTunnelMode mode);
/**
* @param tunnel object
* Returns a boolean indicating whether tunneled operation is enabled.
* @brief Get the tunnel mode
* @param tunnel A LinphoneTunnel object
* @return Return a #LinphoneTunnelMode enumeration
**/
LINPHONE_PUBLIC bool_t linphone_tunnel_enabled(LinphoneTunnel *tunnel);
LINPHONE_PUBLIC LinphoneTunnelMode linphone_tunnel_get_mode(const LinphoneTunnel *tunnel);
/**
* @param tunnel object
* Returns a boolean indicating whether tunnel is connected successfully.
* @brief Check whether the tunnel is connected
* @param tunnel LinphoneTunnel object
* @return True if the tunnel is connected
**/
bool_t linphone_tunnel_connected(LinphoneTunnel *tunnel);
/**
* @param tunnel object
* Returns a boolean indicating whether tunnel is connected successfully.
**/
bool_t linphone_tunnel_connected(LinphoneTunnel *tunnel);
LINPHONE_PUBLIC bool_t linphone_tunnel_connected(const LinphoneTunnel *tunnel);
/**
* @param tunnel object
@ -187,20 +191,18 @@ bool_t linphone_tunnel_connected(LinphoneTunnel *tunnel);
LINPHONE_PUBLIC void linphone_tunnel_reconnect(LinphoneTunnel *tunnel);
/**
* Start tunnel need detection.
* @param tunnel object
* In auto detect mode, the tunnel manager try to establish a real time rtp cummunication with the tunnel server on specified port.
*<br>In case of success, the tunnel is automatically turned off. Otherwise, if no udp commmunication is feasible, tunnel mode is turned on.
*<br> Call this method each time to run the auto detection algorithm
* @brief Set whether SIP packets must be directly sent to a UA or pass through the tunnel
* @param tunnel Tunnel to configure
* @param enable If true, SIP packets shall pass through the tunnel
*/
LINPHONE_PUBLIC void linphone_tunnel_auto_detect(LinphoneTunnel *tunnel);
LINPHONE_PUBLIC void linphone_tunnel_enable_sip(LinphoneTunnel *tunnel, bool_t enable);
/**
* Tells whether tunnel auto detection is enabled.
* @param[in] tunnel LinphoneTunnel object.
* @return TRUE if auto detection is enabled, FALSE otherwise.
* @brief Check whether tunnel is set to transport SIP packets
* @param tunnel Tunnel to check
* @return True, SIP packets shall pass through through tunnel
*/
LINPHONE_PUBLIC bool_t linphone_tunnel_auto_detect_enabled(LinphoneTunnel *tunnel);
LINPHONE_PUBLIC bool_t linphone_tunnel_sip_enabled(const LinphoneTunnel *tunnel);
/**
* Set an optional http proxy to go through when connecting to tunnel server.
@ -222,8 +224,50 @@ LINPHONE_PUBLIC void linphone_tunnel_set_http_proxy(LinphoneTunnel *tunnel, cons
**/
LINPHONE_PUBLIC void linphone_tunnel_get_http_proxy(LinphoneTunnel*tunnel,const char **host, int *port, const char **username, const char **passwd);
/**
* @brief Set authentication info for the http proxy
* @param tunnel LinphoneTunnel object
* @param username User name
* @param passwd Password
*/
LINPHONE_PUBLIC void linphone_tunnel_set_http_proxy_auth_info(LinphoneTunnel*tunnel, const char* username,const char* passwd);
/**
* @deprecated Replaced by linphone_tunnel_set_mode()
* @brief Sets whether tunneling of SIP and RTP is required.
* @param tunnel object
* @param enabled If true enter in tunneled mode, if false exits from tunneled mode.
* The TunnelManager takes care of refreshing SIP registration when switching on or off the tunneled mode.
*
**/
LINPHONE_PUBLIC void linphone_tunnel_enable(LinphoneTunnel *tunnel, bool_t enabled);
/**
* @deprecated Replaced by linphone_tunnel_get_mode()
* @brief Check whether tunnel is enabled
* @param tunnel Tunnel object
* @return Returns a boolean indicating whether tunneled operation is enabled.
**/
LINPHONE_PUBLIC bool_t linphone_tunnel_enabled(const LinphoneTunnel *tunnel);
/**
* @deprecated Replaced by linphone_tunnel_set_mode(LinphoneTunnelModeAuto)
* @brief Start tunnel need detection.
* @param tunnel object
* In auto detect mode, the tunnel manager try to establish a real time rtp cummunication with the tunnel server on specified port.
* <br>In case of success, the tunnel is automatically turned off. Otherwise, if no udp commmunication is feasible, tunnel mode is turned on.
* <br> Call this method each time to run the auto detection algorithm
*/
LINPHONE_PUBLIC void linphone_tunnel_auto_detect(LinphoneTunnel *tunnel);
/**
* @deprecated Replaced by linphone_tunnel_get_mode()
* @brief Tells whether tunnel auto detection is enabled.
* @param[in] tunnel LinphoneTunnel object.
* @return TRUE if auto detection is enabled, FALSE otherwise.
*/
LINPHONE_PUBLIC bool_t linphone_tunnel_auto_detect_enabled(LinphoneTunnel *tunnel);
/**
* @}

View file

@ -29,7 +29,7 @@
#include "lpconfig.h"
LinphoneTunnel* linphone_core_get_tunnel(LinphoneCore *lc){
LinphoneTunnel* linphone_core_get_tunnel(const LinphoneCore *lc){
return lc->tunnel;
}
@ -45,21 +45,21 @@ void linphone_tunnel_add_server(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tu
void linphone_tunnel_remove_server(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tunnel_config){
}
const MSList *linphone_tunnel_get_servers(LinphoneTunnel *tunnel){
const MSList *linphone_tunnel_get_servers(const LinphoneTunnel *tunnel){
return NULL;
}
void linphone_tunnel_clean_servers(LinphoneTunnel *tunnel){
}
void linphone_tunnel_enable(LinphoneTunnel *tunnel, bool_t enabled){
void linphone_tunnel_set_mode(LinphoneTunnel *tunnel, LinphoneTunnelMode mode) {
}
bool_t linphone_tunnel_enabled(LinphoneTunnel *tunnel){
return FALSE;
LinphoneTunnelMode linphone_tunnel_get_mode(const LinphoneTunnel *tunnel){
return LinphoneTunnelModeDisable;
}
bool_t linphone_tunnel_connected(LinphoneTunnel *tunnel){
bool_t linphone_tunnel_connected(const LinphoneTunnel *tunnel){
return FALSE;
}
@ -79,9 +79,14 @@ void linphone_tunnel_get_http_proxy(LinphoneTunnel*tunnel,const char **host, int
void linphone_tunnel_reconnect(LinphoneTunnel *tunnel){
}
void linphone_tunnel_auto_detect(LinphoneTunnel *tunnel){
}
void linphone_tunnel_configure(LinphoneTunnel *tunnel){
}
void linphone_tunnel_enable_sip(LinphoneTunnel *tunnel, bool_t enable) {}
bool_t linphone_tunnel_sip_enabled(const LinphoneTunnel *tunnel) { return FALSE; }
/* Deprecated functions */
void linphone_tunnel_enable(LinphoneTunnel *tunnel, bool_t enabled) {}
bool_t linphone_tunnel_enabled(const LinphoneTunnel *tunnel) { return FALSE; }
void linphone_tunnel_auto_detect(LinphoneTunnel *tunnel) {}
bool_t linphone_tunnel_auto_detect_enabled(LinphoneTunnel *tunnel) { return FALSE; }

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -24,6 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "mediastreamer2/mscommon.h"
#include "mediastreamer2/msvideo.h"
#include "mediastreamer2/mediastream.h"
#include "mediastreamer2/bitratecontrol.h"
#ifdef IN_LINPHONE
#include "sipsetup.h"
@ -249,86 +250,61 @@ LinphoneDictionary* lp_config_section_to_dict( const LpConfig* lpconfig, const c
void lp_config_load_dict_to_section( LpConfig* lpconfig, const char* section, const LinphoneDictionary* dict);
#ifdef IN_LINPHONE
#include "linphonefriend.h"
#include "event.h"
#else
#include "linphone/linphonefriend.h"
#include "linphone/event.h"
#endif
LINPHONE_PUBLIC LinphoneAddress * linphone_address_new(const char *addr);
LINPHONE_PUBLIC LinphoneAddress * linphone_address_clone(const LinphoneAddress *addr);
LINPHONE_PUBLIC LinphoneAddress * linphone_address_ref(LinphoneAddress *addr);
LINPHONE_PUBLIC void linphone_address_unref(LinphoneAddress *addr);
LINPHONE_PUBLIC const char *linphone_address_get_scheme(const LinphoneAddress *u);
LINPHONE_PUBLIC const char *linphone_address_get_display_name(const LinphoneAddress* u);
LINPHONE_PUBLIC const char *linphone_address_get_username(const LinphoneAddress *u);
LINPHONE_PUBLIC const char *linphone_address_get_domain(const LinphoneAddress *u);
LINPHONE_PUBLIC int linphone_address_get_port(const LinphoneAddress *u);
LINPHONE_PUBLIC void linphone_address_set_display_name(LinphoneAddress *u, const char *display_name);
LINPHONE_PUBLIC void linphone_address_set_username(LinphoneAddress *uri, const char *username);
LINPHONE_PUBLIC void linphone_address_set_domain(LinphoneAddress *uri, const char *host);
LINPHONE_PUBLIC void linphone_address_set_port(LinphoneAddress *uri, int port);
/*remove tags, params etc... so that it is displayable to the user*/
LINPHONE_PUBLIC void linphone_address_clean(LinphoneAddress *uri);
LINPHONE_PUBLIC bool_t linphone_address_is_secure(const LinphoneAddress *uri);
LINPHONE_PUBLIC LinphoneTransportType linphone_address_get_transport(const LinphoneAddress *uri);
LINPHONE_PUBLIC void linphone_address_set_transport(LinphoneAddress *uri,LinphoneTransportType type);
LINPHONE_PUBLIC char *linphone_address_as_string(const LinphoneAddress *u);
LINPHONE_PUBLIC char *linphone_address_as_string_uri_only(const LinphoneAddress *u);
LINPHONE_PUBLIC bool_t linphone_address_weak_equal(const LinphoneAddress *a1, const LinphoneAddress *a2);
LINPHONE_PUBLIC void linphone_address_destroy(LinphoneAddress *u);
/**
* Create a #LinphoneAddress object by parsing the user supplied address, given as a string.
* @param[in] lc #LinphoneCore object
* @param[in] address String containing the user supplied address
* @return The create #LinphoneAddress object
* @ingroup linphone_address
*/
LINPHONE_PUBLIC LinphoneAddress * linphone_core_create_address(LinphoneCore *lc, const char *address);
struct _SipSetupContext;
/**
* Enum representing the direction of a call.
* @ingroup call_logs
* @addtogroup media_parameters
* @{
**/
enum _LinphoneCallDir {
LinphoneCallOutgoing, /**< outgoing calls*/
LinphoneCallIncoming /**< incoming calls*/
/**
* Object representing an RTP payload type.
*/
typedef PayloadType LinphonePayloadType;
/**
* Get the type of payload.
* @param[in] pt LinphonePayloadType object
* @return The type of payload.
*/
LINPHONE_PUBLIC int linphone_payload_type_get_type(const LinphonePayloadType *pt);
/**
* Get the normal bitrate in bits/s.
* @param[in] pt LinphonePayloadType object
* @return The normal bitrate in bits/s.
*/
LINPHONE_PUBLIC int linphone_payload_type_get_normal_bitrate(const LinphonePayloadType *pt);
/**
* Get the mime type.
* @param[in] pt LinphonePayloadType object
* @return The mime type.
*/
LINPHONE_PUBLIC char * linphone_payload_type_get_mime_type(const LinphonePayloadType *pt);
/**
* Get the number of channels.
* @param[in] pt LinphonePayloadType object
* @return The number of channels.
*/
LINPHONE_PUBLIC int linphone_payload_type_get_channels(const LinphonePayloadType *pt);
/**
* Enum describing RTP AVPF activation modes.
**/
enum _LinphoneAVPFMode{
LinphoneAVPFDefault=-1, /**<Use default value defined at upper level*/
LinphoneAVPFDisabled, /**<AVPF is disabled*/
LinphoneAVPFEnabled /**<AVPF is enabled */
};
/**
* Typedef for enum
* @ingroup call_logs
* Enum describing RTP AVPF activation modes.
**/
typedef enum _LinphoneCallDir LinphoneCallDir;
/**
* Enum representing the status of a call
* @ingroup call_logs
**/
typedef enum _LinphoneCallStatus {
LinphoneCallSuccess, /**< The call was sucessful*/
LinphoneCallAborted, /**< The call was aborted */
LinphoneCallMissed, /**< The call was missed (unanswered)*/
LinphoneCallDeclined /**< The call was declined, either locally or by remote end*/
} LinphoneCallStatus;
/**
* Structure representing a call log.
*
* @ingroup call_logs
*
**/
typedef struct _LinphoneCallLog LinphoneCallLog;
typedef enum _LinphoneAVPFMode LinphoneAVPFMode;
/**
* Enum describing type of media encryption types.
* @ingroup media_parameters
**/
enum _LinphoneMediaEncryption {
LinphoneMediaEncryptionNone, /**< No media encryption is used */
@ -338,122 +314,17 @@ enum _LinphoneMediaEncryption {
/**
* Enum describing type of media encryption types.
* @ingroup media_parameters
**/
typedef enum _LinphoneMediaEncryption LinphoneMediaEncryption;
/**
* Convert enum member to string.
* @ingroup media_parameters
**/
LINPHONE_PUBLIC const char *linphone_media_encryption_to_string(LinphoneMediaEncryption menc);
/*public: */
LINPHONE_PUBLIC LinphoneAddress *linphone_call_log_get_from(LinphoneCallLog *cl);
LINPHONE_PUBLIC LinphoneAddress *linphone_call_log_get_to(LinphoneCallLog *cl);
LINPHONE_PUBLIC LinphoneAddress *linphone_call_log_get_remote_address(LinphoneCallLog *cl);
LINPHONE_PUBLIC LinphoneCallDir linphone_call_log_get_dir(LinphoneCallLog *cl);
LINPHONE_PUBLIC LinphoneCallStatus linphone_call_log_get_status(LinphoneCallLog *cl);
LINPHONE_PUBLIC bool_t linphone_call_log_video_enabled(LinphoneCallLog *cl);
LINPHONE_PUBLIC time_t linphone_call_log_get_start_date(LinphoneCallLog *cl);
LINPHONE_PUBLIC int linphone_call_log_get_duration(LinphoneCallLog *cl);
LINPHONE_PUBLIC float linphone_call_log_get_quality(LinphoneCallLog *cl);
LINPHONE_PUBLIC void linphone_call_log_set_user_pointer(LinphoneCallLog *cl, void *up);
LINPHONE_PUBLIC void *linphone_call_log_get_user_pointer(const LinphoneCallLog *cl);
void linphone_call_log_set_ref_key(LinphoneCallLog *cl, const char *refkey);
const char *linphone_call_log_get_ref_key(const LinphoneCallLog *cl);
LINPHONE_PUBLIC const rtp_stats_t *linphone_call_log_get_local_stats(const LinphoneCallLog *cl);
LINPHONE_PUBLIC const rtp_stats_t *linphone_call_log_get_remote_stats(const LinphoneCallLog *cl);
LINPHONE_PUBLIC const char *linphone_call_log_get_call_id(const LinphoneCallLog *cl);
LINPHONE_PUBLIC char * linphone_call_log_to_str(LinphoneCallLog *cl);
/**
* Private structure definition for LinphoneCallParams.
* @ingroup call_control
* @}
**/
struct _LinphoneCallParams;
/**
* The LinphoneCallParams is an object containing various call related parameters.
* It can be used to retrieve parameters from a currently running call or modify the call's characteristics
* dynamically.
* @ingroup call_control
**/
typedef struct _LinphoneCallParams LinphoneCallParams;
LINPHONE_PUBLIC const PayloadType* linphone_call_params_get_used_audio_codec(const LinphoneCallParams *cp);
LINPHONE_PUBLIC const PayloadType* linphone_call_params_get_used_video_codec(const LinphoneCallParams *cp);
LINPHONE_PUBLIC LinphoneCallParams * linphone_call_params_copy(const LinphoneCallParams *cp);
LINPHONE_PUBLIC void linphone_call_params_enable_video(LinphoneCallParams *cp, bool_t enabled);
LINPHONE_PUBLIC bool_t linphone_call_params_video_enabled(const LinphoneCallParams *cp);
LINPHONE_PUBLIC LinphoneMediaEncryption linphone_call_params_get_media_encryption(const LinphoneCallParams *cp);
LINPHONE_PUBLIC void linphone_call_params_set_media_encryption(LinphoneCallParams *cp, LinphoneMediaEncryption e);
LINPHONE_PUBLIC void linphone_call_params_enable_early_media_sending(LinphoneCallParams *cp, bool_t enabled);
LINPHONE_PUBLIC bool_t linphone_call_params_early_media_sending_enabled(const LinphoneCallParams *cp);
#define linphone_call_params_local_conference_mode linphone_call_params_get_local_conference_mode /* Deprecated */
LINPHONE_PUBLIC bool_t linphone_call_params_get_local_conference_mode(const LinphoneCallParams *cp);
LINPHONE_PUBLIC void linphone_call_params_set_audio_bandwidth_limit(LinphoneCallParams *cp, int bw);
LINPHONE_PUBLIC void linphone_call_params_destroy(LinphoneCallParams *cp);
LINPHONE_PUBLIC bool_t linphone_call_params_low_bandwidth_enabled(const LinphoneCallParams *cp);
LINPHONE_PUBLIC void linphone_call_params_enable_low_bandwidth(LinphoneCallParams *cp, bool_t enabled);
LINPHONE_PUBLIC void linphone_call_params_set_record_file(LinphoneCallParams *cp, const char *path);
LINPHONE_PUBLIC const char *linphone_call_params_get_record_file(const LinphoneCallParams *cp);
LINPHONE_PUBLIC const char *linphone_call_params_get_session_name(const LinphoneCallParams *cp);
LINPHONE_PUBLIC void linphone_call_params_set_session_name(LinphoneCallParams *cp, const char *subject);
/**
* Add a custom SIP header in the INVITE for a call.
* @param[in] params The #LinphoneCallParams to add a custom SIP header to.
* @param[in] header_name The name of the header to add.
* @param[in] header_value The content of the header to add.
* @ingroup call_control
**/
LINPHONE_PUBLIC void linphone_call_params_add_custom_header(LinphoneCallParams *params, const char *header_name, const char *header_value);
/**
* Get a custom SIP header.
* @param[in] params The #LinphoneCallParams to get the custom SIP header from.
* @param[in] header_name The name of the header to get.
* @returns The content of the header or NULL if not found.
* @ingroup call_control
**/
LINPHONE_PUBLIC const char *linphone_call_params_get_custom_header(const LinphoneCallParams *params, const char *header_name);
/**
* Gets the size of the video that is sent.
* @param[in] cp The call parameters for which to get the sent video size.
* @return The sent video size or MS_VIDEO_SIZE_UNKNOWN if not available.
*/
LINPHONE_PUBLIC MSVideoSize linphone_call_params_get_sent_video_size(const LinphoneCallParams *cp);
/**
* Gets the size of the video that is received.
* @param[in] cp The call paramaters for which to get the received video size.
* @return The received video size or MS_VIDEO_SIZE_UNKNOWN if not available.
*/
LINPHONE_PUBLIC MSVideoSize linphone_call_params_get_received_video_size(const LinphoneCallParams *cp);
/**
* Gets the framerate of the video that is sent.
* @param[in] cp The call parameters.
* @return the actual sent framerate in frames per seconds, 0 if not available.
*/
LINPHONE_PUBLIC float linphone_call_params_get_sent_framerate(const LinphoneCallParams *cp);
/**
* Gets the framerate of the video that is received.
* @param[in] cp The call paramaters for which to get the received framerate.
* @return the actual received framerate in frames per seconds, 0 if not available.
*/
LINPHONE_PUBLIC float linphone_call_params_get_received_framerate(const LinphoneCallParams *cp);
/**
* Gets the RTP profile being used.
* @param[in] cp #LinphoneCallParams object
* @returns The RTP profile.
*/
LINPHONE_PUBLIC const char * linphone_call_params_get_rtp_profile(const LinphoneCallParams *cp);
/*
@ -514,8 +385,53 @@ typedef unsigned int LinphonePrivacyMask;
LINPHONE_PUBLIC const char* linphone_privacy_to_string(LinphonePrivacy privacy);
LINPHONE_PUBLIC void linphone_call_params_set_privacy(LinphoneCallParams *params, LinphonePrivacyMask privacy);
LINPHONE_PUBLIC LinphonePrivacyMask linphone_call_params_get_privacy(const LinphoneCallParams *params);
#ifdef IN_LINPHONE
#include "linphonefriend.h"
#include "event.h"
#include "call_log.h"
#include "call_params.h"
#else
#include "linphone/linphonefriend.h"
#include "linphone/event.h"
#include "linphone/call_log.h"
#include "linphone/call_params.h"
#endif
LINPHONE_PUBLIC LinphoneAddress * linphone_address_new(const char *addr);
LINPHONE_PUBLIC LinphoneAddress * linphone_address_clone(const LinphoneAddress *addr);
LINPHONE_PUBLIC LinphoneAddress * linphone_address_ref(LinphoneAddress *addr);
LINPHONE_PUBLIC void linphone_address_unref(LinphoneAddress *addr);
LINPHONE_PUBLIC const char *linphone_address_get_scheme(const LinphoneAddress *u);
LINPHONE_PUBLIC const char *linphone_address_get_display_name(const LinphoneAddress* u);
LINPHONE_PUBLIC const char *linphone_address_get_username(const LinphoneAddress *u);
LINPHONE_PUBLIC const char *linphone_address_get_domain(const LinphoneAddress *u);
LINPHONE_PUBLIC int linphone_address_get_port(const LinphoneAddress *u);
LINPHONE_PUBLIC void linphone_address_set_display_name(LinphoneAddress *u, const char *display_name);
LINPHONE_PUBLIC void linphone_address_set_username(LinphoneAddress *uri, const char *username);
LINPHONE_PUBLIC void linphone_address_set_domain(LinphoneAddress *uri, const char *host);
LINPHONE_PUBLIC void linphone_address_set_port(LinphoneAddress *uri, int port);
/*remove tags, params etc... so that it is displayable to the user*/
LINPHONE_PUBLIC void linphone_address_clean(LinphoneAddress *uri);
LINPHONE_PUBLIC bool_t linphone_address_is_secure(const LinphoneAddress *uri);
LINPHONE_PUBLIC LinphoneTransportType linphone_address_get_transport(const LinphoneAddress *uri);
LINPHONE_PUBLIC void linphone_address_set_transport(LinphoneAddress *uri,LinphoneTransportType type);
LINPHONE_PUBLIC char *linphone_address_as_string(const LinphoneAddress *u);
LINPHONE_PUBLIC char *linphone_address_as_string_uri_only(const LinphoneAddress *u);
LINPHONE_PUBLIC bool_t linphone_address_weak_equal(const LinphoneAddress *a1, const LinphoneAddress *a2);
LINPHONE_PUBLIC void linphone_address_destroy(LinphoneAddress *u);
/**
* Create a #LinphoneAddress object by parsing the user supplied address, given as a string.
* @param[in] lc #LinphoneCore object
* @param[in] address String containing the user supplied address
* @return The create #LinphoneAddress object
* @ingroup linphone_address
*/
LINPHONE_PUBLIC LinphoneAddress * linphone_core_create_address(LinphoneCore *lc, const char *address);
struct _SipSetupContext;
struct _LinphoneInfoMessage;
@ -530,7 +446,6 @@ LINPHONE_PUBLIC void linphone_info_message_add_header(LinphoneInfoMessage *im, c
LINPHONE_PUBLIC const char *linphone_info_message_get_header(const LinphoneInfoMessage *im, const char *name);
LINPHONE_PUBLIC void linphone_info_message_set_content(LinphoneInfoMessage *im, const LinphoneContent *content);
LINPHONE_PUBLIC const LinphoneContent * linphone_info_message_get_content(const LinphoneInfoMessage *im);
LINPHONE_PUBLIC const char *linphone_info_message_get_from(const LinphoneInfoMessage *im);
LINPHONE_PUBLIC void linphone_info_message_destroy(LinphoneInfoMessage *im);
LINPHONE_PUBLIC LinphoneInfoMessage *linphone_info_message_copy(const LinphoneInfoMessage *orig);
@ -652,10 +567,35 @@ LINPHONE_PUBLIC float linphone_call_stats_get_receiver_loss_rate(const LinphoneC
LINPHONE_PUBLIC float linphone_call_stats_get_sender_interarrival_jitter(const LinphoneCallStats *stats, LinphoneCall *call);
LINPHONE_PUBLIC float linphone_call_stats_get_receiver_interarrival_jitter(const LinphoneCallStats *stats, LinphoneCall *call);
LINPHONE_PUBLIC uint64_t linphone_call_stats_get_late_packets_cumulative_number(const LinphoneCallStats *stats, LinphoneCall *call);
LINPHONE_PUBLIC float linphone_call_stats_get_download_bandwidth(const LinphoneCallStats *stats);
LINPHONE_PUBLIC float linphone_call_stats_get_upload_bandwidth(const LinphoneCallStats *stats);
LINPHONE_PUBLIC LinphoneIceState linphone_call_stats_get_ice_state(const LinphoneCallStats *stats);
LINPHONE_PUBLIC LinphoneUpnpState linphone_call_stats_get_upnp_state(const LinphoneCallStats *stats);
/** Callback prototype */
typedef void (*LinphoneCallCbFunc)(LinphoneCall *call,void * user_data);
/**
* Player interface.
* @ingroup call_control
**/
typedef struct _LinphonePlayer LinphonePlayer;
/**
* Callback for notifying end of play (file).
* @param obj the LinphonePlayer
* @param user_data the user_data provided when calling linphone_player_open().
* @ingroup call_control
**/
typedef void (*LinphonePlayerEofCallback)(struct _LinphonePlayer *obj, void *user_data);
int linphone_player_open(LinphonePlayer *obj, const char *filename, LinphonePlayerEofCallback, void *user_data);
int linphone_player_start(LinphonePlayer *obj);
int linphone_player_pause(LinphonePlayer *obj);
int linphone_player_seek(LinphonePlayer *obj, int time_ms);
MSPlayerState linphone_player_get_state(LinphonePlayer *obj);
void linphone_player_close(LinphonePlayer *obj);
/**
* LinphoneCallState enum represents the different state a call can reach into.
* The application is notified of state changes through the LinphoneCoreVTable::call_state_changed callback.
@ -685,15 +625,56 @@ typedef enum _LinphoneCallState{
LINPHONE_PUBLIC const char *linphone_call_state_to_string(LinphoneCallState cs);
/**
* Acquire a reference to the call.
* An application that wishes to retain a pointer to call object
* must use this function to unsure the pointer remains
* valid. Once the application no more needs this pointer,
* it must call linphone_call_unref().
* @param[in] call The call.
* @return The same call.
* @ingroup call_control
**/
LINPHONE_PUBLIC LinphoneCall *linphone_call_ref(LinphoneCall *call);
/**
* Release reference to the call.
* @param[in] call The call.
* @ingroup call_control
**/
LINPHONE_PUBLIC void linphone_call_unref(LinphoneCall *call);
/**
* Retrieve the user pointer associated with the call.
* @param[in] call The call.
* @return The user pointer associated with the call.
* @ingroup call_control
**/
LINPHONE_PUBLIC void *linphone_call_get_user_data(const LinphoneCall *call);
/**
* Assign a user pointer to the call.
* @param[in] cfg The call.
* @param[in] ud The user pointer to associate with the call.
* @ingroup call_control
**/
LINPHONE_PUBLIC void linphone_call_set_user_data(LinphoneCall *call, void *ud);
LINPHONE_PUBLIC LinphoneCore *linphone_call_get_core(const LinphoneCall *call);
LINPHONE_PUBLIC LinphoneCallState linphone_call_get_state(const LinphoneCall *call);
LINPHONE_PUBLIC bool_t linphone_call_asked_to_autoanswer(LinphoneCall *call);
/**
* Get the remote address of the current call.
* @param[in] lc LinphoneCore object.
* @return The remote address of the current call or NULL if there is no current call.
* @ingroup call_control
*/
LINPHONE_PUBLIC const LinphoneAddress * linphone_core_get_current_call_remote_address(LinphoneCore *lc);
LINPHONE_PUBLIC const LinphoneAddress * linphone_call_get_remote_address(const LinphoneCall *call);
LINPHONE_PUBLIC char *linphone_call_get_remote_address_as_string(const LinphoneCall *call);
LINPHONE_PUBLIC LinphoneCallDir linphone_call_get_dir(const LinphoneCall *call);
LINPHONE_PUBLIC LinphoneCall * linphone_call_ref(LinphoneCall *call);
LINPHONE_PUBLIC void linphone_call_unref(LinphoneCall *call);
LINPHONE_PUBLIC LinphoneCallLog *linphone_call_get_call_log(const LinphoneCall *call);
LINPHONE_PUBLIC const char *linphone_call_get_refer_to(const LinphoneCall *call);
LINPHONE_PUBLIC bool_t linphone_call_has_transfer_pending(const LinphoneCall *call);
@ -719,13 +700,16 @@ LINPHONE_PUBLIC const char* linphone_call_get_authentication_token(LinphoneCall
LINPHONE_PUBLIC bool_t linphone_call_get_authentication_token_verified(LinphoneCall *call);
LINPHONE_PUBLIC void linphone_call_set_authentication_token_verified(LinphoneCall *call, bool_t verified);
LINPHONE_PUBLIC void linphone_call_send_vfu_request(LinphoneCall *call);
LINPHONE_PUBLIC void *linphone_call_get_user_pointer(LinphoneCall *call);
LINPHONE_PUBLIC void linphone_call_set_user_pointer(LinphoneCall *call, void *user_pointer);
/** @deprecated Use linphone_call_get_user_data() instead. */
#define linphone_call_get_user_pointer(call) linphone_call_get_user_data(call)
/** @deprecated Use linphone_call_set_user_data() instead. */
#define linphone_call_set_user_pointer(call, ud) linphone_call_set_user_data(call, ud)
LINPHONE_PUBLIC void linphone_call_set_next_video_frame_decoded_callback(LinphoneCall *call, LinphoneCallCbFunc cb, void* user_data);
LINPHONE_PUBLIC LinphoneCallState linphone_call_get_transfer_state(LinphoneCall *call);
LINPHONE_PUBLIC void linphone_call_zoom_video(LinphoneCall* call, float zoom_factor, float* cx, float* cy);
LINPHONE_PUBLIC void linphone_call_start_recording(LinphoneCall *call);
LINPHONE_PUBLIC void linphone_call_stop_recording(LinphoneCall *call);
LINPHONE_PUBLIC LinphonePlayer * linphone_call_get_player(LinphoneCall *call);
/**
* Return TRUE if this call is currently part of a conference
@ -812,6 +796,34 @@ typedef enum _LinphoneRegistrationState{
*/
LINPHONE_PUBLIC const char *linphone_registration_state_to_string(LinphoneRegistrationState cs);
LINPHONE_PUBLIC LinphoneProxyConfig *linphone_proxy_config_new(void);
/**
* Acquire a reference to the proxy config.
* @param[in] cfg The proxy config.
* @return The same proxy config.
**/
LINPHONE_PUBLIC LinphoneProxyConfig *linphone_proxy_config_ref(LinphoneProxyConfig *cfg);
/**
* Release reference to the proxy config.
* @param[in] cfg The proxy config.
**/
LINPHONE_PUBLIC void linphone_proxy_config_unref(LinphoneProxyConfig *cfg);
/**
* Retrieve the user pointer associated with the proxy config.
* @param[in] cfg The proxy config.
* @return The user pointer associated with the proxy config.
**/
LINPHONE_PUBLIC void *linphone_proxy_config_get_user_data(const LinphoneProxyConfig *cfg);
/**
* Assign a user pointer to the proxy config.
* @param[in] cfg The proxy config.
* @param[in] ud The user pointer to associate with the proxy config.
**/
LINPHONE_PUBLIC void linphone_proxy_config_set_user_data(LinphoneProxyConfig *cfg, void *ud);
LINPHONE_PUBLIC int linphone_proxy_config_set_server_addr(LinphoneProxyConfig *obj, const char *server_addr);
LINPHONE_PUBLIC int linphone_proxy_config_set_identity(LinphoneProxyConfig *obj, const char *identity);
LINPHONE_PUBLIC int linphone_proxy_config_set_route(LinphoneProxyConfig *obj, const char *route);
@ -919,6 +931,20 @@ LINPHONE_PUBLIC bool_t linphone_proxy_config_is_registered(const LinphoneProxyCo
**/
LINPHONE_PUBLIC const char *linphone_proxy_config_get_domain(const LinphoneProxyConfig *cfg);
/**
* Get the realm of the given proxy config.
* @param[in] cfg #LinphoneProxyConfig object.
* @returns The realm of the proxy config.
**/
LINPHONE_PUBLIC const char *linphone_proxy_config_get_realm(const LinphoneProxyConfig *cfg);
/**
* Set the realm of the given proxy config.
* @param[in] cfg #LinphoneProxyConfig object.
* @param[in] realm New realm value.
* @returns The realm of the proxy config.
**/
LINPHONE_PUBLIC void linphone_proxy_config_set_realm(LinphoneProxyConfig *cfg, const char * realm);
LINPHONE_PUBLIC const char *linphone_proxy_config_get_route(const LinphoneProxyConfig *obj);
LINPHONE_PUBLIC const char *linphone_proxy_config_get_identity(const LinphoneProxyConfig *obj);
LINPHONE_PUBLIC bool_t linphone_proxy_config_publish_enabled(const LinphoneProxyConfig *obj);
@ -974,14 +1000,6 @@ LINPHONE_PUBLIC SipSetup *linphone_proxy_config_get_sip_setup(LinphoneProxyConfi
* normalize a human readable phone number into a basic string. 888-444-222 becomes 888444222
*/
LINPHONE_PUBLIC int linphone_proxy_config_normalize_number(LinphoneProxyConfig *proxy, const char *username, char *result, size_t result_len);
/*
* attached a user data to a proxy config
*/
LINPHONE_PUBLIC void linphone_proxy_config_set_user_data(LinphoneProxyConfig *cr, void * ud);
/*
* get user data to a proxy config. return null if any
*/
LINPHONE_PUBLIC void * linphone_proxy_config_get_user_data(LinphoneProxyConfig *cr);
/**
* Set default privacy policy for all calls routed through this proxy.
@ -1012,6 +1030,7 @@ LINPHONE_PUBLIC const char* linphone_proxy_config_get_file_transfer_server(const
* Indicates whether AVPF/SAVPF must be used for calls using this proxy config.
* @param[in] cfg #LinphoneProxyConfig object
* @param[in] enable True to enable AVPF/SAVF, false to disable it.
* @deprecated use linphone_proxy_config_set_avpf_mode()
*/
LINPHONE_PUBLIC void linphone_proxy_config_enable_avpf(LinphoneProxyConfig *cfg, bool_t enable);
@ -1019,6 +1038,7 @@ LINPHONE_PUBLIC void linphone_proxy_config_enable_avpf(LinphoneProxyConfig *cfg,
* Indicates whether AVPF/SAVPF is being used for calls using this proxy config.
* @param[in] cfg #LinphoneProxyConfig object
* @return True if AVPF/SAVPF is enabled, false otherwise.
* @deprecated use linphone_proxy_config_set_avpf_mode()
*/
LINPHONE_PUBLIC bool_t linphone_proxy_config_avpf_enabled(LinphoneProxyConfig *cfg);
@ -1036,6 +1056,20 @@ LINPHONE_PUBLIC void linphone_proxy_config_set_avpf_rr_interval(LinphoneProxyCon
*/
LINPHONE_PUBLIC uint8_t linphone_proxy_config_get_avpf_rr_interval(const LinphoneProxyConfig *cfg);
/**
* Get enablement status of RTCP feedback (also known as AVPF profile).
* @param[in] cfg the proxy config
* @return the enablement mode, which can be LinphoneAVPFDefault (use LinphoneCore's mode), LinphoneAVPFEnabled (avpf is enabled), or LinphoneAVPFDisabled (disabled).
**/
LINPHONE_PUBLIC LinphoneAVPFMode linphone_proxy_config_get_avpf_mode(const LinphoneProxyConfig *cfg);
/**
* Enable the use of RTCP feedback (also known as AVPF profile).
* @param[in] cfg the proxy config
* @param[in] mode the enablement mode, which can be LinphoneAVPFDefault (use LinphoneCore's mode), LinphoneAVPFEnabled (avpf is enabled), or LinphoneAVPFDisabled (disabled).
**/
LINPHONE_PUBLIC void linphone_proxy_config_set_avpf_mode(LinphoneProxyConfig *cfg, LinphoneAVPFMode mode);
/**
* @}
**/
@ -1246,7 +1280,8 @@ typedef enum _LinphoneChatMessageState {
LinphoneChatMessageStateIdle, /**< Initial state */
LinphoneChatMessageStateInProgress, /**< Delivery in progress */
LinphoneChatMessageStateDelivered, /**< Message succesffully delivered an acknoleged by remote end point */
LinphoneChatMessageStateNotDelivered /**< Message was not delivered */
LinphoneChatMessageStateNotDelivered, /**< Message was not delivered */
LinphoneChatMessageStateFileTransferError /**< Message was received(and acknowledged) but cannot get file from server */
} LinphoneChatMessageState;
/**
@ -1261,6 +1296,7 @@ LINPHONE_PUBLIC void linphone_core_set_chat_database_path(LinphoneCore *lc, cons
LINPHONE_PUBLIC LinphoneChatRoom * linphone_core_create_chat_room(LinphoneCore *lc, const char *to);
LINPHONE_PUBLIC LinphoneChatRoom * linphone_core_get_or_create_chat_room(LinphoneCore *lc, const char *to);
LINPHONE_PUBLIC LinphoneChatRoom *linphone_core_get_chat_room(LinphoneCore *lc, const LinphoneAddress *addr);
LINPHONE_PUBLIC LinphoneChatRoom *linphone_core_get_chat_room_from_uri(LinphoneCore *lc, const char *to);
LINPHONE_PUBLIC void linphone_core_disable_chat(LinphoneCore *lc, LinphoneReason deny_reason);
LINPHONE_PUBLIC void linphone_core_enable_chat(LinphoneCore *lc);
LINPHONE_PUBLIC bool_t linphone_core_chat_enabled(const LinphoneCore *lc);
@ -1268,6 +1304,33 @@ LINPHONE_PUBLIC void linphone_chat_room_destroy(LinphoneChatRoom *cr);
LINPHONE_PUBLIC LinphoneChatMessage* linphone_chat_room_create_message(LinphoneChatRoom *cr,const char* message);
LINPHONE_PUBLIC LinphoneChatMessage* linphone_chat_room_create_message_2(LinphoneChatRoom *cr, const char* message, const char* external_body_url, LinphoneChatMessageState state, time_t time, bool_t is_read, bool_t is_incoming);
/**
* Acquire a reference to the chat room.
* @param[in] cr The chat room.
* @return The same chat room.
**/
LINPHONE_PUBLIC LinphoneChatRoom *linphone_chat_room_ref(LinphoneChatRoom *cr);
/**
* Release reference to the chat room.
* @param[in] cr The chat room.
**/
LINPHONE_PUBLIC void linphone_chat_room_unref(LinphoneChatRoom *cr);
/**
* Retrieve the user pointer associated with the chat room.
* @param[in] cr The chat room.
* @return The user pointer associated with the chat room.
**/
LINPHONE_PUBLIC void *linphone_chat_room_get_user_data(const LinphoneChatRoom *cr);
/**
* Assign a user pointer to the chat room.
* @param[in] cr The chat room.
* @param[in] ud The user pointer to associate with the chat room.
**/
LINPHONE_PUBLIC void linphone_chat_room_set_user_data(LinphoneChatRoom *cr, void *ud);
/**
* Create a message attached to a dedicated chat room with a particular content. Use #linphone_chat_room_file_transfer_send to initiate the transfer
* @param[in] cr the chat room.
@ -1284,9 +1347,24 @@ LINPHONE_PUBLIC MSList *linphone_chat_room_get_history(LinphoneChatRoom *cr,int
LINPHONE_PUBLIC void linphone_chat_room_mark_as_read(LinphoneChatRoom *cr);
LINPHONE_PUBLIC void linphone_chat_room_delete_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg);
LINPHONE_PUBLIC void linphone_chat_room_delete_history(LinphoneChatRoom *cr);
/**
* Gets the number of messages in a chat room.
* @param[in] cr The #LinphoneChatRoom object corresponding to the conversation for which size has to be computed
* @return the number of messages.
*/
LINPHONE_PUBLIC int linphone_chat_room_get_history_size(LinphoneChatRoom *cr);
/**
* Notify the destination of the chat message being composed that the user is typing a new message.
* Gets the partial list of messages in the given range, sorted from oldest to most recent.
* @param[in] cr The #LinphoneChatRoom object corresponding to the conversation for which messages should be retrieved
* @param[in] begin The first message of the range to be retrieved. History most recent message has index 0.
* @param[in] end The last message of the range to be retrieved. History oldest message has index of history size - 1 (use #linphone_chat_room_get_history_size to retrieve history size)
* @return \mslist{LinphoneChatMessage}
*/
LINPHONE_PUBLIC MSList *linphone_chat_room_get_history_range(LinphoneChatRoom *cr, int begin, int end);
/**
* Notifies the destination of the chat message being composed that the user is typing a new message.
* @param[in] cr The #LinphoneChatRoom object corresponding to the conversation for which a new message is being typed.
*/
LINPHONE_PUBLIC void linphone_chat_room_compose(LinphoneChatRoom *cr);
@ -1301,8 +1379,6 @@ LINPHONE_PUBLIC bool_t linphone_chat_room_is_remote_composing(const LinphoneChat
LINPHONE_PUBLIC int linphone_chat_room_get_unread_messages_count(LinphoneChatRoom *cr);
LINPHONE_PUBLIC LinphoneCore* linphone_chat_room_get_lc(LinphoneChatRoom *cr);
LINPHONE_PUBLIC LinphoneCore* linphone_chat_room_get_core(LinphoneChatRoom *cr);
LINPHONE_PUBLIC void linphone_chat_room_set_user_data(LinphoneChatRoom *cr, void * ud);
LINPHONE_PUBLIC void * linphone_chat_room_get_user_data(LinphoneChatRoom *cr);
LINPHONE_PUBLIC MSList* linphone_core_get_chat_rooms(LinphoneCore *lc);
LINPHONE_PUBLIC unsigned int linphone_chat_message_store(LinphoneChatMessage *msg);
@ -1312,14 +1388,22 @@ LINPHONE_PUBLIC LinphoneChatMessage* linphone_chat_message_clone(const LinphoneC
LINPHONE_PUBLIC LinphoneChatMessage * linphone_chat_message_ref(LinphoneChatMessage *msg);
LINPHONE_PUBLIC void linphone_chat_message_unref(LinphoneChatMessage *msg);
LINPHONE_PUBLIC void linphone_chat_message_destroy(LinphoneChatMessage* msg);
LINPHONE_PUBLIC void linphone_chat_message_set_from(LinphoneChatMessage* message, const LinphoneAddress* from);
LINPHONE_PUBLIC const LinphoneAddress* linphone_chat_message_get_from(const LinphoneChatMessage* message);
LINPHONE_PUBLIC void linphone_chat_message_set_to(LinphoneChatMessage* message, const LinphoneAddress* from);
LINPHONE_PUBLIC const LinphoneAddress* linphone_chat_message_get_to(const LinphoneChatMessage* message);
/** @deprecated Use linphone_chat_message_set_from_address() instead. */
#define linphone_chat_message_set_from(msg, addr) linphone_chat_message_set_from_address(msg, addr)
LINPHONE_PUBLIC void linphone_chat_message_set_from_address(LinphoneChatMessage* message, const LinphoneAddress* addr);
/** @deprecated Use linphone_chat_message_get_from_address() instead. */
#define linphone_chat_message_get_from(msg) linphone_chat_message_get_from_address(msg)
LINPHONE_PUBLIC const LinphoneAddress* linphone_chat_message_get_from_address(const LinphoneChatMessage* message);
#define linphone_chat_message_set_to(msg, addr) linphone_chat_message_set_to_address(msg, addr)
LINPHONE_PUBLIC void linphone_chat_message_set_to_address(LinphoneChatMessage* message, const LinphoneAddress* addr);
/** @deprecated Use linphone_chat_message_get_to_address() instead. */
#define linphone_chat_message_get_to(msg) linphone_chat_message_get_to_address(msg)
LINPHONE_PUBLIC const LinphoneAddress* linphone_chat_message_get_to_address(const LinphoneChatMessage* message);
LINPHONE_PUBLIC const char* linphone_chat_message_get_external_body_url(const LinphoneChatMessage* message);
LINPHONE_PUBLIC void linphone_chat_message_set_external_body_url(LinphoneChatMessage* message,const char* url);
LINPHONE_PUBLIC const LinphoneContent* linphone_chat_message_get_file_transfer_information(const LinphoneChatMessage* message);
LINPHONE_PUBLIC void linphone_chat_message_start_file_download(const LinphoneChatMessage*message);
LINPHONE_PUBLIC void linphone_chat_message_start_file_download(LinphoneChatMessage* message, LinphoneChatMessageStateChangedCb status_cb);
LINPHONE_PUBLIC void linphone_chat_room_cancel_file_transfer(LinphoneChatMessage* msg);
LINPHONE_PUBLIC const char* linphone_chat_message_get_appdata(const LinphoneChatMessage* message);
LINPHONE_PUBLIC void linphone_chat_message_set_appdata(LinphoneChatMessage* message, const char* data);
LINPHONE_PUBLIC const char* linphone_chat_message_get_text(const LinphoneChatMessage* message);
@ -1559,6 +1643,13 @@ typedef enum _LinphoneConfiguringState {
*/
typedef void (*LinphoneCoreConfiguringStatusCb)(LinphoneCore *lc, LinphoneConfiguringState status, const char *message);
/**
* Callback prototype for reporting network change either automatically detected or notified by #linphone_core_set_network_reachable.
* @param lc the LinphoneCore
* @param reachable true if network is reachable.
*/
typedef void (*LinphoneCoreNetworkReachableCb)(LinphoneCore *lc, bool_t reachable);
/**
* This structure holds all callbacks that the application should implement.
* None is mandatory.
@ -1590,11 +1681,24 @@ typedef struct _LinphoneCoreVTable{
DisplayUrlCb display_url; /**< @deprecated */
ShowInterfaceCb show; /**< @deprecated Notifies the application that it should show up*/
LinphoneCoreTextMessageReceivedCb text_received; /** @deprecated, use #message_received instead <br> A text message has been received */
LinphoneCoreFileTransferRecvCb file_transfer_received; /** Callback to store file received attached to a #LinphoneChatMessage */
LinphoneCoreFileTransferRecvCb file_transfer_recv; /** Callback to store file received attached to a #LinphoneChatMessage */
LinphoneCoreFileTransferSendCb file_transfer_send; /** Callback to collect file chunk to be sent for a #LinphoneChatMessage */
LinphoneCoreFileTransferProgressIndicationCb file_transfer_progress_indication; /**Callback to indicate file transfer progress*/
LinphoneCoreNetworkReachableCb network_reachable; /** Call back to report IP network status (I.E up/down)*/
} LinphoneCoreVTable;
/**
* Instantiate a vtable with all argument set to NULL
* @returns newly allocated vtable
*/
LINPHONE_PUBLIC LinphoneCoreVTable *linphone_vtable_new();
/**
* destroy a vtable.
* @param vtable to be destroyed
*/
LINPHONE_PUBLIC void linphone_vtable_destroy(LinphoneCoreVTable* table);
/**
* @}
**/
@ -1660,6 +1764,14 @@ LINPHONE_PUBLIC void linphone_core_set_log_level(OrtpLogLevel loglevel);
LINPHONE_PUBLIC void linphone_core_enable_logs(FILE *file);
LINPHONE_PUBLIC void linphone_core_enable_logs_with_cb(OrtpLogFunc logfunc);
LINPHONE_PUBLIC void linphone_core_disable_logs(void);
/**
* Enable logs serialization (output logs from either the thread that creates the linphone core or the thread that calls linphone_core_iterate()).
* Must be called before creating the linphone core.
* @ingroup misc
*/
LINPHONE_PUBLIC void linphone_core_serialize_logs(void);
LINPHONE_PUBLIC const char *linphone_core_get_version(void);
LINPHONE_PUBLIC const char *linphone_core_get_user_agent(LinphoneCore *lc);
/**
@ -1691,24 +1803,26 @@ LINPHONE_PUBLIC LinphoneCore *linphone_core_new_with_config(const LinphoneCoreVT
/* function to be periodically called in a main loop */
/* For ICE to work properly it should be called every 20ms */
LINPHONE_PUBLIC void linphone_core_iterate(LinphoneCore *lc);
#if 0 /*not implemented yet*/
/**
* @ingroup initializing
* Provide Linphone Core with an unique identifier. This be later used to identified contact address coming from this device.
* Value is not saved.
* add a listener to be notified of linphone core events. Once events are received, registered vtable are invoked in order.
* @param vtable a LinphoneCoreVTable structure holding your application callbacks. Object is owned by linphone core until linphone_core_remove_listener.
* @param lc object
* @param string identifying the device, can be EMEI or UDID
*
*/
void linphone_core_set_device_identifier(LinphoneCore *lc,const char* device_id);
LINPHONE_PUBLIC void linphone_core_add_listener(LinphoneCore *lc, LinphoneCoreVTable *vtable);
/**
* @ingroup initializing
* get Linphone unique identifier
* remove a listener registred by linphone_core_add_listener.
* @param vtable a LinphoneCoreVTable structure holding your application callbacks
* @param lc object
* @param string identifying the device, can be EMEI or UDID
*
*/
const char* linphone_core_get_device_identifier(const LinphoneCore *lc);
LINPHONE_PUBLIC void linphone_core_remove_listener(LinphoneCore *lc, const LinphoneCoreVTable *vtable);
#endif
/*sets the user-agent string in sip messages, ideally called just after linphone_core_new() or linphone_core_init() */
LINPHONE_PUBLIC void linphone_core_set_user_agent(LinphoneCore *lc, const char *ua_name, const char *version);
@ -1729,7 +1843,16 @@ LINPHONE_PUBLIC int linphone_core_transfer_call_to_another(LinphoneCore *lc, Lin
LINPHONE_PUBLIC LinphoneCall * linphone_core_start_refered_call(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params);
LINPHONE_PUBLIC bool_t linphone_core_inc_invite_pending(LinphoneCore*lc);
/** @deprecated Use linphone_core_is_incoming_invite_pending() instead. */
#define linphone_core_inc_invite_pending(lc) linphone_core_is_incoming_invite_pending(lc)
/**
* Tells whether there is an incoming invite pending.
* @ingroup call_control
* @param[in] lc LinphoneCore object
* @return A boolean telling whether an incoming invite is pending or not.
*/
LINPHONE_PUBLIC bool_t linphone_core_is_incoming_invite_pending(LinphoneCore*lc);
LINPHONE_PUBLIC bool_t linphone_core_in_call(const LinphoneCore *lc);
@ -1775,9 +1898,12 @@ LINPHONE_PUBLIC int linphone_core_accept_call_update(LinphoneCore *lc, LinphoneC
* Get default call parameters reflecting current linphone core configuration
* @param lc LinphoneCore object
* @return LinphoneCallParams
* @deprecated use linphone_core_create_call_params()
*/
LINPHONE_PUBLIC LinphoneCallParams *linphone_core_create_default_call_parameters(LinphoneCore *lc);
LINPHONE_PUBLIC LinphoneCallParams *linphone_core_create_call_params(LinphoneCore *lc, LinphoneCall *call);
LINPHONE_PUBLIC LinphoneCall *linphone_core_get_call_by_remote_address(LinphoneCore *lc, const char *remote_address);
LINPHONE_PUBLIC void linphone_core_send_dtmf(LinphoneCore *lc,char dtmf);
@ -1808,6 +1934,9 @@ LINPHONE_PUBLIC int linphone_core_get_upload_bandwidth(const LinphoneCore *lc);
LINPHONE_PUBLIC void linphone_core_enable_adaptive_rate_control(LinphoneCore *lc, bool_t enabled);
LINPHONE_PUBLIC bool_t linphone_core_adaptive_rate_control_enabled(const LinphoneCore *lc);
LINPHONE_PUBLIC void linphone_core_set_adaptive_rate_algorithm(LinphoneCore *lc, const char *algorithm);
LINPHONE_PUBLIC const char* linphone_core_get_adaptive_rate_algorithm(const LinphoneCore *lc);
LINPHONE_PUBLIC void linphone_core_set_download_ptime(LinphoneCore *lc, int ptime);
LINPHONE_PUBLIC int linphone_core_get_download_ptime(LinphoneCore *lc);
@ -1859,48 +1988,48 @@ LINPHONE_PUBLIC int linphone_core_set_video_codecs(LinphoneCore *lc, MSList *cod
/**
* Tells whether the specified payload type is enabled.
* @param[in] lc #LinphoneCore object.
* @param[in] pt The #PayloadType we want to know is enabled or not.
* @param[in] pt The #LinphonePayloadType we want to know is enabled or not.
* @returns TRUE if the payload type is enabled, FALSE if disabled.
* @ingroup media_parameters
*/
LINPHONE_PUBLIC bool_t linphone_core_payload_type_enabled(LinphoneCore *lc, const PayloadType *pt);
LINPHONE_PUBLIC bool_t linphone_core_payload_type_enabled(LinphoneCore *lc, const LinphonePayloadType *pt);
/**
* Tells whether the specified payload type represents a variable bitrate codec.
* @param[in] lc #LinphoneCore object.
* @param[in] pt The #PayloadType we want to know
* @param[in] pt The #LinphonePayloadType we want to know
* @returns TRUE if the payload type represents a VBR codec, FALSE if disabled.
* @ingroup media_parameters
*/
LINPHONE_PUBLIC bool_t linphone_core_payload_type_is_vbr(LinphoneCore *lc, const PayloadType *pt);
LINPHONE_PUBLIC bool_t linphone_core_payload_type_is_vbr(LinphoneCore *lc, const LinphonePayloadType *pt);
/**
* Set an explicit bitrate (IP bitrate, not codec bitrate) for a given codec, in kbit/s.
* @param[in] lc the #LinphoneCore object
* @param[in] pt the #PayloadType to modify.
* @param[in] pt the #LinphonePayloadType to modify.
* @param[in] bitrate the IP bitrate in kbit/s.
* @ingroup media_parameters
**/
LINPHONE_PUBLIC void linphone_core_set_payload_type_bitrate(LinphoneCore *lc, PayloadType *pt, int bitrate);
LINPHONE_PUBLIC void linphone_core_set_payload_type_bitrate(LinphoneCore *lc, LinphonePayloadType *pt, int bitrate);
/**
* Get the bitrate explicitely set with linphone_core_set_payload_type_bitrate().
* @param[in] lc the #LinphoneCore object
* @param[in] pt the #PayloadType to modify.
* @param[in] pt the #LinphonePayloadType to modify.
* @return bitrate the IP bitrate in kbit/s, or -1 if an error occured.
* @ingroup media_parameters
**/
LINPHONE_PUBLIC int linphone_core_get_payload_type_bitrate(LinphoneCore *lc, const PayloadType *pt);
LINPHONE_PUBLIC int linphone_core_get_payload_type_bitrate(LinphoneCore *lc, const LinphonePayloadType *pt);
/**
* Enable or disable the use of the specified payload type.
* @param[in] lc #LinphoneCore object.
* @param[in] pt The #PayloadType to enable or disable. It can be retrieved using #linphone_core_find_payload_type
* @param[in] pt The #LinphonePayloadType to enable or disable. It can be retrieved using #linphone_core_find_payload_type
* @param[in] enable TRUE to enable the payload type, FALSE to disable it.
* @return 0 if successful, any other value otherwise.
* @ingroup media_parameters
*/
LINPHONE_PUBLIC int linphone_core_enable_payload_type(LinphoneCore *lc, PayloadType *pt, bool_t enable);
LINPHONE_PUBLIC int linphone_core_enable_payload_type(LinphoneCore *lc, LinphonePayloadType *pt, bool_t enable);
/**
* Wildcard value used by #linphone_core_find_payload_type to ignore rate in search algorithm
@ -1922,7 +2051,7 @@ LINPHONE_PUBLIC int linphone_core_enable_payload_type(LinphoneCore *lc, PayloadT
* @param channels number of channels, can be #LINPHONE_FIND_PAYLOAD_IGNORE_CHANNELS
* @return Returns NULL if not found.
*/
LINPHONE_PUBLIC PayloadType* linphone_core_find_payload_type(LinphoneCore* lc, const char* type, int rate, int channels) ;
LINPHONE_PUBLIC LinphonePayloadType* linphone_core_find_payload_type(LinphoneCore* lc, const char* type, int rate, int channels) ;
LINPHONE_PUBLIC int linphone_core_get_payload_type_number(LinphoneCore *lc, const PayloadType *pt);
@ -1946,12 +2075,17 @@ LINPHONE_PUBLIC void linphone_core_remove_proxy_config(LinphoneCore *lc, Linphon
LINPHONE_PUBLIC const MSList *linphone_core_get_proxy_config_list(const LinphoneCore *lc);
LINPHONE_PUBLIC void linphone_core_set_default_proxy(LinphoneCore *lc, LinphoneProxyConfig *config);
/** @deprecated Use linphone_core_set_default_proxy_config() instead. */
#define linphone_core_set_default_proxy(lc, config) linphone_core_set_default_proxy_config(lc, config)
void linphone_core_set_default_proxy_index(LinphoneCore *lc, int index);
LINPHONE_PUBLIC int linphone_core_get_default_proxy(LinphoneCore *lc, LinphoneProxyConfig **config);
LINPHONE_PUBLIC LinphoneProxyConfig * linphone_core_get_default_proxy_config(LinphoneCore *lc);
LINPHONE_PUBLIC void linphone_core_set_default_proxy_config(LinphoneCore *lc, LinphoneProxyConfig *config);
/**
* Create an authentication information with default values from Linphone core.
* @param[in] lc #LinphoneCore object
@ -2260,34 +2394,54 @@ bool_t linphone_core_get_rtp_no_xmit_on_audio_mute(const LinphoneCore *lc);
void linphone_core_set_rtp_no_xmit_on_audio_mute(LinphoneCore *lc, bool_t val);
/* returns a list of LinphoneCallLog */
LINPHONE_PUBLIC const MSList * linphone_core_get_call_logs(LinphoneCore *lc);
LINPHONE_PUBLIC void linphone_core_clear_call_logs(LinphoneCore *lc);
/*******************************************************************************
* Call log related functions *
******************************************************************************/
/**
* @addtogroup call_logs
* @{
**/
/**
* Get the list of call logs (past calls).
* @param[in] lc LinphoneCore object
* @return \mslist{LinphoneCallLog}
**/
LINPHONE_PUBLIC const MSList * linphone_core_get_call_logs(LinphoneCore *lc);
/**
* Erase the call log.
* @param[in] lc LinphoneCore object
**/
LINPHONE_PUBLIC void linphone_core_clear_call_logs(LinphoneCore *lc);
/**
* Get the number of missed calls.
* Once checked, this counter can be reset with linphone_core_reset_missed_calls_count().
* @param[in] lc #LinphoneCore object.
* @returns The number of missed calls.
* @ingroup call_logs
**/
LINPHONE_PUBLIC int linphone_core_get_missed_calls_count(LinphoneCore *lc);
LINPHONE_PUBLIC int linphone_core_get_missed_calls_count(LinphoneCore *lc);
/**
* Reset the counter of missed calls.
* @param[in] lc #LinphoneCore object.
* @ingroup call_logs
**/
LINPHONE_PUBLIC void linphone_core_reset_missed_calls_count(LinphoneCore *lc);
LINPHONE_PUBLIC void linphone_core_reset_missed_calls_count(LinphoneCore *lc);
/**
* Remove a specific call log from call history list.
* This function destroys the call log object. It must not be accessed anymore by the application after calling this function.
* @param[in] lc #LinphoneCore object
* @param[in] call_log #LinphoneCallLog object to remove.
* @ingroup call_logs
**/
LINPHONE_PUBLIC void linphone_core_remove_call_log(LinphoneCore *lc, LinphoneCallLog *call_log);
LINPHONE_PUBLIC void linphone_core_remove_call_log(LinphoneCore *lc, LinphoneCallLog *call_log);
/**
* @}
**/
/* video support */
LINPHONE_PUBLIC bool_t linphone_core_video_supported(LinphoneCore *lc);
@ -2336,6 +2490,24 @@ LINPHONE_PUBLIC void linphone_core_enable_video_capture(LinphoneCore *lc, bool_t
**/
LINPHONE_PUBLIC void linphone_core_enable_video_display(LinphoneCore *lc, bool_t enable);
/**
* Enable or disable video source reuse when switching from preview to actual video call.
*
* This source reuse is useful when you always display the preview, even before calls are initiated.
* By keeping the video source for the transition to a real video call, you will smooth out the
* source close/reopen cycle.
*
* This function does not have any effect durfing calls. It just indicates the #LinphoneCore to
* initiate future calls with video source reuse or not.
* Also, at the end of a video call, the source will be closed whatsoever for now.
* @param[in] lc #LinphoneCore object
* @param[in] enable TRUE to enable video source reuse. FALSE to disable it for subsequent calls.
* @ingroup media_parameters
*
*/
LINPHONE_PUBLIC void linphone_core_enable_video_source_reuse(LinphoneCore* lc, bool_t enable);
/**
* Tells whether video capture is enabled.
* @param[in] lc #LinphoneCore object.
@ -2456,8 +2628,10 @@ LINPHONE_PUBLIC int linphone_core_get_camera_sensor_rotation(LinphoneCore *lc);
/* start or stop streaming video in case of embedded window */
void linphone_core_show_video(LinphoneCore *lc, bool_t show);
/** @deprecated Use linphone_core_set_use_files() instead. */
#define linphone_core_use_files(lc, yesno) linphone_core_set_use_files(lc, yesno)
/*play/record support: use files instead of soundcard*/
LINPHONE_PUBLIC void linphone_core_use_files(LinphoneCore *lc, bool_t yesno);
LINPHONE_PUBLIC void linphone_core_set_use_files(LinphoneCore *lc, bool_t yesno);
LINPHONE_PUBLIC void linphone_core_set_play_file(LinphoneCore *lc, const char *file);
LINPHONE_PUBLIC void linphone_core_set_record_file(LinphoneCore *lc, const char *file);
@ -2494,7 +2668,7 @@ LINPHONE_PUBLIC void linphone_core_enable_keep_alive(LinphoneCore* lc,bool_t ena
*/
LINPHONE_PUBLIC bool_t linphone_core_keep_alive_enabled(LinphoneCore* lc);
LINPHONE_PUBLIC void *linphone_core_get_user_data(LinphoneCore *lc);
LINPHONE_PUBLIC void *linphone_core_get_user_data(const LinphoneCore *lc);
LINPHONE_PUBLIC void linphone_core_set_user_data(LinphoneCore *lc, void *userdata);
/* returns LpConfig object to read/write to the config file: usefull if you wish to extend
@ -2654,7 +2828,7 @@ typedef struct _LinphoneTunnel LinphoneTunnel;
/**
* get tunnel instance if available
*/
LINPHONE_PUBLIC LinphoneTunnel *linphone_core_get_tunnel(LinphoneCore *lc);
LINPHONE_PUBLIC LinphoneTunnel *linphone_core_get_tunnel(const LinphoneCore *lc);
LINPHONE_PUBLIC void linphone_core_set_sip_dscp(LinphoneCore *lc, int dscp);
LINPHONE_PUBLIC int linphone_core_get_sip_dscp(const LinphoneCore *lc);
@ -2754,6 +2928,13 @@ LINPHONE_PUBLIC void linphone_core_set_tone(LinphoneCore *lc, LinphoneToneID id,
* */
LINPHONE_PUBLIC void linphone_core_set_file_transfer_server(LinphoneCore *core, const char * server_url);
/**
* Get the globaly set http file transfer server to be used for content type application/vnd.gsma.rcs-ft-http+xml.
* @param[in] core #LinphoneCore from which to get the server_url
* @return URL of the file server like https://file.linphone.org/upload.php
* */
LINPHONE_PUBLIC const char * linphone_core_get_file_transfer_server(LinphoneCore *core);
/**
* Returns a null terminated table of strings containing the file format extension supported for call recording.
* @param core the core
@ -2762,6 +2943,16 @@ LINPHONE_PUBLIC void linphone_core_set_file_transfer_server(LinphoneCore *core,
**/
LINPHONE_PUBLIC const char ** linphone_core_get_supported_file_formats(LinphoneCore *core);
LINPHONE_PUBLIC void linphone_core_add_supported_tag(LinphoneCore *core, const char *tag);
LINPHONE_PUBLIC void linphone_core_remove_supported_tag(LinphoneCore *core, const char *tag);
LINPHONE_PUBLIC void linphone_core_set_avpf_mode(LinphoneCore *lc, LinphoneAVPFMode mode);
LINPHONE_PUBLIC LinphoneAVPFMode linphone_core_get_avpf_mode(const LinphoneCore *lc);
LINPHONE_PUBLIC int linphone_core_get_avpf_rr_interval(const LinphoneCore *lc);
#ifdef __cplusplus
}
#endif

View file

@ -55,6 +55,7 @@ extern "C" void libmsbcg729_init();
#ifdef HAVE_WEBRTC
extern "C" void libmswebrtc_init();
#endif
#include <belle-sip/wakelock.h>
#endif /*ANDROID*/
@ -76,25 +77,6 @@ extern "C" void libmswebrtc_init();
return jUserDataObj; \
}
#define RETURN_PROXY_CONFIG_USER_DATA_OBJECT(javaclass, funcprefix, cobj) \
{ \
jclass jUserDataObjectClass; \
jmethodID jUserDataObjectCtor; \
jobject jUserDataObj; \
jUserDataObj = (jobject)funcprefix ## _get_user_data(cobj); \
if (jUserDataObj == NULL) { \
jUserDataObjectClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/" javaclass)); \
jUserDataObjectCtor = env->GetMethodID(jUserDataObjectClass,"<init>", "(J)V"); \
jUserDataObj = env->NewObject(jUserDataObjectClass, jUserDataObjectCtor,(jlong) cobj); \
jUserDataObj = env->NewGlobalRef(jUserDataObj); \
funcprefix ## _set_user_data(cobj, jUserDataObj); \
env->DeleteGlobalRef(jUserDataObjectClass); \
} \
return jUserDataObj; \
}
static JavaVM *jvm=0;
static const char* LogDomain = "Linphone";
static jclass handler_class;
@ -208,6 +190,9 @@ public:
vTable.notify_received=notifyReceived;
vTable.publish_state_changed=publishStateChanged;
vTable.configuring_status=configuringStatus;
vTable.file_transfer_progress_indication=fileTransferProgressIndication;
vTable.file_transfer_send=fileTransferSend;
vTable.file_transfer_recv=fileTransferRecv;
listenerClass = (jclass)env->NewGlobalRef(env->GetObjectClass( alistener));
@ -310,6 +295,10 @@ public:
configuringStateId = env->GetMethodID(listenerClass,"configuringStatus","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCore$RemoteProvisioningState;Ljava/lang/String;)V");
configuringStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCore$RemoteProvisioningState"));
configuringStateFromIntId = env->GetStaticMethodID(configuringStateClass,"fromInt","(I)Lorg/linphone/core/LinphoneCore$RemoteProvisioningState;");
fileTransferProgressIndicationId = env->GetMethodID(listenerClass, "fileTransferProgressIndication", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatMessage;Lorg/linphone/core/LinphoneContent;I)V");
fileTransferSendId = env->GetMethodID(listenerClass, "fileTransferSend", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatMessage;Lorg/linphone/core/LinphoneContent;Ljava/nio/ByteBuffer;I)I");
fileTransferRecvId = env->GetMethodID(listenerClass, "fileTransferRecv", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatMessage;Lorg/linphone/core/LinphoneContent;[BI)V");
}
~LinphoneCoreData() {
@ -417,6 +406,10 @@ public:
jclass subscriptionDirClass;
jmethodID subscriptionDirFromIntId;
jmethodID fileTransferProgressIndicationId;
jmethodID fileTransferSendId;
jmethodID fileTransferRecvId;
LinphoneCoreVTable vTable;
static void showInterfaceCb(LinphoneCore *lc) {
@ -467,9 +460,35 @@ public:
,env->CallStaticObjectMethod(lcData->globalStateClass,lcData->globalStateFromIntId,(jint)gstate),
message ? env->NewStringUTF(message) : NULL);
}
/*
* returns the java LinphoneProxyConfig associated with a C LinphoneProxyConfig.
**/
jobject getProxy(JNIEnv *env , LinphoneProxyConfig *proxy, jobject core){
jobject jobj=0;
if (proxy!=NULL){
void *up=linphone_proxy_config_get_user_data(proxy);
if (up==NULL){
jobj=env->NewObject(proxyClass,proxyCtrId,core,(jlong)proxy);
linphone_proxy_config_set_user_data(proxy,(void*)env->NewWeakGlobalRef(jobj));
linphone_proxy_config_ref(proxy);
}else{
//promote the weak ref to local ref
jobj=env->NewLocalRef((jobject)up);
if (jobj == NULL){
//the weak ref was dead
jobj=env->NewObject(proxyClass,proxyCtrId,core,(jlong)proxy);
linphone_proxy_config_set_user_data(proxy,(void*)env->NewWeakGlobalRef(jobj));
}
}
}
return jobj;
}
static void registrationStateChange(LinphoneCore *lc, LinphoneProxyConfig* proxy,LinphoneRegistrationState state,const char* message) {
JNIEnv *env = 0;
jint result = jvm->AttachCurrentThread(&env,NULL);
jobject jproxy;
if (result != 0) {
ms_error("cannot attach VM");
return;
@ -478,7 +497,7 @@ public:
env->CallVoidMethod(lcData->listener
,lcData->registrationStateId
,lcData->core
,env->NewObject(lcData->proxyClass,lcData->proxyCtrId,lcData->core,(jlong)proxy)
,(jproxy=lcData->getProxy(env,proxy,lcData->core))
,env->CallStaticObjectMethod(lcData->registrationStateClass,lcData->registrationStateFromIntId,(jint)state),
message ? env->NewStringUTF(message) : NULL);
}
@ -591,19 +610,37 @@ public:
,env->NewObject(lcData->addressClass,lcData->addressCtrId,(jlong)from)
,message ? env->NewStringUTF(message) : NULL);
}
jobject getChatMessage(JNIEnv *env , LinphoneChatMessage *msg){
jobject jobj = 0;
if (msg != NULL){
void *up = linphone_chat_message_get_user_data(msg);
if (up == NULL) {
jobj = env->NewObject(chatMessageClass,chatMessageCtrId,(jlong)linphone_chat_message_ref(msg));
jobj = env->NewGlobalRef(jobj);
linphone_chat_message_set_user_data(msg,(void*)jobj);
} else {
jobj = (jobject)up;
}
}
return jobj;
}
static void message_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage *msg) {
JNIEnv *env = 0;
jobject jmsg;
jint result = jvm->AttachCurrentThread(&env,NULL);
if (result != 0) {
ms_error("cannot attach VM");
return;
}
LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_get_user_data(lc);
/*note: we call linphone_chat_message_ref() because the application does not acquire the object when invoked from a callback*/
env->CallVoidMethod(lcData->listener
,lcData->messageReceivedId
,lcData->core
,env->NewObject(lcData->chatRoomClass,lcData->chatRoomCtrId,(jlong)room)
,env->NewObject(lcData->chatMessageClass,lcData->chatMessageCtrId,(jlong)msg));
,(jmsg = lcData->getChatMessage(env, msg)));
}
static void is_composing_received(LinphoneCore *lc, LinphoneChatRoom *room) {
JNIEnv *env = 0;
@ -771,6 +808,64 @@ public:
LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_get_user_data(lc);
env->CallVoidMethod(lcData->listener, lcData->configuringStateId, lcData->core, env->CallStaticObjectMethod(lcData->configuringStateClass,lcData->configuringStateFromIntId,(jint)status), message ? env->NewStringUTF(message) : NULL);
}
static void fileTransferProgressIndication(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, size_t progress) {
JNIEnv *env = 0;
jobject jmsg;
jint result = jvm->AttachCurrentThread(&env,NULL);
if (result != 0) {
ms_error("cannot attach VM");
return;
}
LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_get_user_data(lc);
env->CallVoidMethod(lcData->listener,
lcData->fileTransferProgressIndicationId,
lcData->core,
(jmsg = lcData->getChatMessage(env, message)),
content ? create_java_linphone_content(env, content) : NULL,
progress);
}
static void fileTransferSend(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, char* buff, size_t* size) {
JNIEnv *env = 0;
jobject jmsg;
size_t asking = *size;
jint result = jvm->AttachCurrentThread(&env,NULL);
if (result != 0) {
ms_error("cannot attach VM");
return;
}
LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_get_user_data(lc);
*size = env->CallIntMethod(lcData->listener,
lcData->fileTransferSendId,
lcData->core,
(jmsg = lcData->getChatMessage(env, message)),
content ? create_java_linphone_content(env, content) : NULL,
buff ? env->NewDirectByteBuffer(buff, asking) : NULL,
asking);
}
static void fileTransferRecv(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, const char* buff, size_t size) {
JNIEnv *env = 0;
jobject jmsg;
jint result = jvm->AttachCurrentThread(&env,NULL);
if (result != 0) {
ms_error("cannot attach VM");
return;
}
LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_get_user_data(lc);
jbyteArray jbytes = env->NewByteArray(size);
env->SetByteArrayRegion(jbytes, 0, size, (jbyte*)buff);
env->CallVoidMethod(lcData->listener,
lcData->fileTransferRecvId,
lcData->core,
(jmsg = lcData->getChatMessage(env, message)),
content ? create_java_linphone_content(env, content) : NULL,
jbytes,
size);
}
};
extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_newLinphoneCore(JNIEnv* env
@ -894,35 +989,37 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setDefaultProxyConfig( J
,jlong pc) {
linphone_core_set_default_proxy((LinphoneCore*)lc,(LinphoneProxyConfig*)pc);
}
extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_getDefaultProxyConfig( JNIEnv* env
extern "C" jobject Java_org_linphone_core_LinphoneCoreImpl_getDefaultProxyConfig(JNIEnv* env
,jobject thiz
,jlong lc) {
LinphoneProxyConfig *config=0;
LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_get_user_data((LinphoneCore*)lc);
linphone_core_get_default_proxy((LinphoneCore*)lc,&config);
return (jlong)config;
}
static jobject getOrCreateProxy(JNIEnv* env,LinphoneProxyConfig* proxy){
RETURN_PROXY_CONFIG_USER_DATA_OBJECT("LinphoneProxyConfigImpl", linphone_proxy_config, proxy);
if(config != 0) {
jobject jproxy = lcData->getProxy(env,config,lcData->core);
return jproxy;
} else {
return NULL;
}
}
extern "C" jobjectArray Java_org_linphone_core_LinphoneCoreImpl_getProxyConfigList(JNIEnv* env, jobject thiz, jlong lc) {
const MSList* proxies = linphone_core_get_proxy_config_list((LinphoneCore*)lc);
int proxyCount = ms_list_size(proxies);
jclass cls = env->FindClass("java/lang/Object");
jclass cls = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneProxyConfigImpl"));
jobjectArray jProxies = env->NewObjectArray(proxyCount,cls,NULL);
LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_get_user_data((LinphoneCore*)lc);
for (int i = 0; i < proxyCount; i++ ) {
LinphoneProxyConfig* proxy = (LinphoneProxyConfig*)proxies->data;
jobject jproxy = getOrCreateProxy(env,proxy);
jobject jproxy = lcData->getProxy(env,proxy,lcData->core);
if(jproxy != NULL){
env->SetObjectArrayElement(jProxies, i, jproxy);
} else {
return NULL;
}
proxies = proxies->next;
}
env->DeleteGlobalRef(cls);
return jProxies;
}
@ -932,9 +1029,7 @@ extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_addProxyConfig( JNIEnv*
,jlong lc
,jlong pc) {
LinphoneProxyConfig* proxy = (LinphoneProxyConfig*)pc;
linphone_proxy_config_set_user_data(proxy, env->NewGlobalRef(jproxyCfg));
return (jint)linphone_core_add_proxy_config((LinphoneCore*)lc,(LinphoneProxyConfig*)pc);
return (jint)linphone_core_add_proxy_config((LinphoneCore*)lc,proxy);
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_removeProxyConfig(JNIEnv* env, jobject thiz, jlong lc, jlong proxy) {
@ -1272,6 +1367,13 @@ extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_isPayloadTypeEnabled
return (jboolean) linphone_core_payload_type_enabled((LinphoneCore*)lc, (PayloadType*)pt);
}
extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_payloadTypeIsVbr(JNIEnv* env
,jobject thiz
,jlong lc
,jlong pt) {
return (jboolean) linphone_core_payload_type_is_vbr((LinphoneCore*)lc, (PayloadType*)pt);
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setPayloadTypeBitrate(JNIEnv* env
,jobject thiz
,jlong lc
@ -1287,6 +1389,42 @@ extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_getPayloadTypeBitrate(JN
return (jint)linphone_core_get_payload_type_bitrate((LinphoneCore*)lc,(PayloadType*)pt);
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_enableAdaptiveRateControl(JNIEnv* env
,jobject thiz
,jlong lc
,jboolean enable) {
linphone_core_enable_adaptive_rate_control((LinphoneCore*)lc, enable);
}
extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_isAdaptiveRateControlEnabled(JNIEnv* env
,jobject thiz
,jlong lc
) {
return (jboolean)linphone_core_adaptive_rate_control_enabled((LinphoneCore*)lc);
}
extern "C" jstring Java_org_linphone_core_LinphoneCoreImpl_getAdaptiveRateAlgorithm(JNIEnv* env
,jobject thiz
,jlong lc
) {
const char* alg = linphone_core_get_adaptive_rate_algorithm((LinphoneCore*)lc);
if (alg) {
return env->NewStringUTF(alg);
} else {
return NULL;
}
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setAdaptiveRateAlgorithm(JNIEnv* env
,jobject thiz
,jlong lc
,jstring jalg) {
const char* alg = jalg?env->GetStringUTFChars(jalg, NULL):NULL;
linphone_core_set_adaptive_rate_algorithm((LinphoneCore*)lc,alg);
if (alg) env->ReleaseStringUTFChars(jalg, alg);
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_enableEchoCancellation(JNIEnv* env
,jobject thiz
,jlong lc
@ -1525,11 +1663,6 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setMediaEncryptionMandat
linphone_core_set_media_encryption_mandatory((LinphoneCore*)lc, yesno);
}
extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_createProxyConfig(JNIEnv* env, jobject thiz, jlong lc) {
LinphoneProxyConfig* proxy = linphone_core_create_proxy_config((LinphoneCore *)lc);
return (jlong) proxy;
}
/*
* Class: org_linphone_core_LinphoneCoreImpl
* Method: disableChat
@ -1560,14 +1693,20 @@ extern "C" JNIEXPORT jboolean JNICALL Java_org_linphone_core_LinphoneCoreImpl_ch
//ProxyConfig
extern "C" jlong Java_org_linphone_core_LinphoneProxyConfigImpl_newLinphoneProxyConfig(JNIEnv* env,jobject thiz) {
LinphoneProxyConfig* proxy = linphone_proxy_config_new();
return (jlong) proxy;
extern "C" jlong Java_org_linphone_core_LinphoneProxyConfigImpl_createProxyConfig(JNIEnv* env, jobject thiz, jlong lc) {
LinphoneProxyConfig* proxy = linphone_core_create_proxy_config((LinphoneCore *)lc);
linphone_proxy_config_set_user_data(proxy,env->NewWeakGlobalRef(thiz));
return (jlong) proxy;
}
extern "C" void Java_org_linphone_core_LinphoneProxyConfigImpl_delete(JNIEnv* env,jobject thiz,jlong ptr) {
linphone_proxy_config_destroy((LinphoneProxyConfig*)ptr);
extern "C" void Java_org_linphone_core_LinphoneProxyConfigImpl_finalize(JNIEnv* env
,jobject thiz
,jlong ptr) {
LinphoneProxyConfig *proxy=(LinphoneProxyConfig*)ptr;
linphone_proxy_config_set_user_data(proxy,NULL);
linphone_proxy_config_unref(proxy);
}
extern "C" void Java_org_linphone_core_LinphoneProxyConfigImpl_setIdentity(JNIEnv* env,jobject thiz,jlong proxyCfg,jstring jidentity) {
const char* identity = env->GetStringUTFChars(jidentity, NULL);
linphone_proxy_config_set_identity((LinphoneProxyConfig*)proxyCfg,identity);
@ -1729,6 +1868,15 @@ extern "C" jlong Java_org_linphone_core_LinphoneProxyConfigImpl_getErrorInfo(JNI
return (jlong)linphone_proxy_config_get_error_info((LinphoneProxyConfig *) ptr);
}
extern "C" jint Java_org_linphone_core_LinphoneProxyConfigImpl_getPublishExpires(JNIEnv* env,jobject thiz,jlong ptr) {
return (jint)linphone_proxy_config_get_publish_expires((LinphoneProxyConfig *) ptr);
}
extern "C" void Java_org_linphone_core_LinphoneProxyConfigImpl_setPublishExpires(JNIEnv* env
,jobject thiz
,jlong ptr
,jint jval) {
linphone_proxy_config_set_publish_expires((LinphoneProxyConfig *) ptr, jval);
}
//Auth Info
extern "C" jlong Java_org_linphone_core_LinphoneAuthInfoImpl_newLinphoneAuthInfo(JNIEnv* env
@ -2395,12 +2543,11 @@ extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_getFriendByAddress(JNIE
env->ReleaseStringUTFChars(jaddress, address);
return (jlong) lf;
}
//LinphoneChatRoom
extern "C" jlongArray Java_org_linphone_core_LinphoneChatRoomImpl_getHistory(JNIEnv* env
extern "C" jlongArray _LinphoneChatRoomImpl_getHistory(JNIEnv* env
,jobject thiz
,jlong ptr
,jint limit) {
MSList* history = linphone_chat_room_get_history((LinphoneChatRoom*)ptr, limit);
,MSList* history) {
int historySize = ms_list_size(history);
jlongArray jHistory = env->NewLongArray(historySize);
jlong *jInternalArray = env->GetLongArrayElements(jHistory, NULL);
@ -2416,6 +2563,21 @@ extern "C" jlongArray Java_org_linphone_core_LinphoneChatRoomImpl_getHistory(JNI
return jHistory;
}
extern "C" jlongArray Java_org_linphone_core_LinphoneChatRoomImpl_getHistoryRange(JNIEnv* env
,jobject thiz
,jlong ptr
,jint start
,jint end) {
MSList* history = linphone_chat_room_get_history_range((LinphoneChatRoom*)ptr, start, end);
return _LinphoneChatRoomImpl_getHistory(env, thiz, ptr, history);
}
extern "C" jlongArray Java_org_linphone_core_LinphoneChatRoomImpl_getHistory(JNIEnv* env
,jobject thiz
,jlong ptr
,jint limit) {
MSList* history = linphone_chat_room_get_history((LinphoneChatRoom*)ptr, limit);
return _LinphoneChatRoomImpl_getHistory(env, thiz, ptr, history);
}
extern "C" jlong Java_org_linphone_core_LinphoneChatRoomImpl_getPeerAddress(JNIEnv* env
,jobject thiz
,jlong ptr) {
@ -2454,6 +2616,11 @@ extern "C" jlong Java_org_linphone_core_LinphoneChatRoomImpl_createLinphoneChatM
return (jlong) chatMessage;
}
extern "C" jint Java_org_linphone_core_LinphoneChatRoomImpl_getHistorySize (JNIEnv* env
,jobject thiz
,jlong ptr) {
return (jint) linphone_chat_room_get_history_size((LinphoneChatRoom*)ptr);
}
extern "C" jint Java_org_linphone_core_LinphoneChatRoomImpl_getUnreadMessagesCount(JNIEnv* env
,jobject thiz
,jlong ptr) {
@ -2495,6 +2662,57 @@ extern "C" void Java_org_linphone_core_LinphoneChatRoomImpl_destroy(JNIEnv* env
linphone_chat_room_destroy((LinphoneChatRoom*)ptr);
}
extern "C" jlong Java_org_linphone_core_LinphoneChatRoomImpl_createFileTransferMessage(JNIEnv* env, jobject thiz, jlong ptr, jstring jname, jstring jtype, jstring jsubtype, jint data_size) {
LinphoneContent content = {0};
LinphoneChatMessage *message = NULL;
content.type = (char*)env->GetStringUTFChars(jtype, NULL);
content.subtype = (char*)env->GetStringUTFChars(jsubtype, NULL);
content.name = (char*)env->GetStringUTFChars(jname, NULL);
content.size = data_size;
message = linphone_chat_room_create_file_transfer_message((LinphoneChatRoom *)ptr, &content);
env->ReleaseStringUTFChars(jtype, content.type);
env->ReleaseStringUTFChars(jsubtype, content.subtype);
env->ReleaseStringUTFChars(jname, content.name);
return (jlong) message;
}
extern "C" void Java_org_linphone_core_LinphoneChatRoomImpl_cancelFileTransfer(JNIEnv* env, jobject thiz, jlong ptr, jlong message) {
linphone_chat_room_cancel_file_transfer((LinphoneChatMessage *)message);
}
extern "C" jobject Java_org_linphone_core_LinphoneChatMessageImpl_getFileTransferInformation(JNIEnv* env, jobject thiz, jlong ptr) {
const LinphoneContent *content = linphone_chat_message_get_file_transfer_information((LinphoneChatMessage *)ptr);
if (content)
return create_java_linphone_content(env, content);
return NULL;
}
extern "C" jstring Java_org_linphone_core_LinphoneChatMessageImpl_getAppData(JNIEnv* env, jobject thiz, jlong ptr) {
const char * app_data = linphone_chat_message_get_appdata((LinphoneChatMessage *)ptr);
return app_data ? env->NewStringUTF(app_data) : NULL;
}
extern "C" void Java_org_linphone_core_LinphoneChatMessageImpl_setAppData(JNIEnv* env, jobject thiz, jlong ptr, jstring appdata) {
const char * data = appdata ? env->GetStringUTFChars(appdata, NULL) : NULL;
linphone_chat_message_set_appdata((LinphoneChatMessage *)ptr, data);
if (appdata)
env->ReleaseStringUTFChars(appdata, data);
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setFileTransferServer(JNIEnv* env, jobject thiz, jlong ptr, jstring server_url) {
const char * url = server_url ? env->GetStringUTFChars(server_url, NULL) : NULL;
linphone_core_set_file_transfer_server((LinphoneCore *)ptr, url);
if (server_url)
env->ReleaseStringUTFChars(server_url, url);
}
extern "C" jstring Java_org_linphone_core_LinphoneCoreImpl_getFileTransferServer(JNIEnv* env, jobject thiz, jlong ptr) {
const char * server_url = linphone_core_get_file_transfer_server((LinphoneCore *)ptr);
return server_url ? env->NewStringUTF(server_url) : NULL;
}
extern "C" void Java_org_linphone_core_LinphoneChatMessageImpl_store(JNIEnv* env
,jobject thiz
,jlong ptr) {
@ -2559,6 +2777,12 @@ extern "C" jlong Java_org_linphone_core_LinphoneChatMessageImpl_getFrom(JNIEnv*
return (jlong) linphone_chat_message_get_from((LinphoneChatMessage*)ptr);
}
extern "C" jlong Java_org_linphone_core_LinphoneChatMessageImpl_getTo(JNIEnv* env
,jobject thiz
,jlong ptr) {
return (jlong) linphone_chat_message_get_to((LinphoneChatMessage*)ptr);
}
extern "C" jlong Java_org_linphone_core_LinphoneChatMessageImpl_getPeerAddress(JNIEnv* env
,jobject thiz
,jlong ptr) {
@ -2676,6 +2900,13 @@ extern "C" void Java_org_linphone_core_LinphoneChatRoomImpl_sendMessage2(JNIEnv*
linphone_chat_room_send_message2((LinphoneChatRoom*)chatroom_ptr, (LinphoneChatMessage*)messagePtr, chat_room_impl_callback, (void*)listener);
}
extern "C" void Java_org_linphone_core_LinphoneChatMessageImpl_startFileDownload(JNIEnv* env, jobject thiz, jlong ptr, jobject jlistener) {
jobject listener = env->NewGlobalRef(jlistener);
LinphoneChatMessage * message = (LinphoneChatMessage *)ptr;
message->cb_ud = listener;
linphone_chat_message_start_file_download(message, chat_room_impl_callback);
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setVideoWindowId(JNIEnv* env
,jobject thiz
,jlong lc
@ -3024,6 +3255,19 @@ JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneProxyConfigImpl_getQual
return jvalue;
}
JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneProxyConfigImpl_setRealm(JNIEnv *env, jobject thiz, jlong ptr, jstring jrealm) {
if (jrealm){
const char *realm=env->GetStringUTFChars(jrealm, NULL);
linphone_proxy_config_set_realm((LinphoneProxyConfig *)ptr, realm);
env->ReleaseStringUTFChars(jrealm,realm);
}
}
JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneProxyConfigImpl_getRealm(JNIEnv *env, jobject thiz, jlong ptr) {
jstring jvalue = env->NewStringUTF(linphone_proxy_config_get_realm((LinphoneProxyConfig *)ptr));
return jvalue;
}
extern "C" jint Java_org_linphone_core_LinphoneCallImpl_getDuration(JNIEnv* env,jobject thiz,jlong ptr) {
return (jint)linphone_call_get_duration((LinphoneCall *) ptr);
}
@ -3293,6 +3537,60 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_tunnelAddServerAndMirror
env->ReleaseStringUTFChars(jHost, cHost);
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_tunnelAddServer(JNIEnv *env, jobject thiz, jlong pCore, jobject config) {
LinphoneTunnel *tunnel = linphone_core_get_tunnel((LinphoneCore *)pCore);
if(tunnel != NULL) {
jclass TunnelConfigClass = env->FindClass("org/linphone/core/TunnelConfig");
jmethodID getHostMethod = env->GetMethodID(TunnelConfigClass, "getHost", "()Ljava/lang/String;");
jmethodID getPortMethod = env->GetMethodID(TunnelConfigClass, "getPort", "()I");
jmethodID getRemoteUdpMirrorPortMethod = env->GetMethodID(TunnelConfigClass, "getRemoteUdpMirrorPort", "()I");
jmethodID getDelayMethod = env->GetMethodID(TunnelConfigClass, "getDelay", "()I");
jstring hostString = (jstring)env->CallObjectMethod(config, getHostMethod);
const char *host = env->GetStringUTFChars(hostString, NULL);
if(host == NULL || strlen(host)==0) {
ms_error("LinphoneCore.tunnelAddServer(): no tunnel host defined");
}
LinphoneTunnelConfig *tunnelConfig = linphone_tunnel_config_new();
linphone_tunnel_config_set_host(tunnelConfig, host);
linphone_tunnel_config_set_port(tunnelConfig, env->CallIntMethod(config, getPortMethod));
linphone_tunnel_config_set_remote_udp_mirror_port(tunnelConfig, env->CallIntMethod(config, getRemoteUdpMirrorPortMethod));
linphone_tunnel_config_set_delay(tunnelConfig, env->CallIntMethod(config, getDelayMethod));
linphone_tunnel_add_server(tunnel, tunnelConfig);
env->ReleaseStringUTFChars(hostString, host);
} else {
ms_error("LinphoneCore.tunnelAddServer(): tunnel feature is not enabled");
}
}
extern "C" jobjectArray Java_org_linphone_core_LinphoneCoreImpl_tunnelGetServers(JNIEnv *env, jobject thiz, jlong pCore) {
LinphoneTunnel *tunnel = linphone_core_get_tunnel((LinphoneCore *)pCore);
jclass TunnelConfigClass = env->FindClass("org/linphone/core/TunnelConfig");
jmethodID setHostMethod = env->GetMethodID(TunnelConfigClass, "setHost", "(Ljava/lang/String;)V");
jmethodID setPortMethod = env->GetMethodID(TunnelConfigClass, "setPort", "(I)V");
jmethodID setRemoteUdpMirrorPortMethod = env->GetMethodID(TunnelConfigClass, "setRemoteUdpMirrorPort", "(I)V");
jmethodID setDelayMethod = env->GetMethodID(TunnelConfigClass, "setDelay", "(I)V");
jobjectArray tunnelConfigArray = NULL;
if(tunnel != NULL) {
const MSList *servers = linphone_tunnel_get_servers(tunnel);
const MSList *it;
int i;
ms_message("servers=%p", (void *)servers);
ms_message("taille=%i", ms_list_size(servers));
tunnelConfigArray = env->NewObjectArray(ms_list_size(servers), TunnelConfigClass, NULL);
for(it = servers, i=0; it != NULL; it = it->next, i++) {
const LinphoneTunnelConfig *conf = (const LinphoneTunnelConfig *)it->data;
jobject elt = env->AllocObject(TunnelConfigClass);
env->CallVoidMethod(elt, setHostMethod, env->NewStringUTF(linphone_tunnel_config_get_host(conf)));
env->CallVoidMethod(elt, setPortMethod, linphone_tunnel_config_get_port(conf));
env->CallVoidMethod(elt, setRemoteUdpMirrorPortMethod, linphone_tunnel_config_get_remote_udp_mirror_port(conf));
env->CallVoidMethod(elt, setDelayMethod, linphone_tunnel_config_get_delay(conf));
env->SetObjectArrayElement(tunnelConfigArray, i, elt);
}
}
return tunnelConfigArray;
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_tunnelSetHttpProxy(JNIEnv *env,jobject thiz,jlong pCore,
jstring jHost, jint port, jstring username, jstring password) {
@ -3323,6 +3621,37 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_tunnelEnable(JNIEnv *env
linphone_tunnel_enable(tunnel, enable);
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_tunnelSetMode(JNIEnv *env, jobject thiz, jlong pCore, jint mode) {
LinphoneTunnel *tunnel = ((LinphoneCore *)pCore)->tunnel;
if(tunnel != NULL) {
linphone_tunnel_set_mode(tunnel, (LinphoneTunnelMode)mode);
}
}
extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_tunnelGetMode(JNIEnv *env, jobject thiz, jlong pCore) {
LinphoneTunnel *tunnel = ((LinphoneCore *)pCore)->tunnel;
if(tunnel != NULL) {
return (jint)linphone_tunnel_get_mode(tunnel);
} else {
return 0;
}
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_tunnelEnableSip(JNIEnv *env, jobject thiz, jlong pCore, jboolean enable) {
LinphoneTunnel *tunnel = ((LinphoneCore *)pCore)->tunnel;
if(tunnel != NULL) {
linphone_tunnel_enable_sip(tunnel, (bool_t)enable);
}
}
extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_tunnelSipEnabled(JNIEnv *env, jobject thiz, jlong pCore) {
LinphoneTunnel *tunnel = ((LinphoneCore *)pCore)->tunnel;
if(tunnel != NULL) {
return (jboolean)linphone_tunnel_sip_enabled(tunnel);
} else {
return JNI_FALSE;
}
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setUserAgent(JNIEnv *env,jobject thiz,jlong pCore, jstring name, jstring version){
const char* cname=env->GetStringUTFChars(name, NULL);
@ -3363,6 +3692,14 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setCpuCountNative(JNIEnv
ms_set_cpu_count(count);
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setAudioJittcomp(JNIEnv *env, jobject thiz, jlong lc, jint value) {
linphone_core_set_audio_jittcomp((LinphoneCore *)lc, value);
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setVideoJittcomp(JNIEnv *env, jobject thiz, jlong lc, jint value) {
linphone_core_set_video_jittcomp((LinphoneCore *)lc, value);
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setAudioPort(JNIEnv *env, jobject thiz, jlong lc, jint port) {
linphone_core_set_audio_port((LinphoneCore *)lc, port);
}
@ -3383,6 +3720,13 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setAudioDscp(JNIEnv* env
linphone_core_set_audio_dscp((LinphoneCore*)ptr,dscp);
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setAndroidPowerManager(JNIEnv *env, jclass cls, jobject pm) {
#ifdef ANDROID
if(pm != NULL) bellesip_wake_lock_init(env, pm);
else bellesip_wake_lock_uninit(env);
#endif
}
extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_getAudioDscp(JNIEnv* env,jobject thiz,jlong ptr){
return linphone_core_get_audio_dscp((LinphoneCore*)ptr);
}
@ -3629,22 +3973,25 @@ extern "C" jintArray Java_org_linphone_core_LpConfigImpl_getIntRange(JNIEnv *env
static jobject create_java_linphone_content(JNIEnv *env, const LinphoneContent *content){
jclass contentClass;
jmethodID ctor;
jstring jtype, jsubtype, jencoding;
jbyteArray jdata=NULL;
jstring jtype, jsubtype, jencoding, jname;
jbyteArray jdata = NULL;
jint jsize = 0;
contentClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneContentImpl"));
ctor = env->GetMethodID(contentClass,"<init>", "(Ljava/lang/String;Ljava/lang/String;[BLjava/lang/String;)V");
ctor = env->GetMethodID(contentClass,"<init>", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[BLjava/lang/String;I)V");
jtype=env->NewStringUTF(content->type);
jsubtype=env->NewStringUTF(content->subtype);
jencoding=content->encoding ? env->NewStringUTF(content->encoding) : NULL;
jtype = env->NewStringUTF(content->type);
jsubtype = env->NewStringUTF(content->subtype);
jencoding = content->encoding ? env->NewStringUTF(content->encoding) : NULL;
jname = content->name ? env->NewStringUTF(content->name) : NULL;
jsize = (jint) content->size;
if (content->data){
jdata=env->NewByteArray(content->size);
env->SetByteArrayRegion(jdata,0,content->size,(jbyte*)content->data);
jdata = env->NewByteArray(content->size);
env->SetByteArrayRegion(jdata, 0, content->size, (jbyte*)content->data);
}
jobject jobj=env->NewObject(contentClass,ctor,jtype, jsubtype, jdata,jencoding);
jobject jobj = env->NewObject(contentClass, ctor, jname, jtype, jsubtype, jdata, jencoding, jsize);
env->DeleteGlobalRef(contentClass);
return jobj;
}

View file

@ -356,7 +356,8 @@ LINPHONE_PUBLIC void linphone_core_reject_subscriber(LinphoneCore *lc, LinphoneF
/**
* Get Buddy list of LinphoneFriend
* @param lc #LinphoneCore object
* @param[in] lc #LinphoneCore object
* @return \mslist{LinphoneFriend}
*/
LINPHONE_PUBLIC const MSList * linphone_core_get_friend_list(const LinphoneCore *lc);

View file

@ -752,7 +752,7 @@ LINPHONE_PUBLIC void linphone_presence_model_set_user_data(LinphonePresenceModel
* @param[in] model The #LinphonePresenceModel object for which to get the user data.
* @return A pointer to the user data.
*/
LINPHONE_PUBLIC void * linphone_presence_model_get_user_data(LinphonePresenceModel *model);
LINPHONE_PUBLIC void * linphone_presence_model_get_user_data(const LinphonePresenceModel *model);
/**
* Increase the reference count of the #LinphonePresenceService object.
@ -780,7 +780,7 @@ LINPHONE_PUBLIC void linphone_presence_service_set_user_data(LinphonePresenceSer
* @param[in] service The #LinphonePresenceService object for which to get the user data.
* @return A pointer to the user data.
*/
LINPHONE_PUBLIC void * linphone_presence_service_get_user_data(LinphonePresenceService *service);
LINPHONE_PUBLIC void * linphone_presence_service_get_user_data(const LinphonePresenceService *service);
/**
* Increase the reference count of the #LinphonePresencePerson object.
@ -808,7 +808,7 @@ LINPHONE_PUBLIC void linphone_presence_person_set_user_data(LinphonePresencePers
* @param[in] person The #LinphonePresencePerson object for which to get the user data.
* @return A pointer to the user data.
*/
LINPHONE_PUBLIC void * linphone_presence_person_get_user_data(LinphonePresencePerson *person);
LINPHONE_PUBLIC void * linphone_presence_person_get_user_data(const LinphonePresencePerson *person);
/**
* Increase the reference count of the #LinphonePresenceActivity object.
@ -836,7 +836,7 @@ LINPHONE_PUBLIC void linphone_presence_activity_set_user_data(LinphonePresenceAc
* @param[in] activity The #LinphonePresenceActivity object for which to get the user data.
* @return A pointer to the user data.
*/
LINPHONE_PUBLIC void * linphone_presence_activity_get_user_data(LinphonePresenceActivity *activity);
LINPHONE_PUBLIC void * linphone_presence_activity_get_user_data(const LinphonePresenceActivity *activity);
/**
* Increase the reference count of the #LinphonePresenceNote object.
@ -864,7 +864,7 @@ LINPHONE_PUBLIC void linphone_presence_note_set_user_data(LinphonePresenceNote *
* @param[in] note The #LinphonePresenceNote object for which to get the user data.
* @return A pointer to the user data.
*/
LINPHONE_PUBLIC void * linphone_presence_note_get_user_data(LinphonePresenceNote *note);
LINPHONE_PUBLIC void * linphone_presence_note_get_user_data(const LinphonePresenceNote *note);
/*****************************************************************************

View file

@ -29,7 +29,7 @@ struct _lpc2xml_context {
const LpConfig *lpc;
lpc2xml_function cbf;
void *ctx;
xmlDoc *doc;
char errorBuffer[LPC2XML_BZ];
char warningBuffer[LPC2XML_BZ];
@ -42,7 +42,7 @@ lpc2xml_context* lpc2xml_context_new(lpc2xml_function cbf, void *ctx) {
xmlCtx->lpc = NULL;
xmlCtx->cbf = cbf;
xmlCtx->ctx = ctx;
xmlCtx->doc = NULL;
xmlCtx->errorBuffer[0]='\0';
xmlCtx->warningBuffer[0]='\0';
@ -64,8 +64,8 @@ static void lpc2xml_context_clear_logs(lpc2xml_context *ctx) {
}
static void lpc2xml_log(lpc2xml_context *xmlCtx, int level, const char *fmt, ...) {
va_list args;
va_start(args, fmt);
va_list args;
va_start(args, fmt);
if(xmlCtx->cbf != NULL) {
xmlCtx->cbf((xmlCtx)->ctx, level, fmt, args);
}
@ -75,8 +75,8 @@ static void lpc2xml_log(lpc2xml_context *xmlCtx, int level, const char *fmt, ...
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);
va_list args;
va_start(args, fmt);
vsnprintf(xmlCtx->errorBuffer + sl, LPC2XML_BZ-sl, fmt, args);
va_end(args);
}
@ -85,8 +85,8 @@ static void lpc2xml_genericxml_error(void *ctx, const char *fmt, ...) {
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);
va_list args;
va_start(args, fmt);
vsnprintf(xmlCtx->warningBuffer + sl, LPC2XML_BZ-sl, fmt, args);
va_end(args);
}
@ -114,25 +114,27 @@ struct __processSectionCtx {
static void processSection_cb(const char *entry, struct __processSectionCtx *ctx) {
if(ctx->ret == 0) {
const char *comment = "#";
xmlNode *node;
xmlAttr *name_attr;
if (strncmp(comment, entry, strlen(comment)) == 0) {
lpc2xml_log(ctx->ctx, LPC2XML_WARNING, "Skipped commented entry %s", entry);
ctx->ret = 0;
return;
}
xmlNode *node = xmlNewChild(ctx->node, NULL, (const xmlChar *)"entry", NULL);
node = xmlNewChild(ctx->node, NULL, (const xmlChar *)"entry", NULL);
if(node == NULL) {
lpc2xml_log(ctx->ctx, LPC2XML_ERROR, "Can't create \"entry\" element");
ctx->ret = -1;
return;
}
xmlAttr *name_attr = xmlSetProp(node, (const xmlChar *)"name", (const xmlChar *)entry);
name_attr = xmlSetProp(node, (const xmlChar *)"name", (const xmlChar *)entry);
if(name_attr == NULL) {
lpc2xml_log(ctx->ctx, LPC2XML_ERROR, "Can't create name attribute for \"entry\" element");
ctx->ret = -1;
return;
}
ctx->ret = processEntry(ctx->section, entry, node, ctx->ctx);
}
}
@ -154,12 +156,13 @@ struct __processConfigCtx {
static void processConfig_cb(const char *section, struct __processConfigCtx *ctx) {
if(ctx->ret == 0) {
xmlNode *node = xmlNewChild(ctx->node, NULL, (const xmlChar *)"section", NULL);
xmlAttr *name_attr;
if(node == NULL) {
lpc2xml_log(ctx->ctx, LPC2XML_ERROR, "Can't create \"section\" element");
ctx->ret = -1;
return;
}
xmlAttr *name_attr = xmlSetProp(node, (const xmlChar *)"name", (const xmlChar *)section);
name_attr = xmlSetProp(node, (const xmlChar *)"name", (const xmlChar *)section);
if(name_attr == NULL) {
lpc2xml_log(ctx->ctx, LPC2XML_ERROR, "Can't create name attribute for \"section\" element");
ctx->ret = -1;
@ -177,22 +180,25 @@ static int processConfig(xmlNode *node, lpc2xml_context *ctx) {
static int processDoc(xmlDoc *doc, lpc2xml_context *ctx) {
int ret = 0;
xmlNs *xsi_ns;
xmlNs *lpc_ns;
xmlAttr *schemaLocation;
xmlNode *root_node = xmlNewNode(NULL, (const xmlChar *)"config");
if(root_node == NULL) {
lpc2xml_log(ctx, LPC2XML_ERROR, "Can't create \"config\" element");
return -1;
}
xmlNs *lpc_ns = xmlNewNs(root_node, (const xmlChar *)"http://www.linphone.org/xsds/lpconfig.xsd", NULL);
lpc_ns = xmlNewNs(root_node, (const xmlChar *)"http://www.linphone.org/xsds/lpconfig.xsd", NULL);
if(lpc_ns == NULL) {
lpc2xml_log(ctx, LPC2XML_WARNING, "Can't create lpc namespace");
} else {
xmlSetNs(root_node, lpc_ns);
}
xmlNs *xsi_ns = xmlNewNs(root_node, (const xmlChar *)"http://www.w3.org/2001/XMLSchema-instance", (const xmlChar *)"xsi");
xsi_ns = xmlNewNs(root_node, (const xmlChar *)"http://www.w3.org/2001/XMLSchema-instance", (const xmlChar *)"xsi");
if(lpc_ns == NULL) {
lpc2xml_log(ctx, LPC2XML_WARNING, "Can't create xsi namespace");
}
xmlAttr *schemaLocation = xmlNewNsProp(root_node, xsi_ns, (const xmlChar *)"schemaLocation", (const xmlChar *)"http://www.linphone.org/xsds/lpconfig.xsd lpconfig.xsd");
schemaLocation = xmlNewNsProp(root_node, xsi_ns, (const xmlChar *)"schemaLocation", (const xmlChar *)"http://www.linphone.org/xsds/lpconfig.xsd lpconfig.xsd");
if(schemaLocation == NULL) {
lpc2xml_log(ctx, LPC2XML_WARNING, "Can't create schemaLocation");
}
@ -203,12 +209,13 @@ static int processDoc(xmlDoc *doc, lpc2xml_context *ctx) {
static int internal_convert_lpc2xml(lpc2xml_context *ctx) {
int ret = 0;
xmlDoc *doc;
lpc2xml_log(ctx, LPC2XML_DEBUG, "Generation started");
if(ctx->doc != NULL) {
xmlFreeDoc(ctx->doc);
ctx->doc = NULL;
}
xmlDoc *doc = xmlNewDoc((const xmlChar *)"1.0");
doc = xmlNewDoc((const xmlChar *)"1.0");
ret = processDoc(doc, ctx);
if(ret == 0) {
ctx->doc = doc;
@ -226,9 +233,10 @@ int lpc2xml_set_lpc(lpc2xml_context* context, const LpConfig *lpc) {
int lpc2xml_convert_file(lpc2xml_context* context, const char *filename) {
int ret = -1;
xmlSaveCtxtPtr save_ctx;
lpc2xml_context_clear_logs(context);
xmlSetGenericErrorFunc(context, lpc2xml_genericxml_error);
xmlSaveCtxtPtr save_ctx = xmlSaveToFilename(filename, "UTF-8", XML_SAVE_FORMAT);
save_ctx = xmlSaveToFilename(filename, "UTF-8", XML_SAVE_FORMAT);
if(save_ctx != NULL) {
ret = internal_convert_lpc2xml(context);
if(ret == 0) {
@ -248,9 +256,10 @@ int lpc2xml_convert_file(lpc2xml_context* context, const char *filename) {
int lpc2xml_convert_fd(lpc2xml_context* context, int fd) {
int ret = -1;
xmlSaveCtxtPtr save_ctx;
lpc2xml_context_clear_logs(context);
xmlSetGenericErrorFunc(context, lpc2xml_genericxml_error);
xmlSaveCtxtPtr save_ctx = xmlSaveToFd(fd, "UTF-8", XML_SAVE_FORMAT);
save_ctx = xmlSaveToFd(fd, "UTF-8", XML_SAVE_FORMAT);
if(save_ctx != NULL) {
ret = internal_convert_lpc2xml(context);
if(ret == 0) {
@ -271,9 +280,10 @@ int lpc2xml_convert_fd(lpc2xml_context* context, int fd) {
int lpc2xml_convert_string(lpc2xml_context* context, char **content) {
int ret = -1;
xmlBufferPtr buffer = xmlBufferCreate();
xmlSaveCtxtPtr save_ctx;
lpc2xml_context_clear_logs(context);
xmlSetGenericErrorFunc(context, lpc2xml_genericxml_error);
xmlSaveCtxtPtr save_ctx = xmlSaveToBuffer(buffer, "UTF-8", XML_SAVE_FORMAT);
save_ctx = xmlSaveToBuffer(buffer, "UTF-8", XML_SAVE_FORMAT);
if(save_ctx != NULL) {
ret = internal_convert_lpc2xml(context);
if(ret == 0) {

View file

@ -39,6 +39,12 @@
#endif
#endif /*_WIN32_WCE*/
#ifdef _MSC_VER
#include <Shlwapi.h>
#else
#include <libgen.h>
#endif
#define lp_new0(type,n) (type*)calloc(sizeof(type),n)
@ -271,7 +277,7 @@ static LpSection* lp_config_parse_line(LpConfig* lpconfig, const char* line, LpS
/* remove ending white spaces */
for (; pos2>pos1 && pos2[-1]==' ';pos2--) pos2[-1]='\0';
if (pos2-pos1>=0){
if (pos2-pos1>0){
/* found a pair key,value */
if (cur!=NULL){
@ -457,10 +463,10 @@ int lp_config_get_int(const LpConfig *lpconfig,const char *section, const char *
const char *str=lp_config_get_string(lpconfig,section,key,NULL);
if (str!=NULL) {
int ret=0;
if (strstr(str,"0x")==str){
sscanf(str,"%x",&ret);
}else
}else
sscanf(str,"%i",&ret);
return ret;
}
@ -493,14 +499,14 @@ void lp_config_set_string(LpConfig *lpconfig,const char *section, const char *ke
if (sec!=NULL){
item=lp_section_find_item(sec,key);
if (item!=NULL){
if (value!=NULL)
if (value!=NULL && value[0] != '\0')
lp_item_set_value(item,value);
else lp_section_remove_item(sec,item);
}else{
if (value!=NULL)
if (value!=NULL && value[0] != '\0')
lp_section_add_item(sec,lp_item_new(key,value));
}
}else if (value!=NULL){
}else if (value!=NULL && value[0] != '\0'){
sec=lp_section_new(section);
lp_config_add_section(lpconfig,sec);
lp_section_add_item(sec,lp_item_new(key,value));
@ -542,12 +548,19 @@ void lp_config_set_float(LpConfig *lpconfig,const char *section, const char *key
void lp_item_write(LpItem *item, FILE *file){
if (item->is_comment)
fprintf(file,"%s",item->value);
else
else if (item->value && item->value[0] != '\0' )
fprintf(file,"%s=%s\n",item->key,item->value);
else {
ms_warning("Not writing item %s to file, it is empty", item->key);
}
}
void lp_section_param_write(LpSectionParam *param, FILE *file){
fprintf(file, " %s=%s", param->key, param->value);
if( param->value && param->value[0] != '\0') {
fprintf(file, " %s=%s", param->key, param->value);
} else {
ms_warning("Not writing param %s to file, it is empty", param->key);
}
}
void lp_section_write(LpSection *sec, FILE *file){
@ -650,3 +663,57 @@ const char* lp_config_get_default_string(const LpConfig *lpconfig, const char *s
return lp_config_get_string(lpconfig, default_section, key, default_value);
}
static char *_lp_config_dirname(char *path) {
#ifdef _MSC_VER
char *dir = ms_strdup(path);
PathRemoveFileSpec(dir);
return dir;
#else
char *tmp = ms_strdup(path);
char *dir = ms_strdup(dirname(tmp));
ms_free(tmp);
return dir;
#endif
}
void lp_config_write_relative_file(const LpConfig *lpconfig, const char *filename, const char *data) {
if(strlen(data) > 0) {
char *dir = _lp_config_dirname(lpconfig->filename);
char *filepath = ms_strdup_printf("%s/%s", dir, filename);
FILE *file = fopen(filepath, "w");
if(file != NULL) {
fprintf(file, "%s", data);
fclose(file);
} else {
ms_error("Could not open %s for write", filepath);
}
ms_free(dir);
ms_free(filepath);
} else {
ms_warning("%s has not been created because there is no data to write", filename);
}
}
char *lp_config_read_relative_file(const LpConfig *lpconfig, const char *filename) {
char *dir = _lp_config_dirname(lpconfig->filename);
char *filepath = ms_strdup_printf("%s/%s", dir, filename);
char *result = NULL;
if(ortp_file_exist(filepath) == 0) {
FILE *file = fopen(filepath, "r");
if(file != NULL) {
result = ms_new0(char, MAX_LEN);
if(fgets(result, MAX_LEN, file) == NULL) {
ms_error("%s could not be loaded", filepath);
}
fclose(file);
} else {
ms_error("Could not open %s for read", filepath);
}
} else {
ms_message("%s does not exist", filepath);
}
ms_free(dir);
ms_free(filepath);
return result;
}

View file

@ -272,6 +272,22 @@ LINPHONE_PUBLIC LpConfig *lp_config_ref(LpConfig *lpconfig);
**/
LINPHONE_PUBLIC void lp_config_unref(LpConfig *lpconfig);
/**
* @brief Write a string in a file placed relatively with the Linphone configuration file.
* @param lpconfig LpConfig instance used as a reference
* @param filename Name of the file where to write data. The name is relative to the place of the config file
* @param data String to write
*/
LINPHONE_PUBLIC void lp_config_write_relative_file(const LpConfig *lpconfig, const char *filename, const char *data);
/**
* @brief Read a string from a file placed relatively with the Linphone configuration file
* @param lpconfig LpConfig instance used as a reference
* @param filename Name of the file where data will be read from. The name is relative to the place of the config file
* @return The read string
*/
LINPHONE_PUBLIC char *lp_config_read_relative_file(const LpConfig *lpconfig, const char *filename);
#ifdef __cplusplus
}
#endif

View file

@ -37,6 +37,49 @@ static inline LinphoneChatMessage* get_transient_message(LinphoneChatRoom* cr, u
return NULL;
}
/* DB layout:
* | 0 | storage_id
* | 1 | type
* | 2 | subtype
* | 3 | name
* | 4 | encoding
* | 5 | size
* | 6 | data
*/
// Callback for sql request when getting linphone content
static int callback_content(void *data, int argc, char **argv, char **colName) {
LinphoneChatMessage *message = (LinphoneChatMessage *)data;
if (message->file_transfer_information) {
linphone_content_uninit(message->file_transfer_information);
ms_free(message->file_transfer_information);
message->file_transfer_information = NULL;
}
message->file_transfer_information = (LinphoneContent *)malloc(sizeof(LinphoneContent));
memset(message->file_transfer_information, 0, sizeof(*(message->file_transfer_information)));
message->file_transfer_information->type = argv[1] ? ms_strdup(argv[1]) : NULL;
message->file_transfer_information->subtype = argv[2] ? ms_strdup(argv[2]) : NULL;
message->file_transfer_information->name = argv[3] ? ms_strdup(argv[3]) : NULL;
message->file_transfer_information->encoding = argv[4] ? ms_strdup(argv[4]) : NULL;
message->file_transfer_information->size = (size_t) atoi(argv[5]);
return 0;
}
static void fetch_content_from_database(sqlite3 *db, LinphoneChatMessage *message, int content_id) {
char* errmsg = NULL;
int ret;
char * buf;
buf = sqlite3_mprintf("SELECT * FROM content WHERE id = %i", content_id);
ret = sqlite3_exec(db, buf, callback_content, message, &errmsg);
if (ret != SQLITE_OK) {
ms_error("Error in creation: %s.", errmsg);
sqlite3_free(errmsg);
}
sqlite3_free(buf);
}
/* DB layout:
* | 0 | storage_id
@ -50,10 +93,12 @@ static inline LinphoneChatMessage* get_transient_message(LinphoneChatRoom* cr, u
* | 8 | external body url
* | 9 | utc timestamp
* | 10 | app data text
* | 11 | linphone content
*/
static void create_chat_message(char **argv, void *data){
LinphoneChatRoom *cr = (LinphoneChatRoom *)data;
LinphoneAddress *from;
LinphoneAddress *to;
unsigned int storage_id = atoi(argv[0]);
@ -65,12 +110,18 @@ static void create_chat_message(char **argv, void *data){
if(atoi(argv[3])==LinphoneChatMessageIncoming){
new_message->dir=LinphoneChatMessageIncoming;
from=linphone_address_new(argv[2]);
to=linphone_address_new(argv[1]);
} else {
new_message->dir=LinphoneChatMessageOutgoing;
from=linphone_address_new(argv[1]);
to=linphone_address_new(argv[2]);
}
linphone_chat_message_set_from(new_message,from);
linphone_address_destroy(from);
if (to){
linphone_chat_message_set_to(new_message,to);
linphone_address_destroy(to);
}
if( argv[9] != NULL ){
new_message->time = (time_t)atol(argv[9]);
@ -83,6 +134,13 @@ static void create_chat_message(char **argv, void *data){
new_message->storage_id=storage_id;
new_message->external_body_url= argv[8] ? ms_strdup(argv[8]) : NULL;
new_message->appdata = argv[10]? ms_strdup(argv[10]) : NULL;
if (argv[11] != NULL) {
int id = atoi(argv[11]);
if (id >= 0) {
fetch_content_from_database(cr->lc->db, new_message, id);
}
}
}
cr->messages_hist=ms_list_prepend(cr->messages_hist,new_message);
}
@ -105,7 +163,7 @@ void linphone_sql_request_message(sqlite3 *db,const char *stmt,LinphoneChatRoom
int ret;
ret=sqlite3_exec(db,stmt,callback,cr,&errmsg);
if(ret != SQLITE_OK) {
ms_error("Error in creation: %s.\n", errmsg);
ms_error("Error in creation: %s.", errmsg);
sqlite3_free(errmsg);
}
}
@ -115,7 +173,7 @@ int linphone_sql_request(sqlite3* db,const char *stmt){
int ret;
ret=sqlite3_exec(db,stmt,NULL,NULL,&errmsg);
if(ret != SQLITE_OK) {
ms_error("linphone_sql_request: error sqlite3_exec(): %s.\n", errmsg);
ms_error("linphone_sql_request: statement %s -> error sqlite3_exec(): %s.", stmt, errmsg);
sqlite3_free(errmsg);
}
return ret;
@ -127,29 +185,59 @@ void linphone_sql_request_all(sqlite3* db,const char *stmt, LinphoneCore* lc){
int ret;
ret=sqlite3_exec(db,stmt,callback_all,lc,&errmsg);
if(ret != SQLITE_OK) {
ms_error("linphone_sql_request_all: error sqlite3_exec(): %s.\n", errmsg);
ms_error("linphone_sql_request_all: error sqlite3_exec(): %s.", errmsg);
sqlite3_free(errmsg);
}
}
static int linphone_chat_message_store_content(LinphoneChatMessage *msg) {
LinphoneCore *lc = linphone_chat_room_get_lc(msg->chat_room);
int id = -1;
if (lc->db) {
LinphoneContent *content = msg->file_transfer_information;
char *buf = sqlite3_mprintf("INSERT INTO content VALUES(NULL,%Q,%Q,%Q,%Q,%i,%Q);",
content->type,
content->subtype,
content->name,
content->encoding,
content->size,
NULL
);
linphone_sql_request(lc->db, buf);
sqlite3_free(buf);
id = (unsigned int) sqlite3_last_insert_rowid (lc->db);
}
return id;
}
unsigned int linphone_chat_message_store(LinphoneChatMessage *msg){
LinphoneCore *lc=linphone_chat_room_get_lc(msg->chat_room);
int id=0;
int id = 0;
if (lc->db){
char *peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(msg->chat_room));
char *local_contact=linphone_address_as_string_uri_only(linphone_chat_message_get_local_address(msg));
char *buf=sqlite3_mprintf("INSERT INTO history VALUES(NULL,%Q,%Q,%i,%Q,%Q,%i,%i,%Q,%i,%Q);",
int content_id = -1;
char *peer;
char *local_contact;
char *buf;
if (msg->file_transfer_information) {
content_id = linphone_chat_message_store_content(msg);
}
peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(msg->chat_room));
local_contact=linphone_address_as_string_uri_only(linphone_chat_message_get_local_address(msg));
buf=sqlite3_mprintf("INSERT INTO history VALUES(NULL,%Q,%Q,%i,%Q,%Q,%i,%i,%Q,%i,%Q,%i);",
local_contact,
peer,
msg->dir,
msg->message,
"-1", /* use UTC field now */
msg->is_read,
msg->state,
msg->external_body_url,
msg->time,
msg->appdata);
peer,
msg->dir,
msg->message,
"-1", /* use UTC field now */
msg->is_read,
msg->state,
msg->external_body_url,
msg->time,
msg->appdata,
content_id
);
linphone_sql_request(lc->db,buf);
sqlite3_free(buf);
ms_free(local_contact);
@ -162,8 +250,8 @@ unsigned int linphone_chat_message_store(LinphoneChatMessage *msg){
void linphone_chat_message_store_state(LinphoneChatMessage *msg){
LinphoneCore *lc=msg->chat_room->lc;
if (lc->db){
char *buf=sqlite3_mprintf("UPDATE history SET status=%i WHERE (message = %Q OR url = %Q) AND utc = %i;",
msg->state,msg->message,msg->external_body_url,msg->time);
char *buf=sqlite3_mprintf("UPDATE history SET status=%i WHERE (id = %i) AND utc = %i;",
msg->state,msg->storage_id,msg->time);
linphone_sql_request(lc->db,buf);
sqlite3_free(buf);
}
@ -189,11 +277,13 @@ void linphone_chat_message_store_appdata(LinphoneChatMessage* msg){
void linphone_chat_room_mark_as_read(LinphoneChatRoom *cr){
LinphoneCore *lc=linphone_chat_room_get_lc(cr);
int read=1;
char *peer;
char *buf;
if (lc->db==NULL) return ;
char *peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr));
char *buf=sqlite3_mprintf("UPDATE history SET read=%i WHERE remoteContact = %Q;",
peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr));
buf=sqlite3_mprintf("UPDATE history SET read=%i WHERE remoteContact = %Q;",
read,peer);
linphone_sql_request(lc->db,buf);
sqlite3_free(buf);
@ -202,24 +292,28 @@ void linphone_chat_room_mark_as_read(LinphoneChatRoom *cr){
void linphone_chat_room_update_url(LinphoneChatRoom *cr, LinphoneChatMessage *msg) {
LinphoneCore *lc=linphone_chat_room_get_lc(cr);
char *buf;
if (lc->db==NULL) return ;
char *buf=sqlite3_mprintf("UPDATE history SET url=%Q WHERE id=%i;",msg->external_body_url,msg->storage_id);
buf=sqlite3_mprintf("UPDATE history SET url=%Q WHERE id=%i;",msg->external_body_url,msg->storage_id);
linphone_sql_request(lc->db,buf);
sqlite3_free(buf);
}
int linphone_chat_room_get_unread_messages_count(LinphoneChatRoom *cr){
static int linphone_chat_room_get_messages_count(LinphoneChatRoom *cr, bool_t unread_only){
LinphoneCore *lc=linphone_chat_room_get_lc(cr);
int numrows=0;
char *peer;
char *buf;
sqlite3_stmt *selectStatement;
int returnValue;
if (lc->db==NULL) return 0;
char *peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr));
char *buf=sqlite3_mprintf("SELECT count(*) FROM history WHERE remoteContact = %Q AND read = 0;",peer);
sqlite3_stmt *selectStatement;
int returnValue = sqlite3_prepare_v2(lc->db,buf,-1,&selectStatement,NULL);
peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr));
buf=sqlite3_mprintf("SELECT count(*) FROM history WHERE remoteContact = %Q %s;",peer,unread_only?"AND read = 0":"");
returnValue = sqlite3_prepare_v2(lc->db,buf,-1,&selectStatement,NULL);
if (returnValue == SQLITE_OK){
if(sqlite3_step(selectStatement) == SQLITE_ROW){
numrows= sqlite3_column_int(selectStatement, 0);
@ -231,53 +325,85 @@ int linphone_chat_room_get_unread_messages_count(LinphoneChatRoom *cr){
return numrows;
}
int linphone_chat_room_get_unread_messages_count(LinphoneChatRoom *cr){
return linphone_chat_room_get_messages_count(cr, TRUE);
}
int linphone_chat_room_get_history_size(LinphoneChatRoom *cr){
return linphone_chat_room_get_messages_count(cr, FALSE);
}
void linphone_chat_room_delete_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg) {
LinphoneCore *lc=cr->lc;
char *buf;
if (lc->db==NULL) return ;
char *buf=sqlite3_mprintf("DELETE FROM history WHERE id = %i;", msg->storage_id);
buf=sqlite3_mprintf("DELETE FROM history WHERE id = %i;", msg->storage_id);
linphone_sql_request(lc->db,buf);
sqlite3_free(buf);
}
void linphone_chat_room_delete_history(LinphoneChatRoom *cr){
LinphoneCore *lc=cr->lc;
char *peer;
char *buf;
if (lc->db==NULL) return ;
char *peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr));
char *buf=sqlite3_mprintf("DELETE FROM history WHERE remoteContact = %Q;",peer);
peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr));
buf=sqlite3_mprintf("DELETE FROM history WHERE remoteContact = %Q;",peer);
linphone_sql_request(lc->db,buf);
sqlite3_free(buf);
ms_free(peer);
}
MSList *linphone_chat_room_get_history(LinphoneChatRoom *cr,int nb_message){
MSList *linphone_chat_room_get_history_range(LinphoneChatRoom *cr, int startm, int endm){
LinphoneCore *lc=linphone_chat_room_get_lc(cr);
MSList *ret;
char *buf;
char *peer;
uint64_t begin,end;
int buf_max_size = 512;
if (lc->db==NULL) return NULL;
peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr));
peer = linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr));
cr->messages_hist = NULL;
if (nb_message > 0)
buf=sqlite3_mprintf("SELECT * FROM history WHERE remoteContact = %Q ORDER BY id DESC LIMIT %i ;",peer,nb_message);
else
buf=sqlite3_mprintf("SELECT * FROM history WHERE remoteContact = %Q ORDER BY id DESC;",peer);
/*since we want to append query parameters depending on arguments given, we use malloc instead of sqlite3_mprintf*/
buf=ms_malloc(buf_max_size);
buf=sqlite3_snprintf(buf_max_size-1,buf,"SELECT * FROM history WHERE remoteContact = %Q ORDER BY id DESC",peer);
if (startm<0) startm=0;
if (endm>0&&endm>=startm){
buf=sqlite3_snprintf(buf_max_size-1,buf,"%s LIMIT %i ",buf,endm+1-startm);
}else if(startm>0){
ms_message("%s(): end is lower than start (%d < %d). No end assumed.",__FUNCTION__,endm,startm);
buf=sqlite3_snprintf(buf_max_size-1,buf,"%s LIMIT -1",buf);
}
if (startm>0){
buf=sqlite3_snprintf(buf_max_size-1,buf,"%s OFFSET %i ",buf,startm);
}
begin=ortp_get_cur_time_ms();
linphone_sql_request_message(lc->db,buf,cr);
end=ortp_get_cur_time_ms();
ms_message("linphone_chat_room_get_history(): completed in %i ms",(int)(end-begin));
sqlite3_free(buf);
ms_message("%s(): completed in %i ms",__FUNCTION__, (int)(end-begin));
ms_free(buf);
ret=cr->messages_hist;
cr->messages_hist=NULL;
ms_free(peer);
return ret;
}
MSList *linphone_chat_room_get_history(LinphoneChatRoom *cr,int nb_message){
return linphone_chat_room_get_history_range(cr, 0, nb_message);
}
void linphone_close_storage(sqlite3* db){
sqlite3_close(db);
}
@ -357,8 +483,9 @@ static void linphone_migrate_timestamps(sqlite3* db){
sqlite3_free(errmsg);
linphone_sql_request(db, "ROLLBACK");
} else {
uint64_t end;
linphone_sql_request(db, "COMMIT");
uint64_t end=ortp_get_cur_time_ms();
end=ortp_get_cur_time_ms();
ms_message("Migrated message timestamps to UTC in %i ms",(int)(end-begin));
}
}
@ -373,7 +500,7 @@ void linphone_update_table(sqlite3* db) {
ms_message("Table already up to date: %s.", errmsg);
sqlite3_free(errmsg);
} else {
ms_debug("Table updated successfully for URL.");
ms_debug("Table history updated successfully for URL.");
}
// for UTC timestamp storage
@ -382,7 +509,7 @@ void linphone_update_table(sqlite3* db) {
ms_message("Table already up to date: %s.", errmsg);
sqlite3_free(errmsg);
} else {
ms_debug("Table updated successfully for UTC.");
ms_debug("Table history updated successfully for UTC.");
// migrate from old text-based timestamps to unix time-based timestamps
linphone_migrate_timestamps(db);
}
@ -393,7 +520,32 @@ void linphone_update_table(sqlite3* db) {
ms_message("Table already up to date: %s.", errmsg);
sqlite3_free(errmsg);
} else {
ms_debug("Table updated successfully for app-specific data.");
ms_debug("Table history updated successfully for app-specific data.");
}
// new field for linphone content storage
ret=sqlite3_exec(db,"ALTER TABLE history ADD COLUMN content INTEGER;",NULL,NULL,&errmsg);
if(ret != SQLITE_OK) {
ms_message("Table already up to date: %s.", errmsg);
sqlite3_free(errmsg);
} else {
ms_debug("Table history updated successfully for content data.");
ret = sqlite3_exec(db,"CREATE TABLE IF NOT EXISTS content ("
"id INTEGER PRIMARY KEY AUTOINCREMENT,"
"type TEXT,"
"subtype TEXT,"
"name TEXT,"
"encoding TEXT,"
"size INTEGER,"
"data BLOB"
");",
0,0,&errmsg);
if(ret != SQLITE_OK) {
ms_error("Error in creation: %s.\n", errmsg);
sqlite3_free(errmsg);
} else {
ms_debug("Table content successfully created.");
}
}
}
@ -477,6 +629,10 @@ MSList *linphone_chat_room_get_history(LinphoneChatRoom *cr,int nb_message){
return NULL;
}
LINPHONE_PUBLIC MSList *linphone_chat_room_get_history_range(LinphoneChatRoom *cr, int begin, int end){
return NULL;
}
void linphone_chat_room_delete_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg) {
}
@ -499,4 +655,8 @@ int linphone_chat_room_get_unread_messages_count(LinphoneChatRoom *cr){
return 0;
}
int linphone_chat_room_get_history_size(LinphoneChatRoom *cr){
return 0;
}
#endif

View file

@ -69,7 +69,7 @@ static bool_t payload_type_enabled(const PayloadType *pt) {
return (((pt)->flags & PAYLOAD_TYPE_ENABLED)!=0);
}
bool_t linphone_core_payload_type_enabled(LinphoneCore *lc, const PayloadType *pt){
bool_t linphone_core_payload_type_enabled(LinphoneCore *lc, const LinphonePayloadType *pt){
if (ms_list_find(lc->codecs_conf.audio_codecs, (PayloadType*) pt) || ms_list_find(lc->codecs_conf.video_codecs, (PayloadType*)pt)){
return payload_type_enabled(pt);
}
@ -77,12 +77,12 @@ bool_t linphone_core_payload_type_enabled(LinphoneCore *lc, const PayloadType *p
return FALSE;
}
bool_t linphone_core_payload_type_is_vbr(LinphoneCore *lc, const PayloadType *pt){
bool_t linphone_core_payload_type_is_vbr(LinphoneCore *lc, const LinphonePayloadType *pt){
if (pt->type==PAYLOAD_VIDEO) return TRUE;
return !!(pt->flags & PAYLOAD_TYPE_IS_VBR);
}
int linphone_core_enable_payload_type(LinphoneCore *lc, PayloadType *pt, bool_t enabled){
int linphone_core_enable_payload_type(LinphoneCore *lc, LinphonePayloadType *pt, bool_t enabled){
if (ms_list_find(lc->codecs_conf.audio_codecs,pt) || ms_list_find(lc->codecs_conf.video_codecs,pt)){
payload_type_set_enable(pt,enabled);
_linphone_core_codec_config_write(lc);
@ -108,7 +108,7 @@ const char *linphone_core_get_payload_type_description(LinphoneCore *lc, Payload
return NULL;
}
void linphone_core_set_payload_type_bitrate(LinphoneCore *lc, PayloadType *pt, int bitrate){
void linphone_core_set_payload_type_bitrate(LinphoneCore *lc, LinphonePayloadType *pt, int bitrate){
if (ms_list_find(lc->codecs_conf.audio_codecs, (PayloadType*) pt) || ms_list_find(lc->codecs_conf.video_codecs, (PayloadType*)pt)){
if (pt->type==PAYLOAD_VIDEO || pt->flags & PAYLOAD_TYPE_IS_VBR){
pt->normal_bitrate=bitrate*1000;
@ -131,7 +131,7 @@ static double get_audio_payload_bandwidth_from_codec_bitrate(const PayloadType *
double npacket=50;
double packet_size;
int bitrate;
if (strcmp(payload_type_get_mime(&payload_type_aaceld_44k), payload_type_get_mime(pt))==0) {
/*special case of aac 44K because ptime= 10ms*/
npacket=100;
@ -181,7 +181,7 @@ static int get_audio_payload_bandwidth(LinphoneCore *lc, const PayloadType *pt,
}else return (int)ceil(get_audio_payload_bandwidth_from_codec_bitrate(pt)/1000.0);/*rounding codec bandwidth should be avoid, specially for AMR*/
}
int linphone_core_get_payload_type_bitrate(LinphoneCore *lc, const PayloadType *pt){
int linphone_core_get_payload_type_bitrate(LinphoneCore *lc, const LinphonePayloadType *pt){
int maxbw=get_min_bandwidth(linphone_core_get_download_bandwidth(lc),
linphone_core_get_upload_bandwidth(lc));
if (pt->type==PAYLOAD_AUDIO_CONTINUOUS || pt->type==PAYLOAD_AUDIO_PACKETIZED){
@ -209,7 +209,7 @@ void linphone_core_update_allocated_audio_bandwidth(LinphoneCore *lc){
int maxbw=get_min_bandwidth(linphone_core_get_download_bandwidth(lc),
linphone_core_get_upload_bandwidth(lc));
int max_codec_bitrate=0;
for(elem=linphone_core_get_audio_codecs(lc);elem!=NULL;elem=elem->next){
PayloadType *pt=(PayloadType*)elem->data;
if (payload_type_enabled(pt)){
@ -421,8 +421,7 @@ int linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call){
ms_error("Could not obtain stun server addrinfo.");
return -1;
}
if (lc->vtable.display_status!=NULL)
lc->vtable.display_status(lc,_("Stun lookup in progress..."));
linphone_core_notify_display_status(lc,_("Stun lookup in progress..."));
/*create the two audio and video RTP sockets, and send STUN message to our stun server */
sock1=create_socket(call->media_ports[0].rtp_port);
@ -603,8 +602,7 @@ int linphone_core_gather_ice_candidates(LinphoneCore *lc, LinphoneCall *call)
ms_warning("Fail to resolve STUN server for ICE gathering.");
return -1;
}
if (lc->vtable.display_status != NULL)
lc->vtable.display_status(lc, _("ICE local candidates gathering in progress..."));
linphone_core_notify_display_status(lc, _("ICE local candidates gathering in progress..."));
/* Gather local host candidates. */
if (linphone_core_get_local_ip_for(AF_INET, NULL, local_addr) < 0) {
@ -658,7 +656,7 @@ void linphone_core_update_ice_state_in_call_stats(LinphoneCall *call)
} else {
call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateFailed;
}
if (call->params.has_video && (video_check_list != NULL)) {
if (call->params->has_video && (video_check_list != NULL)) {
if (ice_check_list_state(video_check_list) == ICL_Completed) {
switch (ice_check_list_selected_valid_candidate_type(video_check_list)) {
case ICT_HostCandidate:
@ -678,12 +676,12 @@ void linphone_core_update_ice_state_in_call_stats(LinphoneCall *call)
}
} else if (session_state == IS_Running) {
call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateInProgress;
if (call->params.has_video && (video_check_list != NULL)) {
if (call->params->has_video && (video_check_list != NULL)) {
call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateInProgress;
}
} else {
call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateFailed;
if (call->params.has_video && (video_check_list != NULL)) {
if (call->params->has_video && (video_check_list != NULL)) {
call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateFailed;
}
}
@ -946,18 +944,6 @@ bool_t linphone_core_media_description_contains_video_stream(const SalMediaDescr
return FALSE;
}
LinphoneCall * is_a_linphone_call(void *user_pointer){
LinphoneCall *call=(LinphoneCall*)user_pointer;
if (call==NULL) return NULL;
return call->magic==linphone_call_magic ? call : NULL;
}
LinphoneProxyConfig * is_a_linphone_proxy_config(void *user_pointer){
LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)user_pointer;
if (cfg==NULL) return NULL;
return cfg->magic==linphone_proxy_config_magic ? cfg : NULL;
}
unsigned int linphone_core_get_audio_features(LinphoneCore *lc){
unsigned int ret=0;
const char *features=lp_config_get_string(lc->config,"sound","features",NULL);
@ -1008,7 +994,7 @@ static int get_local_ip_with_getifaddrs(int type, char *address, int size){
struct ifaddrs *ifpstart;
char retaddr[LINPHONE_IPADDR_SIZE]={0};
bool_t found=FALSE;
if (getifaddrs(&ifpstart) < 0) {
return -1;
}
@ -1109,6 +1095,9 @@ 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){
int err;
#ifdef HAVE_GETIFADDRS
int found_ifs;
#endif
strcpy(result,type==AF_INET ? "127.0.0.1" : "::1");
if (dest==NULL){
@ -1124,8 +1113,6 @@ int linphone_core_get_local_ip_for(int type, const char *dest, char *result){
#ifdef HAVE_GETIFADDRS
/*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;
@ -1137,6 +1124,26 @@ int linphone_core_get_local_ip_for(int type, const char *dest, char *result){
return 0;
}
void linphone_core_get_local_ip(LinphoneCore *lc, int af, const char *dest, char *result) {
if (af == AF_UNSPEC) {
if (linphone_core_ipv6_enabled(lc)) {
bool_t has_ipv6 = linphone_core_get_local_ip_for(AF_INET6, dest, result) == 0;
if (strcmp(result, "::1") != 0)
return; /*this machine has real ipv6 connectivity*/
if ((linphone_core_get_local_ip_for(AF_INET, dest, result) == 0) && (strcmp(result, "127.0.0.1") != 0))
return; /*this machine has only ipv4 connectivity*/
if (has_ipv6) {
/*this machine has only local loopback for both ipv4 and ipv6, so prefer ipv6*/
strncpy(result, "::1", LINPHONE_IPADDR_SIZE);
return;
}
}
/*in all other cases use IPv4*/
af = AF_INET;
}
linphone_core_get_local_ip_for(af, dest, result);
}
SalReason linphone_reason_to_sal(LinphoneReason reason){
switch(reason){
case LinphoneReasonNone:

168
coreapi/player.c Normal file
View file

@ -0,0 +1,168 @@
/*
linphone
Copyright (C) 2014 Belledonne Communications SARL
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "private.h"
/**
* Open a new source on this player.
* @param obj the player
* @param filename file to open.
* @param cb a callback used to notify end of play.
* @param user_data a user-data provided in the callback to help the application to retrieve its context.
* @return 0 if successful, -1 otherwise
**/
int linphone_player_open(LinphonePlayer *obj, const char *filename, LinphonePlayerEofCallback cb, void *user_data){
obj->user_data=user_data;
obj->cb=cb;
return obj->open(obj->impl,filename);
}
/**
* Start a play operation. The player must have been open previously with linphone_player_open().
* @param obj the player.
* @return 0 if successful, -1 otherwise
**/
int linphone_player_start(LinphonePlayer *obj){
return obj->start(obj->impl);
}
/**
* Suspend a play operation. The player must have been started previously with linphone_player_start().
* @param obj the player.
* @return 0 if successful, -1 otherwise
**/
int linphone_player_pause(LinphonePlayer *obj){
return obj->pause(obj->impl);
}
/**
* Seek at a given position given in milliseconds. The player must be in the paused state.
* @param obj the player.
* @param time_ms the position to seek to.
* @return 0 if successful, -1 otherwise
**/
int linphone_player_seek(LinphonePlayer *obj, int time_ms){
return obj->seek(obj->impl,time_ms);
}
/**
* Get the state of play operation.
* @param obj the player.
* @return the state of the player within MSPlayerClosed, MSPlayerStarted, MSPlayerPaused.
**/
MSPlayerState linphone_player_get_state(LinphonePlayer *obj){
return obj->get_state(obj->impl);
}
/**
* Close the player.
* @param obj the player.
**/
void linphone_player_close(LinphonePlayer *obj){
return obj->close(obj->impl);
}
/*
* Call player implementation below.
*/
static bool_t call_player_check_state(LinphonePlayer *player, bool_t check_player){
LinphoneCall *call=(LinphoneCall*)player->impl;
if (call->state!=LinphoneCallStreamsRunning){
ms_warning("Call [%p]: in-call player not usable in state [%s]",call,linphone_call_state_to_string(call->state));
return FALSE;
}
if (call->audiostream==NULL) {
ms_error("call_player_check_state(): no audiostream.");
return FALSE;
}
if (check_player && call->audiostream->av_player.player==NULL){
ms_error("call_player_check_state(): no player.");
return FALSE;
}
return TRUE;
}
static void on_eof(void *user_data, MSFilter *f, unsigned int event_id, void *arg){
LinphonePlayer *player=(LinphonePlayer *)user_data;
if (player->cb) player->cb(player,user_data);
}
static int call_player_open(LinphonePlayer* player, const char *filename){
LinphoneCall *call=(LinphoneCall*)player->impl;
MSFilter *filter;
if (!call_player_check_state(player,FALSE)) return -1;
filter=audio_stream_open_remote_play(call->audiostream,filename);
if (!filter) return -1;
ms_filter_add_notify_callback(filter,&on_eof,player,FALSE);
return 0;
}
static int call_player_start(LinphonePlayer *player){
LinphoneCall *call=(LinphoneCall*)player->impl;
if (!call_player_check_state(player,TRUE)) return -1;
return ms_filter_call_method_noarg(call->audiostream->av_player.player,MS_PLAYER_START);
}
static int call_player_pause(LinphonePlayer *player){
LinphoneCall *call=(LinphoneCall*)player->impl;
if (!call_player_check_state(player,TRUE)) return -1;
return ms_filter_call_method_noarg(call->audiostream->av_player.player,MS_PLAYER_PAUSE);
}
static MSPlayerState call_player_get_state(LinphonePlayer *player){
LinphoneCall *call=(LinphoneCall*)player->impl;
MSPlayerState state=MSPlayerClosed;
if (!call_player_check_state(player,TRUE)) return MSPlayerClosed;
ms_filter_call_method(call->audiostream->av_player.player,MS_PLAYER_GET_STATE,&state);
return state;
}
static int call_player_seek(LinphonePlayer *player, int time_ms){
LinphoneCall *call=(LinphoneCall*)player->impl;
if (!call_player_check_state(player,TRUE)) return -1;
return ms_filter_call_method(call->audiostream->av_player.player,MS_PLAYER_SEEK_MS,&time_ms);
}
static void call_player_close(LinphonePlayer *player){
LinphoneCall *call=(LinphoneCall*)player->impl;
if (!call_player_check_state(player,TRUE)) return;
ms_filter_call_method_noarg(call->audiostream->av_player.player,MS_PLAYER_CLOSE);
}
static void on_call_destroy(void *obj, belle_sip_object_t *call_being_destroyed){
ms_free(obj);
}
LinphonePlayer *linphone_call_build_player(LinphoneCall *call){
LinphonePlayer *obj=ms_new0(LinphonePlayer,1);
obj->open=call_player_open;
obj->close=call_player_close;
obj->start=call_player_start;
obj->seek=call_player_seek;
obj->pause=call_player_pause;
obj->get_state=call_player_get_state;
obj->impl=call;
belle_sip_object_weak_ref(call,on_call_destroy,obj);
return obj;
}

View file

@ -89,9 +89,9 @@ static char presence_id_valid_start_characters[] = ":_abcdefghijklmnopqrstuvwxyz
static char * generate_presence_id(void) {
char id[7];
int i;
id[0] = presence_id_valid_start_characters[random() % (sizeof(presence_id_valid_start_characters)-1)];
id[0] = presence_id_valid_start_characters[ortp_random() % (sizeof(presence_id_valid_start_characters)-1)];
for (i = 1; i < 6; i++) {
id[i] = presence_id_valid_characters[random() % (sizeof(presence_id_valid_characters)-1)];
id[i] = presence_id_valid_characters[ortp_random() % (sizeof(presence_id_valid_characters)-1)];
}
id[6] = '\0';
@ -1043,7 +1043,7 @@ void linphone_presence_model_set_user_data(LinphonePresenceModel *model, void *u
model->user_data = user_data;
}
void * linphone_presence_model_get_user_data(LinphonePresenceModel *model) {
void * linphone_presence_model_get_user_data(const LinphonePresenceModel *model) {
return model->user_data;
}
@ -1065,7 +1065,7 @@ void linphone_presence_service_set_user_data(LinphonePresenceService *service, v
service->user_data = user_data;
}
void * linphone_presence_service_get_user_data(LinphonePresenceService *service) {
void * linphone_presence_service_get_user_data(const LinphonePresenceService *service) {
return service->user_data;
}
@ -1087,7 +1087,7 @@ void linphone_presence_person_set_user_data(LinphonePresencePerson *person, void
person->user_data = user_data;
}
void * linphone_presence_person_get_user_data(LinphonePresencePerson *person) {
void * linphone_presence_person_get_user_data(const LinphonePresencePerson *person) {
return person->user_data;
}
@ -1109,7 +1109,7 @@ void linphone_presence_activity_set_user_data(LinphonePresenceActivity *activity
activity->user_data = user_data;
}
void * linphone_presence_activity_get_user_data(LinphonePresenceActivity *activity) {
void * linphone_presence_activity_get_user_data(const LinphonePresenceActivity *activity) {
return activity->user_data;
}
@ -1131,7 +1131,7 @@ void linphone_presence_note_set_user_data(LinphonePresenceNote *note, void *user
note->user_data = user_data;
}
void * linphone_presence_note_get_user_data(LinphonePresenceNote *note) {
void * linphone_presence_note_get_user_data(const LinphonePresenceNote *note) {
return note->user_data;
}
@ -1443,9 +1443,9 @@ void linphone_core_add_subscriber(LinphoneCore *lc, const char *subscriber, SalO
linphone_friend_set_inc_subscribe_policy(fl,LinphoneSPAccept);
fl->inc_subscribe_pending=TRUE;
lc->subscribers=ms_list_append(lc->subscribers,(void *)fl);
if (lc->vtable.new_subscription_requested!=NULL) {
{
char *tmp=linphone_address_as_string(fl->uri);
lc->vtable.new_subscription_requested(lc,fl,tmp);
linphone_core_notify_new_subscription_requested(lc,fl,tmp);
ms_free(tmp);
}
}
@ -1876,8 +1876,7 @@ void linphone_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeStatus ss, Sa
}
lf->presence = presence;
lf->subscribe_active=TRUE;
if (lc->vtable.notify_presence_received)
lc->vtable.notify_presence_received(lc,(LinphoneFriend*)lf);
linphone_core_notify_notify_presence_received(lc,(LinphoneFriend*)lf);
ms_free(tmp);
}else{
ms_message("But this person is not part of our friend list, so we don't care.");

View file

@ -80,6 +80,8 @@ extern "C" {
#endif
struct _LinphoneCallParams{
belle_sip_object_t base;
void *user_data;
LinphoneCall *referer; /*in case this call creation is consecutive to an incoming transfer, this points to the original call */
int audio_bw; /* bandwidth limit for audio stream */
LinphoneMediaEncryption media_encryption;
@ -100,10 +102,14 @@ struct _LinphoneCallParams{
bool_t real_early_media; /*send real media even during early media (for outgoing calls)*/
bool_t in_conference; /*in conference mode */
bool_t low_bandwidth;
bool_t no_user_consent;/*when set to TRUE an UPDATE request will be used instead of reINVITE*/
uint16_t avpf_rr_interval; /*in milliseconds*/
LinphonePrivacyMask privacy;
uint16_t avpf_rr_interval;
};
BELLE_SIP_DECLARE_VPTR(LinphoneCallParams);
struct _LinphoneQualityReporting{
reporting_session_report_t * reports[2]; /**Store information on audio and video media streams (RFC 6035) */
bool_t was_video_running; /*Keep video state since last check in order to detect its (de)activation*/
@ -111,6 +117,8 @@ struct _LinphoneQualityReporting{
};
struct _LinphoneCallLog{
belle_sip_object_t base;
void *user_data;
struct _LinphoneCore *lc;
LinphoneCallDir dir; /**< The direction of the call*/
LinphoneCallStatus status; /**< The status of the call*/
@ -119,18 +127,17 @@ struct _LinphoneCallLog{
char start_date[128]; /**<Human readable string containing the start date*/
int duration; /**<Duration of the call in seconds*/
char *refkey;
void *user_pointer;
rtp_stats_t local_stats;
rtp_stats_t remote_stats;
float quality;
time_t start_date_time; /**Start date of the call in seconds as expressed in a time_t */
char* call_id; /**unique id of a call*/
struct _LinphoneQualityReporting reporting;
bool_t video_enabled;
};
BELLE_SIP_DECLARE_VPTR(LinphoneCallLog);
typedef struct _CallCallbackObj
{
@ -138,8 +145,6 @@ typedef struct _CallCallbackObj
void * _user_data;
}CallCallbackObj;
static const int linphone_call_magic=0x3343;
typedef enum _LinphoneChatMessageDir{
LinphoneChatMessageIncoming,
LinphoneChatMessageOutgoing
@ -163,8 +168,9 @@ struct _LinphoneChatMessage {
bool_t is_read;
unsigned int storage_id;
SalOp *op;
LinphoneContent *file_transfer_information;
char *content_type;
LinphoneContent *file_transfer_information; /**< used to store file transfer information when the message is of file transfer type */
char *content_type; /**< is used to specified the type of message to be sent, used only for file transfer message */
belle_http_request_t *http_request; /**< keep a reference to the http_request in case of file transfer in order to be able to cancel the transfer */
};
BELLE_SIP_DECLARE_VPTR(LinphoneChatMessage);
@ -182,7 +188,8 @@ typedef struct _PortConfig{
struct _LinphoneCall
{
int magic; /*used to distinguish from proxy config*/
belle_sip_object_t base;
void *user_data;
struct _LinphoneCore *core;
SalErrorInfo non_op_error;
int af; /*the address family to prefer for RTP path, guessed from signaling path*/
@ -201,8 +208,6 @@ struct _LinphoneCall
LinphoneCallState prevstate;
LinphoneCallState transfer_state; /*idle if no transfer*/
LinphoneProxyConfig *dest_proxy;
int refcnt;
void * user_pointer;
PortConfig media_ports[2];
MSMediaStreamSessions sessions[2]; /*the rtp, srtp, zrtp contexts for each stream*/
StunCandidate ac,vc; /*audio video ip/port discovered by STUN*/
@ -211,9 +216,9 @@ struct _LinphoneCall
MSAudioEndpoint *endpoint; /*used for conferencing*/
char *refer_to;
LinphoneCallParams params;
LinphoneCallParams current_params;
LinphoneCallParams remote_params;
LinphoneCallParams *params;
LinphoneCallParams *current_params;
LinphoneCallParams *remote_params;
int up_bw; /*upload bandwidth setting at the time the call is started. Used to detect if it changes during a call */
int audio_bw; /*upload bandwidth used by audio */
OrtpEvQueue *audiostream_app_evq;
@ -231,6 +236,7 @@ struct _LinphoneCall
LinphoneCall *referer; /*when this call is the result of a transfer, referer is set to the original call that caused the transfer*/
LinphoneCall *transfer_target;/*if this call received a transfer request, then transfer_target points to the new call created to the refer target */
int localdesc_changed;/*not a boolean, contains a mask representing changes*/
LinphonePlayer *player;
bool_t refer_pending;
bool_t expect_media_in_ack;
@ -239,29 +245,35 @@ struct _LinphoneCall
bool_t all_muted; /*this flag is set during early medias*/
bool_t playing_ringbacktone;
bool_t owns_call_log;
bool_t ringing_beep; /* whether this call is ringing through an already existent current call*/
bool_t auth_token_verified;
bool_t defer_update;
bool_t defer_update;
bool_t was_automatically_paused;
bool_t ping_replied;
bool_t record_active;
bool_t paused_by_app;
};
BELLE_SIP_DECLARE_VPTR(LinphoneCall);
LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, const LinphoneCallParams *params, LinphoneProxyConfig *cfg);
LinphoneCall * linphone_call_new_incoming(struct _LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, SalOp *op);
void linphone_call_set_new_params(LinphoneCall *call, const LinphoneCallParams *params);
void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const char *message);
void linphone_call_set_contact_op(LinphoneCall* call);
void linphone_call_set_compatible_incoming_call_parameters(LinphoneCall *call, const SalMediaDescription *md);
/* private: */
LinphoneCallLog * linphone_call_log_new(LinphoneCall *call, LinphoneAddress *local, LinphoneAddress * remote);
LinphoneCallLog * linphone_call_log_new(LinphoneCallDir dir, LinphoneAddress *local, LinphoneAddress * remote);
void linphone_call_log_completed(LinphoneCall *call);
void linphone_call_log_destroy(LinphoneCallLog *cl);
void linphone_call_set_transfer_state(LinphoneCall* call, LinphoneCallState state);
LinphonePlayer *linphone_call_build_player(LinphoneCall*call);
LinphoneCallParams * linphone_call_params_new(void);
SalMediaProto get_proto_from_call_params(const LinphoneCallParams *params);
void linphone_auth_info_write_config(struct _LpConfig *config, LinphoneAuthInfo *obj, int pos);
@ -269,16 +281,32 @@ void linphone_core_update_proxy_register(LinphoneCore *lc);
void linphone_core_refresh_subscribes(LinphoneCore *lc);
int linphone_core_abort_call(LinphoneCore *lc, LinphoneCall *call, const char *error);
const char *linphone_core_get_nat_address_resolved(LinphoneCore *lc);
/**
* @brief Equivalent to _linphone_core_get_firewall_policy_with_lie(lc, TRUE)
* @param lc LinphoneCore instance
* @return Fairewall policy
*/
LinphoneFirewallPolicy _linphone_core_get_firewall_policy(const LinphoneCore *lc);
/**
* @brief Get the firwall policy which has been set.
* @param lc Instance of LinphoneCore
* @param lie If true, the configured firewall policy will be returned only if no tunnel are enabled.
* Otherwise, NoFirewallPolicy value will be returned.
* @return The firewall policy
*/
LinphoneFirewallPolicy _linphone_core_get_firewall_policy_with_lie(const LinphoneCore *lc, bool_t lie);
int linphone_proxy_config_send_publish(LinphoneProxyConfig *cfg, LinphonePresenceModel *presence);
void linphone_proxy_config_set_state(LinphoneProxyConfig *cfg, LinphoneRegistrationState rstate, const char *message);
void linphone_proxy_config_stop_refreshing(LinphoneProxyConfig *obj);
void linphone_proxy_config_write_all_to_config_file(LinphoneCore *lc);
void _linphone_proxy_config_release(LinphoneProxyConfig *cfg);
/*
* returns service route as defined in as defined by rfc3608, might be a list instead of just one.
* Can be NULL
* */
const LinphoneAddress* linphone_proxy_config_get_service_route(const LinphoneProxyConfig* cfg);
char* linphone_proxy_config_get_contact(const LinphoneProxyConfig *cfg);
void linphone_friend_close_subscriptions(LinphoneFriend *lf);
void linphone_friend_update_subscribes(LinphoneFriend *fr, LinphoneProxyConfig *cfg, bool_t only_when_registered);
@ -291,7 +319,6 @@ void linphone_core_update_friends_subscriptions(LinphoneCore *lc, LinphoneProxyC
int parse_hostname_to_addr(const char *server, struct sockaddr_storage *ss, socklen_t *socklen, int default_port);
void linphone_core_get_local_ip(LinphoneCore *lc, int af, char *result);
bool_t host_has_ipv6_network();
bool_t lp_spawn_command_line_sync(const char *command, char **result,int *command_ret);
@ -356,10 +383,10 @@ void linphone_friend_write_to_config_file(struct _LpConfig *config, LinphoneFrie
LinphoneFriend * linphone_friend_new_from_config_file(struct _LinphoneCore *lc, int index);
void linphone_proxy_config_update(LinphoneProxyConfig *cfg);
void linphone_proxy_config_get_contact(LinphoneProxyConfig *cfg, const char **ip, int *port);
LinphoneProxyConfig * linphone_core_lookup_known_proxy(LinphoneCore *lc, const LinphoneAddress *uri);
const char *linphone_core_find_best_identity(LinphoneCore *lc, const LinphoneAddress *to);
int linphone_core_get_local_ip_for(int type, const char *dest, char *result);
void linphone_core_get_local_ip(LinphoneCore *lc, int af, const char *dest, char *result);
LinphoneProxyConfig *linphone_proxy_config_new_from_config_file(LinphoneCore *lc, int index);
void linphone_proxy_config_write_to_config_file(struct _LpConfig* config,LinphoneProxyConfig *obj, int index);
@ -382,7 +409,7 @@ 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);
void linphone_call_set_state_base(LinphoneCall *call, LinphoneCallState cstate, const char *message,bool_t silently);
const char * linphone_core_get_identity(LinphoneCore *lc);
@ -394,35 +421,35 @@ int linphone_core_proceed_with_invite_if_ready(LinphoneCore *lc, LinphoneCall *c
int linphone_core_start_invite(LinphoneCore *lc, LinphoneCall *call, const LinphoneAddress* destination/* = NULL if to be taken from the call log */);
int linphone_core_restart_invite(LinphoneCore *lc, LinphoneCall *call);
int linphone_core_start_update_call(LinphoneCore *lc, LinphoneCall *call);
int linphone_core_start_accept_call_update(LinphoneCore *lc, LinphoneCall *call);
int linphone_core_start_accept_call_update(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState next_state, const char *state_info);
void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call);
bool_t linphone_core_incompatible_security(LinphoneCore *lc, SalMediaDescription *md);
extern SalCallbacks linphone_sal_callbacks;
bool_t linphone_core_rtcp_enabled(const LinphoneCore *lc);
bool_t linphone_core_symmetric_rtp_enabled(LinphoneCore*lc);
LinphoneCall * is_a_linphone_call(void *user_pointer);
LinphoneProxyConfig * is_a_linphone_proxy_config(void *user_pointer);
void linphone_core_queue_task(LinphoneCore *lc, belle_sip_source_func_t task_fun, void *data, const char *task_description);
static const int linphone_proxy_config_magic=0x7979;
LINPHONE_PUBLIC bool_t linphone_proxy_config_address_equal(const LinphoneAddress *a, const LinphoneAddress *b);
LINPHONE_PUBLIC bool_t linphone_proxy_config_is_server_config_changed(const LinphoneProxyConfig* obj);
void _linphone_proxy_config_unregister(LinphoneProxyConfig *obj);
void _linphone_proxy_config_release_ops(LinphoneProxyConfig *obj);
/*chat*/
void linphone_chat_room_release(LinphoneChatRoom *cr);
void linphone_chat_message_destroy(LinphoneChatMessage* msg);
/**/
struct _LinphoneProxyConfig
{
int magic;
belle_sip_object_t base;
void *user_data;
struct _LinphoneCore *lc;
char *reg_proxy;
char *reg_identity;
char *reg_route;
char *quality_reporting_collector;
char *domain;
char *realm;
char *contact_params;
char *contact_uri_params;
@ -435,17 +462,18 @@ struct _LinphoneProxyConfig
char *dial_prefix;
LinphoneRegistrationState state;
SalOp *publish_op;
LinphoneAVPFMode avpf_mode;
bool_t commit;
bool_t reg_sendregister;
bool_t publish;
bool_t dial_escape_plus;
bool_t send_publish;
bool_t quality_reporting_enabled;
bool_t avpf_enabled;
bool_t pad;
uint8_t avpf_rr_interval;
uint8_t quality_reporting_interval;
void* user_data;
time_t deletion_date;
LinphonePrivacyMask privacy;
/*use to check if server config has changed between edit() and done()*/
@ -455,6 +483,8 @@ struct _LinphoneProxyConfig
};
BELLE_SIP_DECLARE_VPTR(LinphoneProxyConfig);
struct _LinphoneAuthInfo
{
char *username;
@ -471,10 +501,11 @@ typedef enum _LinphoneIsComposingState {
} LinphoneIsComposingState;
struct _LinphoneChatRoom{
belle_sip_object_t base;
void *user_data;
struct _LinphoneCore *lc;
char *peer;
LinphoneAddress *peer_url;
void * user_data;
MSList *messages_hist;
MSList *transient_messages;
LinphoneIsComposingState remote_is_composing;
@ -484,6 +515,7 @@ struct _LinphoneChatRoom{
belle_sip_source_t *composing_refresh_timer;
};
BELLE_SIP_DECLARE_VPTR(LinphoneChatRoom);
struct _LinphoneFriend{
@ -538,6 +570,7 @@ typedef struct rtp_config
int nortp_timeout;
int disable_upnp;
MSCryptoSuite *srtp_suites;
LinphoneAVPFMode avpf_mode;
bool_t rtp_no_xmit_on_audio_mute;
/* stop rtp xmit when audio muted */
bool_t audio_adaptive_jitt_comp_enabled;
@ -599,6 +632,7 @@ typedef struct video_config{
bool_t show_local;
bool_t display;
bool_t selfview; /*during calls*/
bool_t reuse_preview_source;
}video_config_t;
typedef struct ui_config
@ -627,6 +661,7 @@ struct _LinphoneConference{
MSAudioEndpoint *record_endpoint;
RtpProfile *local_dummy_profile;
bool_t local_muted;
bool_t terminated;
};
@ -642,12 +677,12 @@ LinphoneToneDescription *linphone_core_get_call_error_tone(const LinphoneCore *l
void linphone_core_play_call_error_tone(LinphoneCore *lc, LinphoneReason reason);
void _linphone_core_set_tone(LinphoneCore *lc, LinphoneReason reason, LinphoneToneID id, const char *audiofile);
const char *linphone_core_get_tone_file(const LinphoneCore *lc, LinphoneToneID id);
int _linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params);
int _linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params, LinphoneCallState next_state, const char *state_info);
typedef struct _LinphoneConference LinphoneConference;
struct _LinphoneCore
{
LinphoneCoreVTable vtable;
MSList* vtables;
Sal *sal;
LinphoneGlobalState state;
struct _LpConfig *config;
@ -705,6 +740,7 @@ struct _LinphoneCore
bool_t preview_finished;
bool_t auto_net_state_mon;
bool_t network_reachable;
bool_t network_reachable_to_be_notified; /*set to true when state must be notified in next iterate*/
bool_t use_preview_window;
time_t network_last_check;
@ -823,12 +859,11 @@ void _linphone_core_codec_config_write(LinphoneCore *lc);
#ifndef NB_MAX_CALLS
#define NB_MAX_CALLS (10)
#endif
void call_logs_read_from_config_file(LinphoneCore *lc);
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);
void _linphone_call_params_copy(LinphoneCallParams *params, const LinphoneCallParams *refparams);
void linphone_call_params_uninit(LinphoneCallParams *params);
int linphone_upnp_init(LinphoneCore *lc);
void linphone_upnp_destroy(LinphoneCore *lc);
@ -874,6 +909,23 @@ void linphone_core_invalidate_friend_subscriptions(LinphoneCore *lc);
void linphone_configuring_terminated(LinphoneCore *lc, LinphoneConfiguringState state, const char *message);
int linphone_remote_provisioning_download_and_apply(LinphoneCore *lc, const char *remote_provisioning_uri);
int linphone_remote_provisioning_load_file( LinphoneCore* lc, const char* file_path);
/*****************************************************************************
* Player interface
****************************************************************************/
struct _LinphonePlayer{
int (*open)(struct _LinphonePlayer* player, const char *filename);
int (*start)(struct _LinphonePlayer* player);
int (*pause)(struct _LinphonePlayer* player);
int (*seek)(struct _LinphonePlayer* player, int time_ms);
MSPlayerState (*get_state)(struct _LinphonePlayer* player);
void (*close)(struct _LinphonePlayer* player);
LinphonePlayerEofCallback cb;
void *user_data;
void *impl;
};
/*****************************************************************************
@ -920,14 +972,57 @@ const MSCryptoSuite * linphone_core_get_srtp_crypto_suites(LinphoneCore *lc);
*/
BELLE_SIP_DECLARE_TYPES_BEGIN(linphone,10000)
BELLE_SIP_TYPE_ID(LinphoneContactSearch),
BELLE_SIP_TYPE_ID(LinphoneContactProvider),
BELLE_SIP_TYPE_ID(LinphoneContactSearch),
BELLE_SIP_TYPE_ID(LinphoneCall),
BELLE_SIP_TYPE_ID(LinphoneCallLog),
BELLE_SIP_TYPE_ID(LinphoneCallParams),
BELLE_SIP_TYPE_ID(LinphoneChatMessage),
BELLE_SIP_TYPE_ID(LinphoneChatRoom),
BELLE_SIP_TYPE_ID(LinphoneLDAPContactProvider),
BELLE_SIP_TYPE_ID(LinphoneLDAPContactSearch),
BELLE_SIP_TYPE_ID(LinphoneChatMessage)
BELLE_SIP_TYPE_ID(LinphoneProxyConfig)
BELLE_SIP_DECLARE_TYPES_END
void linphone_core_notify_global_state_changed(LinphoneCore *lc, LinphoneGlobalState gstate, const char *message);
void linphone_core_notify_call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate, const char *message);
void linphone_core_notify_call_encryption_changed(LinphoneCore *lc, LinphoneCall *call, bool_t on, const char *authentication_token);
void linphone_core_notify_registration_state_changed(LinphoneCore *lc, LinphoneProxyConfig *cfg, LinphoneRegistrationState cstate, const char *message);
void linphone_core_notify_show_interface(LinphoneCore *lc);
void linphone_core_notify_display_status(LinphoneCore *lc, const char *message);
void linphone_core_notify_display_message(LinphoneCore *lc, const char *message);
void linphone_core_notify_display_warning(LinphoneCore *lc, const char *message);
void linphone_core_notify_display_url(LinphoneCore *lc, const char *message, const char *url);
void linphone_core_notify_notify_presence_received(LinphoneCore *lc, LinphoneFriend * lf);
void linphone_core_notify_new_subscription_requested(LinphoneCore *lc, LinphoneFriend *lf, const char *url);
void linphone_core_notify_auth_info_requested(LinphoneCore *lc, const char *realm, const char *username, const char *domain);
void linphone_core_notify_call_log_updated(LinphoneCore *lc, LinphoneCallLog *newcl);
void linphone_core_notify_text_message_received(LinphoneCore *lc, LinphoneChatRoom *room, const LinphoneAddress *from, const char *message);
void linphone_core_notify_message_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage *message);
void linphone_core_notify_file_transfer_recv(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, const char* buff, size_t size);
void linphone_core_notify_file_transfer_send(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, char* buff, size_t* size);
void linphone_core_notify_file_transfer_progress_indication(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, size_t progress);
void linphone_core_notify_is_composing_received(LinphoneCore *lc, LinphoneChatRoom *room);
void linphone_core_notify_dtmf_received(LinphoneCore* lc, LinphoneCall *call, int dtmf);
/*
* return true if at least a registered vtable has a cb for dtmf received*/
bool_t linphone_core_dtmf_received_has_listener(const LinphoneCore* lc);
void linphone_core_notify_refer_received(LinphoneCore *lc, const char *refer_to);
void linphone_core_notify_buddy_info_updated(LinphoneCore *lc, LinphoneFriend *lf);
void linphone_core_notify_transfer_state_changed(LinphoneCore *lc, LinphoneCall *transfered, LinphoneCallState new_call_state);
void linphone_core_notify_call_stats_updated(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallStats *stats);
void linphone_core_notify_info_received(LinphoneCore *lc, LinphoneCall *call, const LinphoneInfoMessage *msg);
void linphone_core_notify_configuring_status(LinphoneCore *lc, LinphoneConfiguringState status, const char *message);
void linphone_core_notify_network_reachable(LinphoneCore *lc, bool_t reachable);
void linphone_core_notify_notify_received(LinphoneCore *lc, LinphoneEvent *lev, const char *notified_event, const LinphoneContent *body);
void linphone_core_notify_subscription_state_changed(LinphoneCore *lc, LinphoneEvent *lev, LinphoneSubscriptionState state);
void linphone_core_notify_publish_state_changed(LinphoneCore *lc, LinphoneEvent *lev, LinphonePublishState state);
#ifdef __cplusplus
}
#endif

View file

@ -94,26 +94,27 @@ static void linphone_proxy_config_init(LinphoneCore* lc, LinphoneProxyConfig *ob
const char *identity = lc ? lp_config_get_default_string(lc->config, "proxy", "reg_identity", NULL) : NULL;
const char *proxy = lc ? lp_config_get_default_string(lc->config, "proxy", "reg_proxy", NULL) : NULL;
const char *route = lc ? lp_config_get_default_string(lc->config, "proxy", "reg_route", NULL) : NULL;
const char *realm = lc ? lp_config_get_default_string(lc->config, "proxy", "realm", NULL) : NULL;
const char *quality_reporting_collector = lc ? lp_config_get_default_string(lc->config, "proxy", "quality_reporting_collector", NULL) : NULL;
const char *contact_params = lc ? lp_config_get_default_string(lc->config, "proxy", "contact_parameters", NULL) : NULL;
const char *contact_uri_params = lc ? lp_config_get_default_string(lc->config, "proxy", "contact_uri_parameters", NULL) : NULL;
memset(obj, 0, sizeof(LinphoneProxyConfig));
obj->magic = linphone_proxy_config_magic;
obj->expires = lc ? lp_config_get_default_int(lc->config, "proxy", "reg_expires", 3600) : 3600;
obj->reg_sendregister = lc ? lp_config_get_default_int(lc->config, "proxy", "reg_sendregister", 0) : 0;
obj->reg_sendregister = lc ? lp_config_get_default_int(lc->config, "proxy", "reg_sendregister", 1) : 1;
obj->dial_prefix = dial_prefix ? ms_strdup(dial_prefix) : NULL;
obj->dial_escape_plus = lc ? lp_config_get_default_int(lc->config, "proxy", "dial_escape_plus", 0) : 0;
obj->privacy = lc ? lp_config_get_default_int(lc->config, "proxy", "privacy", LinphonePrivacyDefault) : LinphonePrivacyDefault;
obj->reg_identity = identity ? ms_strdup(identity) : NULL;
obj->reg_proxy = proxy ? ms_strdup(proxy) : NULL;
obj->reg_route = route ? ms_strdup(route) : NULL;
obj->domain = NULL;
obj->realm = realm ? ms_strdup(realm) : NULL;
obj->quality_reporting_enabled = lc ? lp_config_get_default_int(lc->config, "proxy", "quality_reporting_enabled", 0) : 0;
obj->quality_reporting_collector = quality_reporting_collector ? ms_strdup(quality_reporting_collector) : NULL;
obj->quality_reporting_interval = lc ? lp_config_get_default_int(lc->config, "proxy", "quality_reporting_interval", 0) : 0;
obj->contact_params = contact_params ? ms_strdup(contact_params) : NULL;
obj->contact_uri_params = contact_uri_params ? ms_strdup(contact_uri_params) : NULL;
obj->avpf_enabled = lc ? lp_config_get_default_int(lc->config, "proxy", "avpf", 0) : 0;
obj->avpf_mode = lc ? lp_config_get_default_int(lc->config, "proxy", "avpf", LinphoneAVPFDefault) : LinphoneAVPFDefault;
obj->avpf_rr_interval = lc ? lp_config_get_default_int(lc->config, "proxy", "avpf_rr_interval", 5) : 5;
obj->publish_expires=-1;
}
@ -131,35 +132,74 @@ LinphoneProxyConfig *linphone_proxy_config_new() {
return linphone_core_create_proxy_config(NULL);
}
static void _linphone_proxy_config_destroy(LinphoneProxyConfig *obj);
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneProxyConfig);
BELLE_SIP_INSTANCIATE_VPTR(LinphoneProxyConfig, belle_sip_object_t,
(belle_sip_object_destroy_t)_linphone_proxy_config_destroy,
NULL, // clone
NULL, // marshal
FALSE
);
LinphoneProxyConfig * linphone_core_create_proxy_config(LinphoneCore *lc) {
LinphoneProxyConfig *obj=NULL;
obj=ms_new(LinphoneProxyConfig,1);
LinphoneProxyConfig *obj = belle_sip_object_new(LinphoneProxyConfig);
linphone_proxy_config_init(lc,obj);
return obj;
}
/**
* Destroys a proxy config.
*
* @note: LinphoneProxyConfig that have been removed from LinphoneCore with
* linphone_core_remove_proxy_config() must not be freed.
**/
void linphone_proxy_config_destroy(LinphoneProxyConfig *obj){
void _linphone_proxy_config_release_ops(LinphoneProxyConfig *obj){
if (obj->op) {
sal_op_release(obj->op);
obj->op=NULL;
}
if (obj->publish_op){
sal_op_release(obj->publish_op);
obj->publish_op=NULL;
}
}
void _linphone_proxy_config_destroy(LinphoneProxyConfig *obj){
if (obj->reg_proxy!=NULL) ms_free(obj->reg_proxy);
if (obj->reg_identity!=NULL) ms_free(obj->reg_identity);
if (obj->reg_route!=NULL) ms_free(obj->reg_route);
if (obj->quality_reporting_collector!=NULL) ms_free(obj->quality_reporting_collector);
if (obj->ssctx!=NULL) sip_setup_context_free(obj->ssctx);
if (obj->domain!=NULL) ms_free(obj->domain);
if (obj->realm!=NULL) ms_free(obj->realm);
if (obj->type!=NULL) ms_free(obj->type);
if (obj->dial_prefix!=NULL) ms_free(obj->dial_prefix);
if (obj->op) sal_op_release(obj->op);
if (obj->publish_op) sal_op_release(obj->publish_op);
if (obj->contact_params) ms_free(obj->contact_params);
if (obj->contact_uri_params) ms_free(obj->contact_uri_params);
if (obj->saved_proxy!=NULL) linphone_address_destroy(obj->saved_proxy);
if (obj->saved_identity!=NULL) linphone_address_destroy(obj->saved_identity);
ms_free(obj);
_linphone_proxy_config_release_ops(obj);
}
/**
* Destroys a proxy config.
* @deprecated
*
* @note: LinphoneProxyConfig that have been removed from LinphoneCore with
* linphone_core_remove_proxy_config() must not be freed.
**/
void linphone_proxy_config_destroy(LinphoneProxyConfig *cfg) {
belle_sip_object_unref(cfg);
}
void _linphone_proxy_config_release(LinphoneProxyConfig *cfg) {
_linphone_proxy_config_release_ops(cfg);
belle_sip_object_unref(cfg);
}
LinphoneProxyConfig *linphone_proxy_config_ref(LinphoneProxyConfig *cfg) {
belle_sip_object_ref(cfg);
return cfg;
}
void linphone_proxy_config_unref(LinphoneProxyConfig *cfg) {
belle_sip_object_unref(cfg);
}
/**
@ -228,10 +268,10 @@ int linphone_proxy_config_set_identity(LinphoneProxyConfig *obj, const char *ide
obj->reg_identity=NULL;
}
obj->reg_identity=ms_strdup(identity);
if (obj->realm){
ms_free(obj->realm);
if (obj->domain){
ms_free(obj->domain);
}
obj->realm=ms_strdup(linphone_address_get_domain(addr));
obj->domain=ms_strdup(linphone_address_get_domain(addr));
linphone_address_destroy(addr);
return 0;
}
@ -240,7 +280,7 @@ int linphone_proxy_config_set_identity(LinphoneProxyConfig *obj, const char *ide
}
const char *linphone_proxy_config_get_domain(const LinphoneProxyConfig *cfg){
return cfg->realm;
return cfg->domain;
}
/**
@ -275,14 +315,14 @@ int linphone_proxy_config_set_route(LinphoneProxyConfig *obj, const char *route)
bool_t linphone_proxy_config_check(LinphoneCore *lc, LinphoneProxyConfig *obj){
if (obj->reg_proxy==NULL){
if (lc && lc->vtable.display_warning)
lc->vtable.display_warning(lc,_("The sip proxy address you entered is invalid, it must start with \"sip:\""
if (lc)
linphone_core_notify_display_warning(lc,_("The sip proxy address you entered is invalid, it must start with \"sip:\""
" followed by a hostname."));
return FALSE;
}
if (obj->reg_identity==NULL){
if (lc && lc->vtable.display_warning)
lc->vtable.display_warning(lc,_("The sip identity you entered is invalid.\nIt should look like "
if (lc)
linphone_core_notify_display_warning(lc,_("The sip identity you entered is invalid.\nIt should look like "
"sip:username@proxydomain, such as sip:alice@example.net"));
return FALSE;
}
@ -310,7 +350,7 @@ void linphone_proxy_config_enable_publish(LinphoneProxyConfig *obj, bool_t val){
/**
* Prevent a proxy config from refreshing its registration.
* This is useful to let registrations to expire naturally (or) when the application wants to keep control on when
* This is useful to let registrations to expire naturally (or) when the application wants to keep control on when
* refreshes are sent.
* However, linphone_core_set_network_reachable(lc,TRUE) will always request the proxy configs to refresh their registrations.
* The refreshing operations can be resumed with linphone_proxy_config_refresh_register().
@ -409,6 +449,7 @@ void _linphone_proxy_config_unregister(LinphoneProxyConfig *obj) {
static void linphone_proxy_config_register(LinphoneProxyConfig *obj){
if (obj->reg_sendregister){
LinphoneAddress* proxy=linphone_address_new(obj->reg_proxy);
LinphoneAddress* to=linphone_address_new(obj->reg_identity);
char* proxy_string;
LinphoneAddress *contact;
ms_message("LinphoneProxyConfig [%p] about to register (LinphoneCore version: %s)",obj,linphone_core_get_version());
@ -417,11 +458,18 @@ static void linphone_proxy_config_register(LinphoneProxyConfig *obj){
if (obj->op)
sal_op_release(obj->op);
obj->op=sal_op_new(obj->lc->sal);
linphone_configure_op(obj->lc, obj->op, to, NULL, FALSE);
linphone_address_destroy(to);
if ((contact=guess_contact_for_register(obj))) {
sal_op_set_contact_address(obj->op,contact);
linphone_address_destroy(contact);
}
sal_op_set_user_pointer(obj->op,obj);
if (sal_register(obj->op,proxy_string,obj->reg_identity,obj->expires)==0) {
linphone_proxy_config_set_state(obj,LinphoneRegistrationProgress,"Registration in progress");
} else {
@ -434,9 +482,6 @@ static void linphone_proxy_config_register(LinphoneProxyConfig *obj){
linphone_proxy_config_set_state(obj,LinphoneRegistrationCleared,"Registration cleared");
}
_linphone_proxy_config_unregister(obj);
}
}
@ -946,13 +991,16 @@ int linphone_proxy_config_done(LinphoneProxyConfig *obj)
return 0;
}
const char* linphone_proxy_config_get_realm(const LinphoneProxyConfig *cfg)
{
return cfg?cfg->realm:NULL;
}
void linphone_proxy_config_set_realm(LinphoneProxyConfig *cfg, const char *realm)
{
if (cfg->realm!=NULL) {
ms_free(cfg->realm);
cfg->realm=NULL;
}
if (realm!=NULL) cfg->realm=ms_strdup(realm);
cfg->realm=ms_strdup(realm);
}
int linphone_proxy_config_send_publish(LinphoneProxyConfig *proxy, LinphonePresenceModel *presence){
@ -960,10 +1008,15 @@ int linphone_proxy_config_send_publish(LinphoneProxyConfig *proxy, LinphonePrese
if (proxy->state==LinphoneRegistrationOk || proxy->state==LinphoneRegistrationCleared){
if (proxy->publish_op==NULL){
LinphoneAddress *to=linphone_address_new(linphone_proxy_config_get_identity(proxy));
proxy->publish_op=sal_op_new(proxy->lc->sal);
sal_op_set_route(proxy->publish_op,proxy->reg_proxy);
sal_op_set_from(proxy->publish_op,linphone_proxy_config_get_identity(proxy));
sal_op_set_to(proxy->publish_op,linphone_proxy_config_get_identity(proxy));
linphone_configure_op(proxy->lc, proxy->publish_op,
to, NULL, FALSE);
if (to!=NULL){
linphone_address_destroy(to);
}
if (lp_config_get_int(proxy->lc->config,"sip","publish_msg_with_contact",0)){
SalAddress *addr=sal_address_new(linphone_proxy_config_get_identity(proxy));
sal_op_set_contact_address(proxy->publish_op,addr);
@ -1089,7 +1142,7 @@ int linphone_core_add_proxy_config(LinphoneCore *lc, LinphoneProxyConfig *cfg){
ms_warning("ProxyConfig already entered, ignored.");
return 0;
}
lc->sip_conf.proxies=ms_list_append(lc->sip_conf.proxies,(void *)cfg);
lc->sip_conf.proxies=ms_list_append(lc->sip_conf.proxies,(void *)linphone_proxy_config_ref(cfg));
linphone_proxy_config_apply(cfg,lc);
return 0;
}
@ -1115,10 +1168,7 @@ void linphone_core_remove_proxy_config(LinphoneCore *lc, LinphoneProxyConfig *cf
linphone_proxy_config_edit(cfg);
linphone_proxy_config_enable_register(cfg,FALSE);
linphone_proxy_config_done(cfg);
linphone_proxy_config_update(cfg); /*so that it has an effect*/
/*as cfg no longer in proxies, unregister will never be issued*/
_linphone_proxy_config_unregister(cfg);
linphone_proxy_config_update(cfg);
}
if (lc->default_proxy==cfg){
lc->default_proxy=NULL;
@ -1139,14 +1189,25 @@ void linphone_core_clear_proxy_config(LinphoneCore *lc){
ms_list_free(copy);
linphone_proxy_config_write_all_to_config_file(lc);
}
static int linphone_core_get_default_proxy_config_index(LinphoneCore *lc) {
int pos = -1;
if (lc->default_proxy != NULL) {
pos = ms_list_position(lc->sip_conf.proxies, ms_list_find(lc->sip_conf.proxies, (void *)lc->default_proxy));
}
return pos;
}
/**
* Sets the default proxy.
*
* This default proxy must be part of the list of already entered LinphoneProxyConfig.
* Toggling it as default will make LinphoneCore use the identity associated with
* the proxy configuration in all incoming and outgoing calls.
* @param[in] lc LinphoneCore object
* @param[in] config The proxy configuration to use as the default one.
**/
void linphone_core_set_default_proxy(LinphoneCore *lc, LinphoneProxyConfig *config){
void linphone_core_set_default_proxy_config(LinphoneCore *lc, LinphoneProxyConfig *config){
/* check if this proxy is in our list */
if (config!=NULL){
if (ms_list_find(lc->sip_conf.proxies,config)==NULL){
@ -1157,7 +1218,7 @@ void linphone_core_set_default_proxy(LinphoneCore *lc, LinphoneProxyConfig *conf
}
lc->default_proxy=config;
if (linphone_core_ready(lc))
lp_config_set_int(lc->config,"sip","default_proxy",linphone_core_get_default_proxy(lc,NULL));
lp_config_set_int(lc->config,"sip","default_proxy",linphone_core_get_default_proxy_config_index(lc));
}
void linphone_core_set_default_proxy_index(LinphoneCore *lc, int index){
@ -1167,18 +1228,26 @@ void linphone_core_set_default_proxy_index(LinphoneCore *lc, int index){
/**
* Returns the default proxy configuration, that is the one used to determine the current identity.
* @deprecated Use linphone_core_get_default_proxy_config() instead.
**/
int linphone_core_get_default_proxy(LinphoneCore *lc, LinphoneProxyConfig **config){
int pos=-1;
if (config!=NULL) *config=lc->default_proxy;
if (lc->default_proxy!=NULL){
pos=ms_list_position(lc->sip_conf.proxies,ms_list_find(lc->sip_conf.proxies,(void *)lc->default_proxy));
}
return pos;
return linphone_core_get_default_proxy_config_index(lc);
}
/**
* Returns the default proxy configuration, that is the one used to determine the current identity.
* @param[in] lc LinphoneCore object
* @return The default proxy configuration.
**/
LinphoneProxyConfig * linphone_core_get_default_proxy_config(LinphoneCore *lc) {
return lc->default_proxy;
}
/**
* Returns an unmodifiable list of entered proxy configurations.
* @param[in] lc The LinphoneCore object
* @return \mslist{LinphoneProxyConfig}
**/
const MSList *linphone_core_get_proxy_config_list(const LinphoneCore *lc){
return lc->sip_conf.proxies;
@ -1205,6 +1274,9 @@ void linphone_proxy_config_write_to_config_file(LpConfig *config, LinphoneProxyC
if (obj->reg_identity!=NULL){
lp_config_set_string(config,key,"reg_identity",obj->reg_identity);
}
if (obj->realm!=NULL){
lp_config_set_string(config,key,"realm",obj->realm);
}
if (obj->contact_params!=NULL){
lp_config_set_string(config,key,"contact_parameters",obj->contact_params);
}
@ -1219,7 +1291,7 @@ void linphone_proxy_config_write_to_config_file(LpConfig *config, LinphoneProxyC
lp_config_set_int(config,key,"reg_expires",obj->expires);
lp_config_set_int(config,key,"reg_sendregister",obj->reg_sendregister);
lp_config_set_int(config,key,"publish",obj->publish);
lp_config_set_int(config, key, "avpf", obj->avpf_enabled);
lp_config_set_int(config, key, "avpf", obj->avpf_mode);
lp_config_set_int(config, key, "avpf_rr_interval", obj->avpf_rr_interval);
lp_config_set_int(config,key,"dial_escape_plus",obj->dial_escape_plus);
lp_config_set_string(config,key,"dial_prefix",obj->dial_prefix);
@ -1259,10 +1331,10 @@ LinphoneProxyConfig *linphone_proxy_config_new_from_config_file(LinphoneCore* lc
CONFIGURE_STRING_VALUE(cfg,config,key,server_addr,"reg_proxy")
CONFIGURE_STRING_VALUE(cfg,config,key,route,"reg_route")
CONFIGURE_STRING_VALUE(cfg,config,key,realm,"realm")
CONFIGURE_BOOL_VALUE(cfg,config,key,quality_reporting,"quality_reporting_enabled")
CONFIGURE_STRING_VALUE(cfg,config,key,quality_reporting_collector,"quality_reporting_collector")
CONFIGURE_INT_VALUE(cfg,config,key,quality_reporting_interval,"quality_reporting_interval")
CONFIGURE_STRING_VALUE(cfg,config,key,contact_parameters,"contact_parameters")
@ -1271,7 +1343,7 @@ LinphoneProxyConfig *linphone_proxy_config_new_from_config_file(LinphoneCore* lc
CONFIGURE_INT_VALUE(cfg,config,key,expires,"reg_expires")
CONFIGURE_BOOL_VALUE(cfg,config,key,register,"reg_sendregister")
CONFIGURE_BOOL_VALUE(cfg,config,key,publish,"publish")
CONFIGURE_BOOL_VALUE(cfg,config,key,avpf,"avpf")
CONFIGURE_INT_VALUE(cfg,config,key,avpf_mode,"avpf")
CONFIGURE_INT_VALUE(cfg,config,key,avpf_rr_interval,"avpf_rr_interval")
CONFIGURE_INT_VALUE(cfg,config,key,dial_escape_plus,"dial_escape_plus")
CONFIGURE_STRING_VALUE(cfg,config,key,dial_prefix,"dial_prefix")
@ -1298,9 +1370,9 @@ static void linphone_proxy_config_activate_sip_setup(LinphoneProxyConfig *cfg){
caps=sip_setup_context_get_capabilities(ssc);
if (caps & SIP_SETUP_CAP_ACCOUNT_MANAGER){
if (sip_setup_context_login_account(ssc,cfg->reg_identity,NULL,NULL)!=0){
if (lc->vtable.display_warning){
{
char *tmp=ms_strdup_printf(_("Could not login as %s"),cfg->reg_identity);
lc->vtable.display_warning(lc,tmp);
linphone_core_notify_display_warning(lc,tmp);
ms_free(tmp);
}
return;
@ -1337,7 +1409,7 @@ static bool_t can_register(LinphoneProxyConfig *cfg){
#endif //BUILD_UPNP
if (lc->sip_conf.register_only_when_network_is_up){
LinphoneTunnel *tunnel=linphone_core_get_tunnel(lc);
if (tunnel && linphone_tunnel_enabled(tunnel)){
if (tunnel && linphone_tunnel_get_mode(tunnel)){
return linphone_tunnel_connected(tunnel);
}else{
return lc->network_reachable;
@ -1474,12 +1546,12 @@ void linphone_account_creator_destroy(LinphoneAccountCreator *obj){
}
}
void linphone_proxy_config_set_user_data(LinphoneProxyConfig *cr, void * ud) {
cr->user_data=ud;
void linphone_proxy_config_set_user_data(LinphoneProxyConfig *cfg, void *ud) {
cfg->user_data = ud;
}
void * linphone_proxy_config_get_user_data(LinphoneProxyConfig *cr) {
return cr->user_data;
void * linphone_proxy_config_get_user_data(const LinphoneProxyConfig *cfg) {
return cfg->user_data;
}
void linphone_proxy_config_set_state(LinphoneProxyConfig *cfg, LinphoneRegistrationState state, const char *message){
@ -1500,9 +1572,8 @@ void linphone_proxy_config_set_state(LinphoneProxyConfig *cfg, LinphoneRegistrat
if (update_friends){
linphone_core_update_friends_subscriptions(lc,cfg,TRUE);
}
if (lc && lc->vtable.registration_state_changed){
lc->vtable.registration_state_changed(lc,cfg,state,message);
}
if (lc)
linphone_core_notify_registration_state_changed(lc,cfg,state,message);
} else {
/*state already reported*/
}
@ -1585,11 +1656,22 @@ int linphone_proxy_config_get_publish_expires(const LinphoneProxyConfig *obj) {
}
void linphone_proxy_config_enable_avpf(LinphoneProxyConfig *cfg, bool_t enable) {
cfg->avpf_enabled = enable;
cfg->avpf_mode=enable ? LinphoneAVPFEnabled : LinphoneAVPFDisabled;
}
bool_t linphone_proxy_config_avpf_enabled(LinphoneProxyConfig *cfg) {
return cfg->avpf_enabled;
if (cfg->avpf_mode==LinphoneAVPFDefault && cfg->lc){
return linphone_core_get_avpf_mode(cfg->lc)==LinphoneAVPFEnabled;
}
return cfg->avpf_mode == LinphoneAVPFEnabled;
}
LinphoneAVPFMode linphone_proxy_config_get_avpf_mode(const LinphoneProxyConfig *cfg){
return cfg->avpf_mode;
}
void linphone_proxy_config_set_avpf_mode(LinphoneProxyConfig *cfg, LinphoneAVPFMode mode){
cfg->avpf_mode=mode;
}
void linphone_proxy_config_set_avpf_rr_interval(LinphoneProxyConfig *cfg, uint8_t interval) {
@ -1600,3 +1682,7 @@ void linphone_proxy_config_set_avpf_rr_interval(LinphoneProxyConfig *cfg, uint8_
uint8_t linphone_proxy_config_get_avpf_rr_interval(const LinphoneProxyConfig *cfg) {
return cfg->avpf_rr_interval;
}
char* linphone_proxy_config_get_contact(const LinphoneProxyConfig *cfg) {
return sal_op_get_public_uri(cfg->op);
}

View file

@ -405,15 +405,9 @@ static void update_ip(LinphoneCall * call, int stats_type) {
}
}
typedef struct on_action_suggested_struct{
LinphoneCall *call;
int stats_type;
}on_action_suggested_struct_t;
static void qos_analyzer_on_action_suggested(void *user_data, int datac, const char** datav){
on_action_suggested_struct_t * oass = (on_action_suggested_struct_t *)user_data;
LinphoneCall *call = oass->call;
reporting_session_report_t *report = call->log->reporting.reports[oass->stats_type];
reporting_session_report_t *report = (reporting_session_report_t*)user_data;
LinphoneCall *call = report->call;
char * appendbuf;
int i;
int ptime = -1;
@ -653,16 +647,16 @@ int linphone_reporting_publish_interval_report(LinphoneCall* call) {
void linphone_reporting_call_state_updated(LinphoneCall *call){
LinphoneCallState state=linphone_call_get_state(call);
MSQosAnalyzer *analyzer;
int i;
if (! quality_reporting_enabled(call)){
if (state == LinphoneCallReleased||!quality_reporting_enabled(call)){
return;
}
switch (state){
case LinphoneCallStreamsRunning:{
bool_t video_enabled=media_report_enabled(call, LINPHONE_CALL_STATS_VIDEO);
int i;
MediaStream *streams[2] = {(MediaStream*) call->audiostream, (MediaStream *) call->videostream};
MSQosAnalyzer *analyzer;
for (i=0;i<2;i++){
if (streams[i]==NULL||streams[i]->rc==NULL){
@ -673,14 +667,12 @@ void linphone_reporting_call_state_updated(LinphoneCall *call){
analyzer=ms_bitrate_controller_get_qos_analyzer(streams[i]->rc);
if (analyzer){
on_action_suggested_struct_t * oass = ms_new0(on_action_suggested_struct_t, 1);
oass->call = call;
oass->stats_type = i;
call->log->reporting.reports[i]->call=call;
STR_REASSIGN(call->log->reporting.reports[i]->qos_analyzer.name, ms_strdup(ms_qos_analyzer_get_name(analyzer)));
ms_qos_analyzer_set_on_action_suggested(analyzer,
qos_analyzer_on_action_suggested,
oass);
call->log->reporting.reports[i]);
}
}
linphone_reporting_update_ip(call);
@ -691,6 +683,16 @@ void linphone_reporting_call_state_updated(LinphoneCall *call){
break;
}
case LinphoneCallEnd:{
MediaStream *streams[2] = {(MediaStream*) call->audiostream, (MediaStream *) call->videostream};
for (i=0;i<2;i++){
if (streams[i]==NULL||streams[i]->rc==NULL){
continue;
}
analyzer=ms_bitrate_controller_get_qos_analyzer(streams[i]->rc);
if (analyzer){
ms_qos_analyzer_set_on_action_suggested(analyzer, NULL, NULL);
}
}
if (call->log->status==LinphoneCallSuccess || call->log->status==LinphoneCallAborted){
linphone_reporting_publish_session_report(call, TRUE);
}

View file

@ -137,6 +137,7 @@ typedef struct reporting_session_report {
// for internal processing
time_t last_report_date;
LinphoneCall *call;
} reporting_session_report_t;

View file

@ -36,23 +36,31 @@ static void xml2lpc_callback(void *ctx, xml2lpc_log_level level, const char *fmt
static void linphone_remote_provisioning_apply(LinphoneCore *lc, const char *xml) {
xml2lpc_context *context = xml2lpc_context_new(xml2lpc_callback, lc);
int result = xml2lpc_set_xml_string(context, xml);
char * error_msg = NULL;
if (result == 0) {
result = xml2lpc_convert(context, linphone_core_get_config(lc));
LpConfig * lpc = linphone_core_get_config(lc);
result = xml2lpc_convert(context, lpc);
if (result == 0) {
lp_config_sync(linphone_core_get_config(lc));
xml2lpc_context_destroy(context);
linphone_configuring_terminated(lc, LinphoneConfiguringSuccessful, NULL);
// if the remote provisioning added a proxy config and none was set before, set it
if (lp_config_has_section(lpc, "proxy_0") && lp_config_get_int(lpc, "sip", "default_proxy", -1) == -1){
lp_config_set_int(lpc, "sip", "default_proxy", 0);
}
lp_config_sync(lpc);
} else {
xml2lpc_context_destroy(context);
linphone_configuring_terminated(lc, LinphoneConfiguringFailed, "xml to lpc failed");
error_msg = "xml to lpc failed";
}
} else {
xml2lpc_context_destroy(context);
linphone_configuring_terminated(lc, LinphoneConfiguringFailed, "invalid xml");
error_msg = "invalid xml";
}
xml2lpc_context_destroy(context);
linphone_configuring_terminated(lc
,error_msg ? LinphoneConfiguringFailed : LinphoneConfiguringSuccessful
, error_msg);
}
static int linphone_remote_provisioning_load_file( LinphoneCore* lc, const char* file_path){
int linphone_remote_provisioning_load_file( LinphoneCore* lc, const char* file_path){
int status = -1;
FILE* f = fopen(file_path, "r");

View file

@ -307,7 +307,7 @@ 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->nb_streams != md2->nb_streams) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED;
if (md1->nb_streams != md2->nb_streams) result |= SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED;
if (md1->bandwidth != md2->bandwidth) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED;
for(i = 0; i < md1->nb_streams; ++i){
result |= sal_stream_description_equals(&md1->streams[i], &md2->streams[i]);
@ -386,6 +386,13 @@ void sal_op_add_route_address(SalOp *op, const SalAddress *address){
sal_op_set_route_address(op,address);
}
}
void sal_op_set_realm(SalOp *op, const char *realm){
SalOpBase* op_base = (SalOpBase*)op;
if (op_base->realm != NULL){
ms_free(op_base->realm);
}
op_base->realm = ms_strdup(realm);
}
void sal_op_set_from(SalOp *op, const char *from){
SET_PARAM(op,from);
}
@ -511,6 +518,10 @@ void __sal_op_free(SalOp *op){
ms_free(b->route);
b->route=NULL;
}
if (b->realm) {
ms_free(b->realm);
b->realm=NULL;
}
if (b->contact_address) {
sal_address_destroy(b->contact_address);
}
@ -724,3 +735,9 @@ belle_sip_stack_t *sal_get_belle_sip_stack(Sal *sal) {
return sal->stack;
}
char* sal_op_get_public_uri(SalOp *op) {
if (op && op->refresher) {
return belle_sip_refresher_get_public_uri(op->refresher);
}
return NULL;
}

View file

@ -607,7 +607,7 @@ int linphone_upnp_context_send_add_port_binding(UpnpContext *lupnp, UpnpPortBind
mapping.remote_port = port->external_port;
mapping.remote_host = "";
snprintf(description, 128, "%s %s at %s:%d",
PACKAGE_NAME,
"Linphone",
(port->protocol == UPNP_IGD_IP_PROTOCOL_TCP)? "TCP": "UDP",
port->local_addr, port->local_port);
mapping.description = description;
@ -834,7 +834,7 @@ int linphone_upnp_call_process(LinphoneCall *call) {
linphone_core_start_update_call(lc, call);
break;
case LinphoneCallUpdatedByRemote:
linphone_core_start_accept_call_update(lc, call);
linphone_core_start_accept_call_update(lc, call,call->prevstate,linphone_call_state_to_string(call->prevstate));
break;
case LinphoneCallOutgoingInit:
linphone_core_proceed_with_invite_if_ready(lc, call, NULL);

View file

@ -18,7 +18,7 @@ UI_FILES= about.ui \
audio_assistant.ui
PIXMAPS= \
stock_people.png
stock_people.png
LINPHONE_ICO_RC_FILE=linphone.rc
LINPHONE_ICO_FILE=linphone.ico
@ -54,7 +54,7 @@ linphone_SOURCES= \
conference.c \
config-fetching.c \
audio_assistant.c \
linphone.h
linphone.h
if BUILD_WIZARD
linphone_SOURCES+= \
setupwizard.c
@ -84,7 +84,7 @@ endif
AM_CFLAGS= -DIN_LINPHONE -I$(top_srcdir)/coreapi/ \
$(MEDIASTREAMER_CFLAGS) \
$(ORTP_CFLAGS) $(BELLESIP_CFLAGS) \
$(STRICT_OPTIONS) $(LIBGTK_CFLAGS) $(LIBGTKMAC_CFLAGS) $(IPV6_CFLAGS) \
$(STRICT_OPTIONS) $(STRICT_OPTIONS_CC) $(LIBGTK_CFLAGS) $(LIBGTKMAC_CFLAGS) $(IPV6_CFLAGS) \
$(TUNNEL_CFLAGS) \
$(SQLITE3_CFLAGS)

View file

@ -168,11 +168,12 @@ static void dialog_click(GtkWidget *dialog, guint response_id, GtkWidget *page){
}
static void calibration_finished(LinphoneCore *lc, LinphoneEcCalibratorStatus status, int delay, void *data){
GtkWidget * dialog;
GtkWidget *speaker_page;
ms_message("echo calibration finished %s.",status==LinphoneEcCalibratorDone ? "successfully" : "with faillure");
if (status==LinphoneEcCalibratorDone) ms_message("Measured delay is %i",delay);
GtkWidget * dialog;
GtkWidget *speaker_page = get_widget_from_assistant("speaker_page");
speaker_page = get_widget_from_assistant("speaker_page");
dialog = gtk_message_dialog_new (
GTK_WINDOW(audio_assistant),
@ -208,6 +209,7 @@ void linphone_gtk_start_record_sound(GtkWidget *w, gpointer data){
AudioStream *stream = NULL;
MSSndCardManager *manager = ms_snd_card_manager_get();
gboolean active=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w));
gint timeout_id;
if(active){
gchar *path = get_record_file();
@ -217,12 +219,12 @@ void linphone_gtk_start_record_sound(GtkWidget *w, gpointer data){
path,NULL,ms_snd_card_manager_get_card(manager,linphone_core_get_capture_device(lc)),FALSE);
g_object_set_data(G_OBJECT(audio_assistant),"record_stream",stream);
}
gint timeout_id = gtk_timeout_add(6000,(GtkFunction)linphone_gtk_stop_record,NULL);
timeout_id = gtk_timeout_add(6000,(GtkFunction)linphone_gtk_stop_record,NULL);
g_object_set_data(G_OBJECT(audio_assistant),"timeout_id",GINT_TO_POINTER(timeout_id));
g_object_set_data(G_OBJECT(audio_assistant),"path",path);
} else {
stream = (AudioStream *)g_object_get_data(G_OBJECT(audio_assistant),"record_stream");
gint timeout_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(audio_assistant),"timeout_id"));
timeout_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(audio_assistant),"timeout_id"));
gtk_timeout_remove(timeout_id);
if(stream != NULL){
audio_stream_stop(stream);
@ -322,7 +324,7 @@ static GtkWidget *create_intro(){
static GtkWidget *create_mic_page(){
GtkWidget *vbox=gtk_table_new(3,2,FALSE);
LinphoneCore *lc=linphone_gtk_get_core();
const char **sound_devices;
GtkWidget *labelMicChoice=gtk_label_new(_("Capture device"));
GtkWidget *labelMicLevel=gtk_label_new(_("Recorded volume"));
GtkWidget *mic_audiolevel=gtk_progress_bar_new();
@ -348,8 +350,8 @@ static GtkWidget *create_mic_page(){
set_widget_to_assistant("mic_audiolevel",mic_audiolevel);
set_widget_to_assistant("label_audiolevel",label_audiolevel);
const char **sound_devices=linphone_core_get_sound_devices(lc);
sound_devices=linphone_core_get_sound_devices(lc);
linphone_gtk_fill_combo_box(capture_device, sound_devices,
linphone_core_get_capture_device(lc), CAP_CAPTURE);
gtk_widget_show_all(vbox);
@ -370,6 +372,7 @@ static GtkWidget *create_speaker_page(){
GtkWidget *playback_device=gtk_combo_box_new();
GtkWidget *mixer_button=gtk_button_new_with_label("System sound preferences");
GtkWidget *image;
const char **sound_devices;
image=gtk_image_new_from_stock(GTK_STOCK_PREFERENCES,GTK_ICON_SIZE_MENU);
gtk_button_set_image(GTK_BUTTON(mixer_button),image);
@ -382,7 +385,7 @@ static GtkWidget *create_speaker_page(){
gtk_table_set_row_spacings(GTK_TABLE(vbox),10);
const char **sound_devices=linphone_core_get_sound_devices(lc);
sound_devices=linphone_core_get_sound_devices(lc);
linphone_gtk_fill_combo_box(playback_device, sound_devices,
linphone_core_get_playback_device(lc),CAP_PLAYBACK);
gtk_widget_show_all(vbox);
@ -414,9 +417,9 @@ static GtkWidget *create_play_record_page(){
gtk_table_attach(GTK_TABLE(vbox), rec_button, 1, 2, 0, 1, GTK_SHRINK, GTK_SHRINK, 0,0);
gtk_table_attach_defaults(GTK_TABLE(vbox), labelPlay, 0, 1, 1, 2);
gtk_table_attach(GTK_TABLE(vbox), play_button, 1, 2, 1, 2, GTK_SHRINK, GTK_SHRINK, 0,0);
gtk_widget_show_all(vbox);
set_widget_to_assistant("rec_button",rec_button);
set_widget_to_assistant("play_button",play_button);
g_signal_connect(G_OBJECT(rec_button),"toggled",(GCallback)linphone_gtk_start_record_sound,vbox);
@ -480,18 +483,23 @@ void linphone_gtk_audio_assistant_apply(GtkWidget *w){
void linphone_gtk_show_audio_assistant(void){
GtkWidget *w;
GtkWidget *welcome;
GtkWidget *mic_page;
GtkWidget *speaker_page;
GtkWidget *play_record_page;
GtkWidget *end_page;
if(audio_assistant!=NULL)
return;
w=audio_assistant=linphone_gtk_create_window("audio_assistant");
gtk_window_set_resizable (GTK_WINDOW(w), FALSE);
gtk_window_set_title(GTK_WINDOW(w),_("Audio Assistant"));
GtkWidget *welcome=create_intro();
GtkWidget *mic_page=create_mic_page();
GtkWidget *speaker_page=create_speaker_page();
GtkWidget *play_record_page=create_play_record_page();
GtkWidget *end_page=create_end_page();
welcome=create_intro();
mic_page=create_mic_page();
speaker_page=create_speaker_page();
play_record_page=create_play_record_page();
end_page=create_end_page();
gtk_assistant_append_page(GTK_ASSISTANT(w),welcome);
gtk_assistant_set_page_type(GTK_ASSISTANT(w),welcome,GTK_ASSISTANT_PAGE_INTRO);

View file

@ -36,7 +36,7 @@ void call_log_selection_changed(GtkTreeView *v){
GtkTreeSelection *select;
GtkTreeIter iter;
GtkTreeModel *model=NULL;
select = gtk_tree_view_get_selection(v);
if (select!=NULL){
if (gtk_tree_selection_get_selected (select, &model, &iter)){
@ -51,7 +51,7 @@ void call_log_selection_changed(GtkTreeView *v){
void linphone_gtk_call_log_chat_selected(GtkWidget *w){
GtkTreeSelection *select;
GtkTreeIter iter;
select=gtk_tree_view_get_selection(GTK_TREE_VIEW(w));
if (select!=NULL){
GtkTreeModel *model=NULL;
@ -72,7 +72,7 @@ void linphone_gtk_call_log_chat_selected(GtkWidget *w){
void linphone_gtk_call_log_add_contact(GtkWidget *w){
GtkTreeSelection *select;
GtkTreeIter iter;
select=gtk_tree_view_get_selection(GTK_TREE_VIEW(w));
if (select!=NULL){
GtkTreeModel *model=NULL;
@ -109,7 +109,7 @@ static bool_t put_selection_to_uribar(GtkWidget *treeview){
cl = (LinphoneCallLog *)pcl;
la = linphone_call_log_get_dir(cl)==LinphoneCallIncoming ? linphone_call_log_get_from(cl) : linphone_call_log_get_to(cl);
tmp = linphone_address_as_string(la);
if(tmp!=NULL)
if(tmp!=NULL)
gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"uribar")),tmp);
ms_free(tmp);
return TRUE;
@ -133,7 +133,7 @@ static GtkWidget *linphone_gtk_create_call_log_menu(GtkWidget *call_log){
GtkWidget *image;
GtkTreeSelection *select;
GtkTreeIter iter;
select=gtk_tree_view_get_selection(GTK_TREE_VIEW(call_log));
if (select!=NULL){
GtkTreeModel *model=NULL;
@ -202,7 +202,7 @@ void linphone_gtk_call_log_clear_missed_call(){
GtkWidget *image=gtk_image_new_from_stock(GTK_STOCK_REFRESH,GTK_ICON_SIZE_MENU);
GtkWidget *l;
const gchar*text=gtk_label_get_text(GTK_LABEL(linphone_gtk_get_widget(mw,"label3")));
l=gtk_label_new(text);
gtk_box_pack_start(GTK_BOX(box),image,FALSE,FALSE,0);
gtk_box_pack_start(GTK_BOX(box),l,FALSE,FALSE,0);
@ -228,7 +228,7 @@ void linphone_gtk_call_log_display_missed_call(int nb){
GtkWidget *image=gtk_image_new_from_stock(GTK_STOCK_REFRESH,GTK_ICON_SIZE_MENU);
GtkWidget *l;
gchar *buf;
buf=g_markup_printf_escaped(_("<b>Recent calls (%i)</b>"),nb);
l=gtk_label_new(NULL);
gtk_label_set_markup(GTK_LABEL(l),buf);
@ -281,7 +281,9 @@ void linphone_gtk_call_log_update(GtkWidget *w){
LinphoneFriend *lf=NULL;
int duration=linphone_call_log_get_duration(cl);
time_t start_date_time=linphone_call_log_get_start_date(cl);
GdkPixbuf *incoming;
GdkPixbuf *outgoing;
#if GLIB_CHECK_VERSION(2,26,0)
if (start_date_time){
GDateTime *dt=g_date_time_new_from_unix_local(start_date_time);
@ -332,7 +334,7 @@ void linphone_gtk_call_log_update(GtkWidget *w){
if (status==NULL) {
headtxt=g_markup_printf_escaped(_("<big><b>%s</b></big>\t%s"),display,start_date ? start_date : "");
logtxt=g_markup_printf_escaped(
_("<small><i>%s</i>\t"
_("<small><i>%s</i>\t"
"<i>Quality: %s</i></small>\n%s\t%s\t"),
addr, quality, minutes, seconds);
} else {
@ -346,8 +348,8 @@ void linphone_gtk_call_log_update(GtkWidget *w){
if (start_date) g_free(start_date);
gtk_tree_store_append (store,&iter,NULL);
GdkPixbuf *incoming = create_pixbuf("call_status_incoming.png");
GdkPixbuf *outgoing = create_pixbuf("call_status_outgoing.png");
incoming = create_pixbuf("call_status_incoming.png");
outgoing = create_pixbuf("call_status_outgoing.png");
gtk_tree_store_set (store,&iter,
0, linphone_call_log_get_dir(cl)==LinphoneCallOutgoing ? outgoing : incoming,
1, headtxt,2,cl,-1);

View file

@ -30,9 +30,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
const char *linphone_gtk_message_storage_get_db_file(const char *filename){
const int path_max=1024;
static char *db_file=NULL;
if (db_file) return db_file;
db_file=(char *)malloc(path_max*sizeof(char));
if (filename==NULL) filename=CONFIG_FILE;
/*try accessing a local file first if exists*/
@ -63,7 +63,7 @@ void linphone_gtk_quit_chatroom(LinphoneChatRoom *cr) {
GtkWidget *w=g_object_get_data(G_OBJECT(friendlist),"chatview");
gchar *from;
GHashTable *table=g_object_get_data(G_OBJECT(w),"table");
g_return_if_fail(w!=NULL);
gtk_notebook_remove_page(GTK_NOTEBOOK(nb),gtk_notebook_page_num(GTK_NOTEBOOK(nb),w));
linphone_chat_room_mark_as_read(cr);
@ -95,7 +95,7 @@ GtkWidget *create_tab_chat_header(LinphoneChatRoom *cr,const LinphoneAddress *ur
GtkWidget *l;
GtkWidget *image=gtk_image_new_from_stock(GTK_STOCK_CLOSE,GTK_ICON_SIZE_MENU);
GtkWidget *b=gtk_button_new();
gtk_button_set_image(GTK_BUTTON(b),image);
gtk_button_set_relief(GTK_BUTTON(b),GTK_RELIEF_NONE);
gtk_widget_set_size_request(b,25,20);
@ -131,14 +131,15 @@ void udpate_tab_chat_header(GtkWidget *chat_view,const LinphoneAddress *uri,Linp
static gboolean scroll_to_end(GtkTextView *w){
GtkTextBuffer *buffer=gtk_text_view_get_buffer(w);
GtkTextMark *mark;
GtkTextIter iter;
gtk_text_buffer_get_end_iter(buffer,&iter);
GtkTextMark *mark=gtk_text_buffer_create_mark(buffer,NULL,&iter,FALSE);
gtk_text_view_scroll_mark_onscreen(w,mark);
mark=gtk_text_buffer_create_mark(buffer,NULL,&iter,FALSE);
gtk_text_view_scroll_mark_onscreen(w,mark);
return FALSE;
}
void linphone_gtk_push_text(GtkWidget *w, const LinphoneAddress *from,
void linphone_gtk_push_text(GtkWidget *w, const LinphoneAddress *from,
gboolean me,LinphoneChatRoom *cr,LinphoneChatMessage *msg, gboolean hist){
GtkTextView *text=GTK_TEXT_VIEW(linphone_gtk_get_widget(w,"textview"));
GtkTextBuffer *buffer=gtk_text_view_get_buffer(text);
@ -153,7 +154,7 @@ void linphone_gtk_push_text(GtkWidget *w, const LinphoneAddress *from,
struct tm *tm;
int tnow_day;
int tnow_year;
gtk_text_buffer_get_start_iter(buffer,&begin);
gtk_text_buffer_get_end_iter(buffer,&iter);
off=gtk_text_iter_get_offset(&iter);
@ -178,7 +179,7 @@ void linphone_gtk_push_text(GtkWidget *w, const LinphoneAddress *from,
case LinphoneChatMessageStateInProgress:
{
g_hash_table_insert(table,(gpointer)msg,GINT_TO_POINTER(gtk_text_iter_get_line(&iter)));
gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,"Sending ..",-1,
gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,"Sending ..",-1,
"right","small","italic","font_grey","bg",NULL);
g_object_set_data(G_OBJECT(w),"table",table);
break;
@ -195,15 +196,15 @@ void linphone_gtk_push_text(GtkWidget *w, const LinphoneAddress *from,
} else {
strftime(buf,80,"%H:%M",tm);
}
gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,buf,-1,
gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,buf,-1,
"right","small","italic","font_grey",me ? "bg":NULL,NULL);
break;
}
case LinphoneChatMessageStateNotDelivered:
gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,"Message not sent",-1,
gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,"Message not sent",-1,
"right","small","italic","font_grey",me ? "bg":NULL,NULL);
break;
default : gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,"Sending ..",-1,
default : gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,"Sending ..",-1,
"right","small","italic","font_grey",me ? "bg":NULL,NULL);
}
gtk_text_buffer_get_end_iter(buffer,&iter);
@ -225,7 +226,7 @@ void update_chat_state_message(LinphoneChatMessageState state,LinphoneChatMessag
GtkWidget *friendlist=linphone_gtk_get_widget(main_window,"contact_list");
GtkWidget *page=(GtkWidget*)g_object_get_data(G_OBJECT(friendlist),"chatview");
GHashTable *table=(GHashTable*)g_object_get_data(G_OBJECT(page),"table");
if(page!=NULL){
GtkTextView *text=GTK_TEXT_VIEW(linphone_gtk_get_widget(page,"textview"));
GtkTextBuffer *b=gtk_text_view_get_buffer(text);
@ -272,7 +273,7 @@ void update_chat_state_message(LinphoneChatMessageState state,LinphoneChatMessag
gtk_text_buffer_insert_with_tags_by_name(b,&iter,result,-1,
"right","small","italic","font_grey","bg",NULL);
g_object_set_data(G_OBJECT(page),"table",table);
}
}
}
static void on_chat_state_changed(LinphoneChatMessage *msg, LinphoneChatMessageState state, void *user_pointer){
@ -330,8 +331,8 @@ void display_history_message(GtkWidget *chat_view,MSList *messages,const Linphon
LinphoneChatMessage *msg=(LinphoneChatMessage *)it->data;
from_str=linphone_address_as_string_uri_only(linphone_chat_message_get_from(msg));
with_str=linphone_address_as_string_uri_only(with);
linphone_gtk_push_text(chat_view,strcmp(from_str,with_str)==0? with :
linphone_chat_message_get_from(msg),
linphone_gtk_push_text(chat_view,strcmp(from_str,with_str)==0? with :
linphone_chat_message_get_from(msg),
strcmp(from_str,with_str)==0? FALSE : TRUE,
linphone_chat_message_get_chat_room(msg),msg,TRUE);
}
@ -343,7 +344,7 @@ void display_history_message(GtkWidget *chat_view,MSList *messages,const Linphon
ms_free(from_str);
ms_free(with_str);
linphone_gtk_free_list(messages);
}
}
}
void linphone_gtk_chat_add_contact(const LinphoneAddress *addr){
@ -445,7 +446,7 @@ void linphone_gtk_load_chatroom(LinphoneChatRoom *cr,const LinphoneAddress *uri,
char *uri_str=linphone_address_as_string(uri);
char *uri_only=linphone_address_as_string_uri_only(uri);
MSList *messages=NULL;
if(g_strcmp0(from_str,uri_only)!=0){
GtkTextView *text_view=GTK_TEXT_VIEW(linphone_gtk_get_widget(chat_view,"textview"));
GtkTextIter start;
@ -483,7 +484,7 @@ void linphone_gtk_text_received ( LinphoneCore *lc, LinphoneChatRoom *room,
gboolean send=TRUE;
/*GtkNotebook *notebook= ( GtkNotebook * ) linphone_gtk_get_widget ( main_window,"viewswitch" );*/
const LinphoneAddress *from= linphone_chat_message_get_from ( msg );
w= ( GtkWidget* ) g_object_get_data ( G_OBJECT ( friendlist ),"chatview" );
if ( w!=NULL ) {
/* Chat window opened */
@ -496,7 +497,7 @@ void linphone_gtk_text_received ( LinphoneCore *lc, LinphoneChatRoom *room,
}
send=FALSE;
}
} else {
} else {
/* Chat window closed */
#ifdef MSG_STORAGE_ENABLED
send=FALSE;
@ -530,7 +531,7 @@ void linphone_gtk_text_received ( LinphoneCore *lc, LinphoneChatRoom *room,
}
linphone_core_play_local(lc,linphone_gtk_get_sound_path("incoming_chat.wav"));
linphone_gtk_show_friends();
}
void linphone_gtk_is_composing_received(LinphoneCore *lc, LinphoneChatRoom *room) {

View file

@ -61,9 +61,9 @@ static GtkWidget *find_conferencee_from_call(LinphoneCall *call){
GtkWidget *conferencee_box=get_conferencee_box(mw);
GList *elem;
GtkWidget *ret=NULL;
if (conferencee_box==NULL) return NULL;
if (call!=NULL){
GList *l=gtk_container_get_children(GTK_CONTAINER(conferencee_box));
for(elem=l;elem!=NULL;elem=elem->next){
@ -87,13 +87,14 @@ static GtkWidget * create_conference_panel(void){
GtkWidget *image=create_pixmap("stopcall-small.png");
GtkWidget *box;
GtkWidget *viewswitch=linphone_gtk_get_widget(mw,"viewswitch");
GtkWidget *participant;
gtk_button_set_image(GTK_BUTTON(button_conf),image);
g_signal_connect_swapped(G_OBJECT(button_conf),"clicked",(GCallback)linphone_gtk_terminate_call,NULL);
g_object_set_data(G_OBJECT(mw),"conf_frame",(gpointer)conf_frame);
box=gtk_vbox_new(FALSE,0);
GtkWidget *participant=linphone_gtk_create_widget("main","callee_frame");
participant=linphone_gtk_create_widget("main","callee_frame");
gtk_widget_show(participant);
gtk_box_set_homogeneous(GTK_BOX(box),TRUE);
init_local_participant(participant);
@ -101,7 +102,7 @@ static GtkWidget * create_conference_panel(void){
gtk_widget_show(box);
g_object_set_data(G_OBJECT(mw),"conferencee_box",box);
gtk_box_pack_start(GTK_BOX(conf_box),box,FALSE,FALSE,PADDING_PIXELS);
gtk_notebook_append_page(GTK_NOTEBOOK(viewswitch),conf_frame,
create_conference_label());
return conf_frame;
@ -111,19 +112,20 @@ void linphone_gtk_set_in_conference(LinphoneCall *call){
GtkWidget *mw=linphone_gtk_get_main_window();
GtkWidget *conf_frame=(GtkWidget *)g_object_get_data(G_OBJECT(mw),"conf_frame");
GtkWidget *viewswitch=linphone_gtk_get_widget(mw,"viewswitch");
GtkWidget *participant;
if(conf_frame==NULL){
conf_frame=create_conference_panel();
}
GtkWidget *participant=find_conferencee_from_call(call);
participant=find_conferencee_from_call(call);
if (participant==NULL){
/*create and add it */
GtkWidget *conferencee_box=get_conferencee_box(mw);
GtkWidget *sound_meter;
const LinphoneAddress *addr=linphone_call_get_remote_address(call);
gchar *markup;
participant=linphone_gtk_create_widget("main","callee_frame");
gtk_widget_show(participant);
if (linphone_address_get_display_name(addr)!=NULL){
@ -140,7 +142,7 @@ void linphone_gtk_set_in_conference(LinphoneCall *call){
gtk_box_pack_start(GTK_BOX(conferencee_box),participant,FALSE,FALSE,PADDING_PIXELS);
g_object_set_data_full(G_OBJECT(participant),"call",linphone_call_ref(call),(GDestroyNotify)linphone_call_unref);
gtk_notebook_set_current_page(GTK_NOTEBOOK(viewswitch),
gtk_notebook_page_num(GTK_NOTEBOOK(viewswitch),conf_frame));
gtk_notebook_page_num(GTK_NOTEBOOK(viewswitch),conf_frame));
}
}
@ -153,13 +155,13 @@ void linphone_gtk_terminate_conference_participant(LinphoneCall *call){
void linphone_gtk_unset_from_conference(LinphoneCall *call){
GtkWidget *frame=find_conferencee_from_call(call);
if (frame){
GtkWidget *mw=linphone_gtk_get_main_window();
GtkWidget *conf_frame=(GtkWidget *)g_object_get_data(G_OBJECT(mw),"conf_frame");
GtkWidget *conferencee_box=g_object_get_data(G_OBJECT(mw),"conferencee_box");
GList *children;
g_message("Removing a participant from conference");
gtk_widget_destroy(frame);
children=gtk_container_get_children(GTK_CONTAINER(conferencee_box));

View file

@ -198,7 +198,7 @@ void linphone_gtk_delete_history(GtkWidget *button){
GtkWidget *chat_view;
LinphoneFriend *lf=NULL;
GtkWidget *friendlist;
friendlist=linphone_gtk_get_widget(w,"contact_list");
chat_view=(GtkWidget *)g_object_get_data(G_OBJECT(friendlist),"chatview");
select = gtk_tree_view_get_selection(GTK_TREE_VIEW(friendlist));
@ -216,7 +216,7 @@ void linphone_gtk_delete_history(GtkWidget *button){
GtkTextIter start;
GtkTextIter end;
GtkTextBuffer *text_buffer;
text_buffer=gtk_text_view_get_buffer(text_view);
gtk_text_buffer_get_bounds(text_buffer, &start, &end);
gtk_text_buffer_delete (text_buffer, &start, &end);
@ -290,7 +290,7 @@ void linphone_gtk_friend_list_set_chat_conversation(const LinphoneAddress *la){
LinphoneFriend *lf=NULL;
LinphoneChatRoom *cr=NULL;
GtkNotebook *notebook=(GtkNotebook *)linphone_gtk_get_widget(w,"viewswitch");
lf=linphone_core_find_friend(linphone_gtk_get_core(),la);
if(lf==NULL){
cr=linphone_gtk_create_chatroom(la);
@ -331,7 +331,7 @@ void linphone_gtk_friend_list_set_chat_conversation(const LinphoneAddress *la){
}
}while(gtk_tree_model_iter_next(model,&iter));
}
}
}
}
void linphone_gtk_notebook_tab_select(GtkNotebook *notebook,GtkWidget *page,guint page_num, gpointer data){
@ -595,11 +595,11 @@ static int get_friend_weight(const LinphoneFriend *lf){
int w=0;
LinphoneCore *lc=linphone_gtk_get_core();
LinphoneChatRoom *cr=linphone_core_get_chat_room(lc,linphone_friend_get_address(lf));
if (cr && linphone_chat_room_get_unread_messages_count(cr)>0){
w+=2000;
}
switch(linphone_friend_get_status(lf)){
case LinphoneStatusOnline:
w+=1000;
@ -685,7 +685,7 @@ static void linphone_gtk_friend_list_init(GtkWidget *friendlist){
gtk_tree_view_set_search_equal_func(GTK_TREE_VIEW(friendlist),friend_search_func,NULL,NULL);
gtk_tree_view_set_search_column(GTK_TREE_VIEW(friendlist),FRIEND_NAME);
gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store),FRIEND_NAME,friend_sort,NULL,NULL);
/*Name and presence column*/
renderer = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes (_("Presence status"),
@ -781,8 +781,9 @@ gboolean linphone_gtk_directory_search_focus_in(GtkWidget *entry){
void linphone_gtk_directory_search_activate(GtkWidget *entry){
LinphoneProxyConfig *cfg;
GtkWidget *w;
linphone_core_get_default_proxy(linphone_gtk_get_core(),&cfg);
GtkWidget *w=linphone_gtk_show_buddy_lookup_window(linphone_proxy_config_get_sip_setup_context(cfg));
w=linphone_gtk_show_buddy_lookup_window(linphone_proxy_config_get_sip_setup_context(cfg));
if (GPOINTER_TO_INT(g_object_get_data(G_OBJECT(entry),"active"))==1)
linphone_gtk_buddy_lookup_set_keyword(w,gtk_entry_get_text(GTK_ENTRY(entry)));
}
@ -809,7 +810,7 @@ void linphone_gtk_show_friends(void){
if (gtk_tree_view_get_model(GTK_TREE_VIEW(friendlist))==NULL){
linphone_gtk_friend_list_init(friendlist);
}
store=GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(friendlist)));
gtk_list_store_clear(store);
@ -1076,7 +1077,7 @@ static gint tree_view_get_cell_from_pos(GtkTreeView *view, guint x, guint y){
gint colx = 0;
GtkTreePath *path;
GtkTreeViewDropPosition pos;
g_return_val_if_fail ( view != NULL, 0 );
columns = gtk_tree_view_get_columns(view);
@ -1086,8 +1087,7 @@ static gint tree_view_get_cell_from_pos(GtkTreeView *view, guint x, guint y){
GtkTreeViewColumn *checkcol = (GtkTreeViewColumn*) node->data;
if (x >= colx && x < (colx + checkcol->width)){
col = checkcol;
gint num = get_col_number_from_tree_view_column(col);
return num;
return get_col_number_from_tree_view_column(col);
} else {
colx += checkcol->width;
}

View file

@ -269,7 +269,7 @@ static void _refresh_call_stats(GtkWidget *callstats, LinphoneCall *call){
gtk_label_set_markup(GTK_LABEL(linphone_gtk_get_widget(callstats,"audio_bandwidth_usage")),tmp);
g_free(tmp);
if (has_video){
gchar *size_r=g_strdup_printf(_("%ix%i @ %f fps"),size_received.width,size_received.height,
gchar *size_r=g_strdup_printf(_("%ix%i @ %f fps"),size_received.width,size_received.height,
linphone_call_params_get_received_framerate(curparams));
gchar *size_s=g_strdup_printf(_("%ix%i @ %f fps"),size_sent.width,size_sent.height,
linphone_call_params_get_sent_framerate(curparams));
@ -366,6 +366,11 @@ void linphone_gtk_create_in_call_view(LinphoneCall *call){
GtkNotebook *notebook=(GtkNotebook *)linphone_gtk_get_widget(main_window,"viewswitch");
static int call_index=1;
int idx;
GtkWidget *transfer;
GtkWidget *conf;
GtkWidget *button;
GtkWidget *image;
if (ms_list_size(linphone_core_get_calls(linphone_gtk_get_core()))==1){
/*this is the only call at this time */
@ -386,19 +391,19 @@ void linphone_gtk_create_in_call_view(LinphoneCall *call){
linphone_gtk_enable_mute_button(
GTK_BUTTON(linphone_gtk_get_widget(call_view,"incall_mute")),FALSE);
GtkWidget *transfer = linphone_gtk_get_widget(call_view,"transfer_button");
transfer = linphone_gtk_get_widget(call_view,"transfer_button");
gtk_button_set_image(GTK_BUTTON(transfer),gtk_image_new_from_stock
(GTK_STOCK_GO_FORWARD,GTK_ICON_SIZE_BUTTON));
g_signal_connect(G_OBJECT(transfer),"clicked",(GCallback)transfer_button_clicked,call);
gtk_widget_hide(transfer);
GtkWidget *conf = linphone_gtk_get_widget(call_view,"conference_button");
conf = linphone_gtk_get_widget(call_view,"conference_button");
gtk_button_set_image(GTK_BUTTON(conf),gtk_image_new_from_stock (GTK_STOCK_ADD,GTK_ICON_SIZE_BUTTON));
g_signal_connect(G_OBJECT(conf),"clicked",(GCallback)conference_button_clicked,call);
gtk_widget_hide(conf);
GtkWidget *button=linphone_gtk_get_widget(call_view,"terminate_call");
GtkWidget *image=create_pixmap("stopcall-small.png");
button=linphone_gtk_get_widget(call_view,"terminate_call");
image=create_pixmap("stopcall-small.png");
gtk_button_set_label(GTK_BUTTON(button),_("Hang up"));
gtk_button_set_image(GTK_BUTTON(button),image);
gtk_widget_show(image);
@ -418,6 +423,7 @@ static void video_button_clicked(GtkWidget *button, LinphoneCall *call){
void linphone_gtk_update_video_button(LinphoneCall *call){
GtkWidget *call_view=(GtkWidget*)linphone_call_get_user_pointer(call);
GtkWidget *button;
GtkWidget *conf_frame;
const LinphoneCallParams *params=linphone_call_get_current_params(call);
gboolean has_video=linphone_call_params_video_enabled(params);
if (call_view==NULL) return;
@ -434,7 +440,7 @@ void linphone_gtk_update_video_button(LinphoneCall *call){
g_signal_connect(G_OBJECT(button),"clicked",(GCallback)video_button_clicked,call);
g_object_set_data(G_OBJECT(button),"signal_connected",GINT_TO_POINTER(1));
}
GtkWidget *conf_frame=(GtkWidget *)g_object_get_data(G_OBJECT(linphone_gtk_get_main_window()),"conf_frame");
conf_frame=(GtkWidget *)g_object_get_data(G_OBJECT(linphone_gtk_get_main_window()),"conf_frame");
gtk_widget_set_sensitive(button,linphone_call_get_state(call)==LinphoneCallStreamsRunning);
if(conf_frame!=NULL){
gtk_widget_set_sensitive(button,FALSE);
@ -753,10 +759,13 @@ static gboolean in_call_view_terminated(LinphoneCall *call){
void linphone_gtk_in_call_view_terminate(LinphoneCall *call, const char *error_msg){
GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call);
GtkWidget *status;
gboolean in_conf;
guint taskid;
if(callview==NULL) return;
GtkWidget *status=linphone_gtk_get_widget(callview,"in_call_status");
guint taskid=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(callview),"taskid"));
gboolean in_conf=linphone_call_params_get_local_conference_mode(linphone_call_get_current_params(call));
status=linphone_gtk_get_widget(callview,"in_call_status");
taskid=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(callview),"taskid"));
in_conf=linphone_call_params_get_local_conference_mode(linphone_call_get_current_params(call));
if (status==NULL) return;
if (error_msg==NULL)
@ -896,8 +905,9 @@ void linphone_gtk_record_call_toggled(GtkWidget *button){
GtkWidget *callview;
GtkWidget *label;
if (call){
const LinphoneCallParams *params;
callview=(GtkWidget*)linphone_call_get_user_pointer (call);
const LinphoneCallParams *params=linphone_call_get_current_params(call);
params=linphone_call_get_current_params(call);
filepath=linphone_call_params_get_record_file(params);
label=linphone_gtk_get_widget(callview,"record_status");
}else if (is_conf){

View file

@ -864,7 +864,7 @@ static gboolean launch_contact_provider_search(void *userdata)
if( ldap && strlen(predicate) >= 3 ){ // don't search too small predicates
unsigned int max_res_count = linphone_ldap_contact_provider_get_max_result(ldap);
LinphoneContactSearch* search;
if( previous_search &&
(strstr(predicate, previous_search) == predicate) && // last search contained results from this one
(prev_res_count != max_res_count) ){ // and we didn't reach the max result limit
@ -879,7 +879,7 @@ static gboolean launch_contact_provider_search(void *userdata)
gtk_object_set_data(GTK_OBJECT(uribar), "previous_search", ms_strdup(predicate));
ms_message("launch_contact_provider_search");
LinphoneContactSearch* search =linphone_contact_provider_begin_search(
search =linphone_contact_provider_begin_search(
linphone_contact_provider_cast(ldap_provider),
predicate, on_contact_provider_search_results, uribar
);
@ -940,6 +940,7 @@ static void linphone_gtk_update_call_buttons(LinphoneCall *call){
//bool_t stop_active=FALSE;
bool_t add_call=FALSE;
int call_list_size=ms_list_size(calls);
GtkWidget *conf_frame;
if (calls==NULL){
start_active=TRUE;
@ -962,7 +963,7 @@ static void linphone_gtk_update_call_buttons(LinphoneCall *call){
gtk_widget_set_visible(button,add_call);
//gtk_widget_set_sensitive(linphone_gtk_get_widget(mw,"terminate_call"),stop_active);
GtkWidget *conf_frame=(GtkWidget *)g_object_get_data(G_OBJECT(mw),"conf_frame");
conf_frame=(GtkWidget *)g_object_get_data(G_OBJECT(mw),"conf_frame");
if(conf_frame==NULL){
linphone_gtk_enable_transfer_button(lc,call_list_size>1);
linphone_gtk_enable_conference_button(lc,call_list_size>1);
@ -1000,7 +1001,7 @@ gchar *linphone_gtk_get_record_path(const LinphoneAddress *address, gboolean is_
break;
}
}
if (address){
id=linphone_address_get_username(address);
if (id==NULL) id=linphone_address_get_domain(address);
@ -1172,13 +1173,14 @@ static void linphone_gtk_new_subscriber_response(GtkWidget *dialog, guint respon
static void linphone_gtk_new_unknown_subscriber(LinphoneCore *lc, LinphoneFriend *lf, const char *url){
GtkWidget *dialog;
gchar *message;
if (linphone_gtk_get_ui_config_int("subscribe_deny_all",0)){
linphone_core_reject_subscriber(linphone_gtk_get_core(),lf);
return;
}
gchar *message=g_strdup_printf(_("%s would like to add you to his contact list.\nWould you allow him to see your presence status or add him to your contact list ?\nIf you answer no, this person will be temporarily blacklisted."),url);
message=g_strdup_printf(_("%s would like to add you to his contact list.\nWould you allow him to see your presence status or add him to your contact list ?\nIf you answer no, this person will be temporarily blacklisted."),url);
dialog = gtk_message_dialog_new (
GTK_WINDOW(linphone_gtk_get_main_window()),
GTK_DIALOG_DESTROY_WITH_PARENT,
@ -1540,7 +1542,7 @@ static void update_registration_status(LinphoneProxyConfig *cfg, LinphoneRegistr
}while(gtk_tree_model_iter_next(model,&iter));
}
if (!found) {
g_warning("Could not find proxy config in combo box of identities.");
/*ignored, this is a notification for a removed proxy config.*/
return;
}
switch (rs){
@ -2001,10 +2003,11 @@ void linphone_gtk_keypad_key_released(GtkWidget *w, GdkEvent *event, gpointer us
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");
GtkWidget *keypad;
if(k!=NULL){
gtk_widget_destroy(k);
}
GtkWidget *keypad=linphone_gtk_create_window("keypad");
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);

View file

@ -179,6 +179,7 @@ void linphone_gtk_ldap_save(GtkWidget *button)
GtkEntry* entry;
GtkToggleButton* toggle;
GtkSpinButton* spin;
GtkComboBox* cbox;
ms_message("SAVE LDAP");
@ -204,7 +205,7 @@ void linphone_gtk_ldap_save(GtkWidget *button)
linphone_dictionary_set_string(dict, "sasl_realm", gtk_entry_get_text(entry));
GtkComboBox* cbox = GTK_COMBO_BOX(linphone_gtk_get_widget(ldap_widget,"ldap_auth_method"));
cbox = GTK_COMBO_BOX(linphone_gtk_get_widget(ldap_widget,"ldap_auth_method"));
linphone_dictionary_set_string(dict, "auth_method", gtk_combo_box_get_active_text(cbox));
entry = GTK_ENTRY(linphone_gtk_get_widget(ldap_widget,"ldap_base_object"));
@ -245,10 +246,11 @@ void linphone_gtk_ldap_save(GtkWidget *button)
}
void linphone_gtk_fill_video_sizes(GtkWidget *combo){
const MSVideoSizeDef *def=linphone_core_get_supported_video_sizes(linphone_gtk_get_core());;
int i,active=0;
int i;
int active=0;
char vsize_def[256];
MSVideoSize cur=linphone_core_get_preferred_video_size(linphone_gtk_get_core());
const MSVideoSizeDef *def=linphone_core_get_supported_video_sizes(linphone_gtk_get_core());;
/* glade creates a combo box without list model and text renderer,
unless we fill it with a dummy text.
This dummy text needs to be removed first*/
@ -828,8 +830,11 @@ void linphone_gtk_show_sip_accounts(GtkWidget *w){
static void linphone_gtk_proxy_closed(GtkWidget *w){
LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)g_object_get_data(G_OBJECT(w),"config");
gboolean was_editing=! GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"is_new"));
if (cfg){
linphone_proxy_config_done(cfg);
if (was_editing){
linphone_proxy_config_done(cfg);
}else linphone_proxy_config_destroy(cfg);
}
}
@ -907,7 +912,15 @@ void linphone_gtk_proxy_address_changed(GtkEditable *editable){
void linphone_gtk_show_proxy_config(GtkWidget *pb, LinphoneProxyConfig *cfg){
GtkWidget *w=linphone_gtk_create_window("sip_account");
const char *tmp;
if (cfg){
gboolean is_new=FALSE;
if (!cfg) {
cfg=linphone_core_create_proxy_config(linphone_gtk_get_core());
is_new=TRUE;
g_object_set_data(G_OBJECT(w),"is_new",GINT_TO_POINTER(TRUE));
}
if (!is_new){
linphone_proxy_config_edit(cfg);
gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(w,"identity")),
linphone_proxy_config_get_identity(cfg));
@ -916,17 +929,19 @@ void linphone_gtk_show_proxy_config(GtkWidget *pb, LinphoneProxyConfig *cfg){
if (tmp) gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(w,"route")),tmp);
tmp=linphone_proxy_config_get_contact_parameters(cfg);
if (tmp) gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(w,"params")),tmp);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(w,"regperiod")),
linphone_proxy_config_get_expires(cfg));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"register")),
linphone_proxy_config_register_enabled(cfg));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"publish")),
linphone_proxy_config_publish_enabled(cfg));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"avpf")),
linphone_proxy_config_avpf_enabled(cfg));
gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(w,"avpf_rr_interval")),
linphone_proxy_config_get_avpf_rr_interval(cfg));
}
gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(w,"regperiod")),
linphone_proxy_config_get_expires(cfg));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"register")),
linphone_proxy_config_register_enabled(cfg));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"publish")),
linphone_proxy_config_publish_enabled(cfg));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"avpf")),
linphone_proxy_config_avpf_enabled(cfg));
gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(w,"avpf_rr_interval")),
linphone_proxy_config_get_avpf_rr_interval(cfg));
g_object_set_data(G_OBJECT(w),"config",(gpointer)cfg);
g_object_set_data(G_OBJECT(w),"parameters",(gpointer)pb);
g_object_weak_ref(G_OBJECT(w),(GWeakNotify)linphone_gtk_proxy_closed,w);
@ -944,12 +959,8 @@ void linphone_gtk_proxy_ok(GtkButton *button){
LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)g_object_get_data(G_OBJECT(w),"config");
int index=gtk_combo_box_get_active(GTK_COMBO_BOX(linphone_gtk_get_widget(w,"transport")));
LinphoneTransportType tport=(LinphoneTransportType)index;
gboolean was_editing=TRUE;
gboolean was_editing=! GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"is_new"));
if (!cfg){
was_editing=FALSE;
cfg=linphone_proxy_config_new();
}
linphone_proxy_config_set_identity(cfg,
gtk_entry_get_text(GTK_ENTRY(linphone_gtk_get_widget(w,"identity"))));
if (linphone_proxy_config_set_server_addr(cfg,
@ -1098,14 +1109,14 @@ static void linphone_gtk_fill_langs(GtkWidget *pb){
const char *all_langs="C " LINPHONE_ALL_LANGS;
const char *name;
int i=0,index=0;
int cur_lang_index=-1;
char text[256]={0};
const char *cur_lang;
#if defined(WIN32) || defined(__APPLE__)
cur_lang=getenv("LANG");
#else
cur_lang=getenv("LANGUAGE");
#endif
int cur_lang_index=-1;
char text[256]={0};
if (cur_lang==NULL) cur_lang="C";
/* glade creates a combo box without list model and text renderer,
unless we fill it with a dummy text.
@ -1581,7 +1592,7 @@ void linphone_gtk_edit_tunnel(GtkButton *button){
if (port==0) port=443;
gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(w,"port")), port);
if (linphone_tunnel_enabled(tunnel)){
if (linphone_tunnel_get_mode(tunnel)){
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"radio_enable")),1);
} else{
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"radio_disable")),1);
@ -1625,7 +1636,7 @@ void linphone_gtk_tunnel_ok(GtkButton *button){
linphone_tunnel_config_set_host(config, host);
linphone_tunnel_config_set_port(config, port);
linphone_tunnel_add_server(tunnel, config);
linphone_tunnel_enable(tunnel,enabled);
linphone_tunnel_set_mode(tunnel, (enabled ? LinphoneTunnelModeEnable : LinphoneTunnelModeDisable));
linphone_tunnel_set_http_proxy(tunnel,http_host,http_port,username,password);
gtk_widget_destroy(w);

View file

@ -44,7 +44,7 @@ static GtkWidget *create_setup_signin_choice(){
GtkWidget *t2=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(t1),_("I have already a linphone.org account and I just want to use it"));
GtkWidget *t3=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(t1),_("I have already a sip account and I just want to use it"));
GtkWidget *t4=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(t1),_("I want to specify a remote configuration URI"));
gtk_box_pack_start (GTK_BOX (vbox), t1, TRUE, TRUE, 2);
gtk_box_pack_start (GTK_BOX (vbox), t2, TRUE, TRUE, 2);
gtk_box_pack_start (GTK_BOX (vbox), t3, TRUE, TRUE, 2);
@ -89,14 +89,20 @@ static GtkWidget *create_linphone_account_informations_page() {
GtkWidget *label=gtk_label_new(_("Enter your linphone.org username"));
GdkColor color;
GtkWidget *labelEmpty;
GtkWidget *labelUsername;
GtkWidget *entryUsername;
GtkWidget *labelPassword;
GtkWidget *entryPassword;
gdk_color_parse ("red", &color);
GtkWidget *labelEmpty=gtk_label_new(NULL);
labelEmpty=gtk_label_new(NULL);
gtk_widget_modify_fg(labelEmpty, GTK_STATE_NORMAL, &color);
GtkWidget *labelUsername=gtk_label_new(_("Username:"));
GtkWidget *entryUsername=gtk_entry_new();
GtkWidget *labelPassword=gtk_label_new(_("Password:"));
GtkWidget *entryPassword=gtk_entry_new();
labelUsername=gtk_label_new(_("Username:"));
entryUsername=gtk_entry_new();
labelPassword=gtk_label_new(_("Password:"));
entryPassword=gtk_entry_new();
gtk_entry_set_visibility(GTK_ENTRY(entryPassword), FALSE);
gtk_table_attach_defaults(GTK_TABLE(vbox), label, 0, 2, 0, 1);
@ -118,19 +124,28 @@ static GtkWidget *create_account_informations_page() {
GtkWidget *label=gtk_label_new(_("Enter your account informations"));
GdkColor color;
GtkWidget *labelEmpty;
GtkWidget *labelUsername;
GtkWidget *labelPassword;
GtkWidget *entryPassword;
GtkWidget *labelDomain;
GtkWidget *labelProxy;
GtkWidget *entryUsername;
GtkWidget *entryDomain;
GtkWidget *entryRoute;
gdk_color_parse ("red", &color);
GtkWidget *labelEmpty=gtk_label_new(NULL);
labelEmpty=gtk_label_new(NULL);
gtk_widget_modify_fg(labelEmpty, GTK_STATE_NORMAL, &color);
GtkWidget *labelUsername=gtk_label_new(_("Username*"));
GtkWidget *labelPassword=gtk_label_new(_("Password*"));
GtkWidget *entryPassword=gtk_entry_new();
labelUsername=gtk_label_new(_("Username*"));
labelPassword=gtk_label_new(_("Password*"));
entryPassword=gtk_entry_new();
gtk_entry_set_visibility(GTK_ENTRY(entryPassword), FALSE);
GtkWidget *labelDomain=gtk_label_new(_("Domain*"));
GtkWidget *labelProxy=gtk_label_new(_("Proxy"));
GtkWidget *entryUsername=gtk_entry_new();
GtkWidget *entryDomain=gtk_entry_new();
GtkWidget *entryRoute=gtk_entry_new();
labelDomain=gtk_label_new(_("Domain*"));
labelProxy=gtk_label_new(_("Proxy"));
entryUsername=gtk_entry_new();
entryDomain=gtk_entry_new();
entryRoute=gtk_entry_new();
gtk_table_attach_defaults(GTK_TABLE(vbox), label, 0, 2, 0, 1);
gtk_table_attach_defaults(GTK_TABLE(vbox), labelUsername, 0, 1, 1, 2);
@ -309,19 +324,25 @@ static GtkWidget *create_account_information_page() {
GtkWidget *labelPassword2=gtk_label_new(_("Confirm your password: (*)"));
GtkWidget *entryUsername=gtk_entry_new();
GtkWidget *entryPassword=gtk_entry_new();
gtk_entry_set_visibility(GTK_ENTRY(entryPassword), FALSE);
GtkWidget *entryEmail=gtk_entry_new();
GtkWidget *entryPassword2=gtk_entry_new();
gtk_entry_set_visibility(GTK_ENTRY(entryPassword2), FALSE);
GtkWidget *checkNewsletter=gtk_check_button_new_with_label("Keep me informed with linphone updates");
GtkWidget *entryEmail;
GtkWidget *entryPassword2;
GtkWidget *checkNewsletter;
GtkWidget *labelError;
GtkWidget *passwordVbox1;
GtkWidget *passwordVbox2;
GdkColor color;
gtk_entry_set_visibility(GTK_ENTRY(entryPassword), FALSE);
entryEmail=gtk_entry_new();
entryPassword2=gtk_entry_new();
gtk_entry_set_visibility(GTK_ENTRY(entryPassword2), FALSE);
checkNewsletter=gtk_check_button_new_with_label(_("Keep me informed with linphone updates"));
gdk_color_parse ("red", &color);
GtkWidget *labelError=gtk_label_new(NULL);
labelError=gtk_label_new(NULL);
gtk_widget_modify_fg(labelError, GTK_STATE_NORMAL, &color);
GtkWidget *passwordVbox1=gtk_vbox_new(FALSE,2);
GtkWidget *passwordVbox2=gtk_vbox_new(FALSE,2);
passwordVbox1=gtk_vbox_new(FALSE,2);
passwordVbox2=gtk_vbox_new(FALSE,2);
gtk_box_pack_start (GTK_BOX (passwordVbox1), labelPassword, TRUE, FALSE, 2);
gtk_box_pack_start (GTK_BOX (passwordVbox1), labelPassword2, TRUE, FALSE, 2);
gtk_box_pack_start (GTK_BOX (passwordVbox2), entryPassword, TRUE, FALSE, 2);
@ -414,6 +435,8 @@ static void linphone_gtk_assistant_prepare(GtkWidget *assistant, GtkWidget *page
if (pagenum == 5) {
gtk_assistant_commit(GTK_ASSISTANT(assistant));
} else if (pagenum == gtk_assistant_get_n_pages(GTK_ASSISTANT(assistant)) - 1) {
LinphoneAddress *identity;
LinphoneAuthInfo *info;
// Saving the account and making it default
LinphoneAccountCreator *creator=linphone_gtk_assistant_get_creator(assistant);
LinphoneProxyConfig *cfg=linphone_proxy_config_new();
@ -424,30 +447,33 @@ static void linphone_gtk_assistant_prepare(GtkWidget *assistant, GtkWidget *page
linphone_proxy_config_enable_publish(cfg, FALSE);
linphone_proxy_config_enable_register(cfg, TRUE);
LinphoneAddress *identity = linphone_address_new(creator->username);
LinphoneAuthInfo *info=linphone_auth_info_new(linphone_address_get_username(identity), NULL, creator->password, NULL, NULL, linphone_address_get_domain(identity));
identity = linphone_address_new(creator->username);
info=linphone_auth_info_new(linphone_address_get_username(identity), NULL, creator->password, NULL, NULL, linphone_address_get_domain(identity));
linphone_core_add_auth_info(linphone_gtk_get_core(),info);
linphone_address_destroy(identity);
// If account created on sip.linphone.org, we configure linphone to use TLS by default
if (strcmp(creator->domain, "sip:sip.linphone.org") == 0 && linphone_core_sip_transport_supported(linphone_gtk_get_core(),LinphoneTransportTls)) {
LinphoneAddress *addr=linphone_address_new(creator->domain);
char *tmp;
linphone_address_set_transport(addr, LinphoneTransportTls);
tmp=linphone_address_as_string(addr);
linphone_proxy_config_set_server_addr(cfg,tmp);
linphone_proxy_config_set_route(cfg,tmp);
ms_free(tmp);
linphone_address_destroy(addr);
if (strcmp(creator->domain, "sip:sip.linphone.org") == 0 ){
linphone_proxy_config_enable_avpf(cfg,TRUE);
// If account created on sip.linphone.org, we configure linphone to use TLS by default
if (linphone_core_sip_transport_supported(linphone_gtk_get_core(),LinphoneTransportTls)) {
LinphoneAddress *addr=linphone_address_new(creator->domain);
char *tmp;
linphone_address_set_transport(addr, LinphoneTransportTls);
tmp=linphone_address_as_string(addr);
linphone_proxy_config_set_server_addr(cfg,tmp);
linphone_proxy_config_set_route(cfg,tmp);
ms_free(tmp);
linphone_address_destroy(addr);
}
}
if (linphone_core_add_proxy_config(linphone_gtk_get_core(),cfg)==-1)
return;
linphone_core_set_default_proxy(linphone_gtk_get_core(),cfg);
linphone_gtk_load_identities();
}
}
@ -486,9 +512,9 @@ static int linphone_gtk_assistant_forward(int curpage, gpointer data){
else if (curpage == 2) { // Account's informations entered
LinphoneAccountCreator *c=linphone_gtk_assistant_get_creator(w);
gchar identity[128];
gchar proxy[128];
g_snprintf(identity, sizeof(identity), "sip:%s@%s", gtk_entry_get_text(GTK_ENTRY(g_object_get_data(G_OBJECT(box),"username"))), gtk_entry_get_text(GTK_ENTRY(g_object_get_data(G_OBJECT(box),"domain"))));
gchar proxy[128];
g_snprintf(proxy, sizeof(proxy), "sip:%s", gtk_entry_get_text(GTK_ENTRY(g_object_get_data(G_OBJECT(box),"domain"))));
linphone_account_creator_set_username(c, identity);
@ -557,25 +583,35 @@ void linphone_gtk_close_assistant(void){
}
void linphone_gtk_show_assistant(void){
GtkWidget *w;
GtkWidget *p1;
GtkWidget *p2;
GtkWidget *p31;
GtkWidget *p32;
GtkWidget *p33;
//GtkWidget *confirm;
GtkWidget *validate;
GtkWidget *error;
GtkWidget *end;
if(the_assistant!=NULL)
return;
GtkWidget *w=the_assistant=gtk_assistant_new();
w=the_assistant=gtk_assistant_new();
gtk_window_set_resizable (GTK_WINDOW(w), FALSE);
gtk_window_set_title(GTK_WINDOW(w),_("SIP account configuration assistant"));
ok = create_pixbuf(linphone_gtk_get_ui_config("ok","ok.png"));
notok = create_pixbuf(linphone_gtk_get_ui_config("notok","notok.png"));
GtkWidget *p1=create_intro();
GtkWidget *p2=create_setup_signin_choice();
GtkWidget *p31=create_account_informations_page();
GtkWidget *p32=create_linphone_account_informations_page();
GtkWidget *p33=create_account_information_page();
//GtkWidget *confirm=create_confirmation_page();
GtkWidget *validate=wait_for_activation();
GtkWidget *error=create_error_page();
GtkWidget *end=create_finish_page();
p1=create_intro();
p2=create_setup_signin_choice();
p31=create_account_informations_page();
p32=create_linphone_account_informations_page();
p33=create_account_information_page();
//confirm=create_confirmation_page();
validate=wait_for_activation();
error=create_error_page();
end=create_finish_page();
linphone_gtk_assistant_init(w);
gtk_assistant_append_page(GTK_ASSISTANT(w),p1);
gtk_assistant_set_page_type(GTK_ASSISTANT(w),p1,GTK_ASSISTANT_PAGE_INTRO);

View file

@ -58,7 +58,7 @@ static gboolean execute_wakeup(char *buf){
static void * server_pipe_thread(void *pointer){
ortp_pipe_t child;
do{
child=ortp_server_pipe_accept_client(server_pipe);
if (server_pipe_running && child!=(ortp_pipe_t)-1){
@ -87,8 +87,9 @@ static void linphone_gtk_init_pipe(const char *name){
}
bool_t linphone_gtk_init_instance(const char *app_name, int option, const char *addr_to_call){
ortp_pipe_t p;
pipe_name=make_name(app_name);
ortp_pipe_t p=ortp_client_pipe_connect(pipe_name);
p=ortp_client_pipe_connect(pipe_name);
if (p!=(ortp_pipe_t)-1){
uint8_t buf[256]={0};
g_message("There is already a running instance.");

View file

@ -92,17 +92,17 @@ create_pixbuf_animation(const gchar *filename)
gchar *pathname = NULL;
GdkPixbufAnimation *pixbuf;
GError *error = NULL;
if (!filename || !filename[0])
return NULL;
pathname = find_pixmap_file (filename);
if (!pathname){
g_warning (_("Couldn't find pixmap file: %s"), filename);
return NULL;
}
pixbuf = gdk_pixbuf_animation_new_from_file (pathname, &error);
if (!pixbuf){
fprintf (stderr, "Failed to load pixbuf file: %s: %s\n",
@ -156,6 +156,11 @@ const char *linphone_gtk_get_lang(const char *config_file){
void linphone_gtk_set_lang(const char *code){
LpConfig *cfg=linphone_core_get_config(linphone_gtk_get_core());
const char *curlang;
#ifdef WIN32
char tmp[128];
#endif
#if defined(WIN32) || defined(__APPLE__)
curlang=getenv("LANG");
#else
@ -167,12 +172,11 @@ void linphone_gtk_set_lang(const char *code){
}
lp_config_set_string(cfg,"GtkUi","lang",code);
#ifdef WIN32
char tmp[128];
snprintf(tmp,sizeof(tmp),"LANG=%s",code);
_putenv(tmp);
#elif __APPLE__
setenv("LANG",code,1);
#else
#else
setenv("LANGUAGE",code,1);
#endif
}

View file

@ -72,7 +72,9 @@ typedef enum {
#define SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED 0x01
#define SAL_MEDIA_DESCRIPTION_CODEC_CHANGED 0x02
#define SAL_MEDIA_DESCRIPTION_CRYPTO_CHANGED 0x04
#define SAL_MEDIA_DESCRIPTION_CHANGED (SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED | SAL_MEDIA_DESCRIPTION_CODEC_CHANGED | SAL_MEDIA_DESCRIPTION_CRYPTO_CHANGED)
#define SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED 0x08
#define SAL_MEDIA_DESCRIPTION_CHANGED (SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED | SAL_MEDIA_DESCRIPTION_CODEC_CHANGED |\
SAL_MEDIA_DESCRIPTION_CRYPTO_CHANGED |SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED)
const char* sal_transport_to_string(SalTransport transport);
SalTransport sal_transport_parse(const char*);
@ -285,6 +287,7 @@ typedef struct SalOpBase{
SalMediaDescription *remote_media;
void *user_pointer;
const char* call_id;
char* realm;
SalAddress* service_route; /*as defined by rfc3608, might be a list*/
SalCustomHeader *sent_custom_headers;
SalCustomHeader *recv_custom_headers;
@ -412,7 +415,7 @@ typedef void (*SalOnCallReceived)(SalOp *op);
typedef void (*SalOnCallRinging)(SalOp *op);
typedef void (*SalOnCallAccepted)(SalOp *op);
typedef void (*SalOnCallAck)(SalOp *op);
typedef void (*SalOnCallUpdating)(SalOp *op);/*< Called when a reINVITE/UPDATE is received*/
typedef void (*SalOnCallUpdating)(SalOp *op, bool_t is_update);/*< Called when a reINVITE/UPDATE is received*/
typedef void (*SalOnCallTerminated)(SalOp *op, const char *from);
typedef void (*SalOnCallFailure)(SalOp *op);
typedef void (*SalOnCallReleased)(SalOp *salop);
@ -516,6 +519,10 @@ int sal_get_listening_port(Sal *ctx, SalTransport tr);
int sal_unlisten_ports(Sal *ctx);
int sal_transport_available(Sal *ctx, SalTransport t);
void sal_set_dscp(Sal *ctx, int dscp);
void sal_set_supported_tags(Sal *ctx, const char* tags);
void sal_add_supported_tag(Sal *ctx, const char* tag);
void sal_remove_supported_tag(Sal *ctx, const char* tag);
const char *sal_get_supported_tags(Sal *ctx);
int sal_reset_transports(Sal *ctx);
ortp_socket_t sal_get_socket(Sal *ctx);
void sal_set_user_agent(Sal *ctx, const char *user_agent);
@ -560,6 +567,7 @@ void sal_op_set_contact_address(SalOp *op, const SalAddress* address);
void sal_op_set_route(SalOp *op, const char *route);
void sal_op_set_route_address(SalOp *op, const SalAddress* address);
void sal_op_add_route_address(SalOp *op, const SalAddress* address);
void sal_op_set_realm(SalOp *op, const char *realm);
void sal_op_set_from(SalOp *op, const char *from);
void sal_op_set_from_address(SalOp *op, const SalAddress *from);
void sal_op_set_to(SalOp *op, const char *to);
@ -613,7 +621,7 @@ int sal_call_notify_ringing(SalOp *h, bool_t early_media);
/*accept an incoming call or, during a call accept a reINVITE*/
int sal_call_accept(SalOp*h);
int sal_call_decline(SalOp *h, SalReason reason, const char *redirection /*optional*/);
int sal_call_update(SalOp *h, const char *subject);
int sal_call_update(SalOp *h, const char *subject, bool_t no_user_consent);
SalMediaDescription * sal_call_get_remote_media_description(SalOp *h);
SalMediaDescription * sal_call_get_final_media_description(SalOp *h);
int sal_call_refer(SalOp *h, const char *refer_to);
@ -749,5 +757,5 @@ int sal_body_has_type(const SalBody *body, const char *type, const char *subtype
int sal_lines_get_value(const char *data, const char *key, char *value, size_t value_size);
belle_sip_stack_t *sal_get_belle_sip_stack(Sal *sal);
char* sal_op_get_public_uri(SalOp *sal);
#endif

View file

@ -323,4 +323,14 @@ public interface LinphoneCall {
*/
ErrorInfo getErrorInfo();
/**
* attached a user data to a call
**/
void setUserData(Object obj);
/**
* Returns user data from a call. return null if any
* @return an Object.
*/
Object getUserData();
}

View file

@ -76,6 +76,9 @@ public interface LinphoneCallParams {
/**
* Set a path to file where the call will be recorded.
* Actual start of the recording is controlled by LinphoneCall.startRecording().
* @param path Path to the file where the call will be recorded. If it is a WAV
* file, only audio will be written whereas if it is a MKV file, audio and video
* will be written.
**/
void setRecordFile(String path);

View file

@ -14,21 +14,25 @@ public interface LinphoneChatMessage {
private final String mStringValue;
/**
* Idle
* Initial state
*/
public final static State Idle = new State(0,"Idle");
/**
* Incoming call received.
* Delivery in progress
*/
public final static State InProgress = new State(1,"InProgress");
/**
* Outgoing call initialiazed.
* Message succesffully delivered an acknoleged by remote end point
*/
public final static State Delivered = new State(2,"Delivered");
/**
* Outgoing call in progress.
* Message was not delivered
*/
public final static State NotDelivered = new State(3,"NotDelivered");
/**
* Message was received(and acknowledged) but cannot get file from server
*/
public final static State FileTransferError = new State(4,"FileTransferError");
private State(int value,String stringValue) {
mValue = value;
@ -74,6 +78,12 @@ public interface LinphoneChatMessage {
*/
LinphoneAddress getFrom();
/**
* Get destination address of the LinphoneChatMessage.
* @return the LinphoneAddress in the To field of the message.
*/
LinphoneAddress getTo();
/**
* Linphone message can carry external body as defined by rfc2017
* @param message #LinphoneChatMessage
@ -147,4 +157,26 @@ public interface LinphoneChatMessage {
* @return an ErrorInfo.
*/
ErrorInfo getErrorInfo();
/**
* Start the download of the file bundled in the message
*/
void startFileDownload(LinphoneChatMessage.StateListener listener);
/**
* Get the file_transfer_information (used by call backs to recover informations during a rcs file transfer)
* @return a pointer to the LinphoneContent structure or NULL if not present.
*/
LinphoneContent getFileTransferInformation();
/**
* Sets data in the chat message
* @param data to store in the message
*/
void setAppData(String data);
/**
* @return the data stored in the chat message if any, else null
*/
String getAppData();
}

View file

@ -21,8 +21,8 @@ package org.linphone.core;
import org.linphone.core.LinphoneChatMessage.State;
/**
*
* A chat room is the place where text messages are exchanged.
*
* A chat room is the place where text messages are exchanged.
Can be created by linphone_core_create_chat_room().
*
*/
@ -33,17 +33,19 @@ public interface LinphoneChatRoom {
* @return LinphoneAddress peer address
*/
LinphoneAddress getPeerAddress();
/**
* send a message to peer member of this chat room.
* @param message to be sent
*/
void sendMessage(String message);
/**
* Send a message to peer member of this chat room.
* @param chat message
*/
void sendMessage(LinphoneChatMessage message, LinphoneChatMessage.StateListener listener);
/**
* Create a LinphoneChatMessage
* @param chatRoom chat room associated to the message
@ -51,31 +53,45 @@ public interface LinphoneChatRoom {
* @return LinphoneChatMessage object
*/
LinphoneChatMessage createLinphoneChatMessage(String message);
/**
* Returns the chat history associated with the peer address associated with this chat room
* @return an array of LinphoneChatMessage
*/
LinphoneChatMessage[] getHistory();
/**
* Returns the chat history associated with the peer address associated with this chat room
* @param limit the maximum number of messages to fetch
* @return an array of LinphoneChatMessage
*/
LinphoneChatMessage[] getHistory(int limit);
/**
* Returns the chat history associated with the peer address associated with this chat room for the given range, sorted from oldest to most recent
* @param begin the first (most recent) message to retrieve. Newest message has index 0. If negative, use value 0 instead.
* @param end the last (oldest) message to retrieve. Oldest message has value "history size" - 1 (equivalent to -1). If negative or lower than begin value, value is given, use -1.
* @return an array of LinphoneChatMessage, empty if nothing has been found
*/
LinphoneChatMessage[] getHistoryRange(int begin, int end);
/**
* Destroys a LinphoneChatRoom.
*/
void destroy();
/**
* Returns the amount of unread messages associated with the peer of this chatRoom.
* @return the amount of unread messages
*/
int getUnreadMessagesCount();
/**
* Returns the amount of messages associated with the peer of this chatRoom.
* @return the amount of messages in the conversation
*/
int getHistorySize();
/**
* Deletes all the messages associated with the peer of this chat room
*/
@ -91,32 +107,46 @@ public interface LinphoneChatRoom {
* @return true if the remote is currently composing a message, false otherwise.
*/
boolean isRemoteComposing();
/**
* Marks all the messages in this conversation as read
*/
void markAsRead();
/**
* Deletes a message
* @param message the message to delete
*/
void deleteMessage(LinphoneChatMessage message);
/**
* Update the value stored in the database for the external_body_url field
* @param message to update
*/
void updateUrl(LinphoneChatMessage message);
/**
* Create a LinphoneChatMessage
* @return LinphoneChatMessage object
*/
LinphoneChatMessage createLinphoneChatMessage(String message, String url, State state, long timestamp, boolean isRead, boolean isIncoming);
/**
* Returns a back pointer to the core managing the chat room.
* @return the LinphoneCore
*/
LinphoneCore getCore();
/**
* Create a message attached to a dedicated chat room with a particular content.
* @param content LinphoneContent initial content.
* @return a new LinphoneChatMessage
*/
LinphoneChatMessage createFileTransferMessage(LinphoneContent content);
/**
* Cancel an ongoing file transfer attached to this message (upload or download)
* @param message
*/
void cancelFileTransfer(LinphoneChatMessage message);
}

View file

@ -31,10 +31,21 @@ public interface LinphoneContent {
**/
byte [] getData();
/**
* Get the data size.
* @return the data size.
* Get the expected data size.
* @return the expected data size
*/
int getSize();
int getExpectedSize();
/**
* Sets the expected data size
*/
void setExpectedSize(int size);
/**
* Return the size of the data field
* @return the size of the data field
*/
int getRealSize();
/**
* Set the content type, for example "application"
@ -59,4 +70,8 @@ public interface LinphoneContent {
* Set the data, as a byte buffer.
**/
void setData(byte data[]);
void setName(String name);
String getName();
}

File diff suppressed because it is too large Load diff

View file

@ -104,12 +104,10 @@ abstract public class LinphoneCoreFactory {
abstract public LinphoneAddress createLinphoneAddress(String address) throws LinphoneCoreException;
abstract public LpConfig createLpConfig(String file);
abstract public LinphoneProxyConfig createProxyConfig(String identity, String proxy,String route,boolean enableRegister) throws LinphoneCoreException;
/**
* Enable verbose traces
* @param enable
* @param tag
* @param enable true to enable debug mode, false to disable it
* @param tag Tag which prefixes each log message.
*/
abstract public void setDebugMode(boolean enable, String tag);

View file

@ -18,6 +18,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.linphone.core;
import java.nio.ByteBuffer;
import org.linphone.core.LinphoneCore.RemoteProvisioningState;
@ -188,6 +190,35 @@ public interface LinphoneCoreListener {
/** @Deprecated Callback to display a warning to the user
* @return */
void displayWarning(LinphoneCore lc,String message);
/**
* Callback to be notified about the transfer progress.
* @param lc the LinphoneCore
* @param message the LinphoneChatMessage
* @param content the LinphoneContent
* @param progress percentage of the transfer done
*/
void fileTransferProgressIndication(LinphoneCore lc, LinphoneChatMessage message, LinphoneContent content, int progress);
/**
* Callback to be notified when new data has been received
* @param lc the LinphoneCore
* @param message the LinphoneChatMessage
* @param content the LinphoneContent
* @param buffer
* @param size
*/
void fileTransferRecv(LinphoneCore lc, LinphoneChatMessage message, LinphoneContent content, byte[] buffer, int size);
/**
* Callback to be notified when new data needs to be sent
* @param lc the LinphoneCore
* @param message the LinphoneChatMessage
* @param content the LinphoneContent
* @param buffer
* @param size
* @return the number of bytes written into buffer
*/
int fileTransferSend(LinphoneCore lc, LinphoneChatMessage message, LinphoneContent content, ByteBuffer buffer, int size);
}

View file

@ -18,19 +18,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.linphone.core;
/**
* The LinphoneProxyConfig object represents a proxy configuration to be used by the LinphoneCore object. Its fields must not be used directly in favour of the accessors methods.
* The LinphoneProxyConfig object represents a proxy configuration to be used by the LinphoneCore object. Its fields must not be used directly in favour of the accessors methods.
* Once created and filled properly the LinphoneProxyConfig can be given to LinphoneCore with {@link LinphoneCore#addProxyConfig(LinphoneProxyConfig)}. This will automatically triggers the registration, if enabled.
*<br>The proxy configuration are persistent to restarts because they are saved in the configuration file. As a consequence, after {@link LinphoneCoreFactory#createLinphoneCore(LinphoneCoreListener, String, String, Object)} there might already be a default proxy that can be examined with {@link LinphoneCore#getDefaultProxyConfig()} .
*
*/
public interface LinphoneProxyConfig {
public void setIsDeleted(boolean b);
public boolean getIsDeleted();
/**
*Starts editing a proxy configuration.
*Because proxy configuration must be consistent, applications MUST call {@link #edit()} before doing any attempts to modify proxy configuration (such as identity, proxy address and so on).
*Because proxy configuration must be consistent, applications MUST call {@link #edit()} before doing any attempts to modify proxy configuration (such as identity, proxy address and so on).
*Once the modifications are done, then the application must call {@link #done()} to commit the changes.
*/
public LinphoneProxyConfig edit();
@ -61,20 +58,20 @@ public interface LinphoneProxyConfig {
public void setProxy(String proxyUri) throws LinphoneCoreException;
/**
* get the proxy's SIP address.
*
*
*/
public String getProxy();
/**
* Enable register for this proxy config.
* Register message is issued after call to {@link #done()}
* @param value
*/
*/
public LinphoneProxyConfig enableRegister(boolean value);
/**
* @return true if registration to the proxy is enabled.
*/
public boolean registerEnabled();
/**
* normalize a human readable phone number into a basic string. 888-444-222 becomes 888444222
* @param number
@ -86,32 +83,32 @@ public interface LinphoneProxyConfig {
* @param prefix
*/
public void setDialPrefix(String prefix);
/**
* Returns the automatically added international prefix to e164 phone numbers
*/
public String getDialPrefix();
/**
* * Sets whether liblinphone should replace "+" by "00" in dialed numbers (passed to
* {@link LinphoneCore#invite(String)}).
* @param value default value is false
*/
public void setDialEscapePlus(boolean value);
/**
* Whether liblinphone should replace "+" by "00" in dialed numbers (passed to
* {@link LinphoneCore#invite(String)}).
*/
public boolean getDialEscapePlus();
/**
* get domain host name or ip
* @return may be null
*/
public String getDomain();
/**
*
*
* @return a boolean indicating that the user is successfully registered on the proxy.
*/
public boolean isRegistered();
@ -122,7 +119,7 @@ public interface LinphoneProxyConfig {
*/
public void setRoute(String routeUri) throws LinphoneCoreException;
/**
*
*
* @return the route set for this proxy configuration.
*/
public String getRoute();
@ -138,95 +135,108 @@ public interface LinphoneProxyConfig {
* returns publish state for this proxy config (see {@link #enablePublish(boolean)} )
*/
public boolean publishEnabled();
LinphoneCore.RegistrationState getState();
/**
* Sets the registration expiration time.
* @param delay expiration time in seconds
*/
void setExpires(int delay);
/**
* Gets the registration expiration time.
* @return delay expiration time in seconds.
*/
int getExpires();
/**
* Set the privacy for all calls or chat sessions using the identity exposed by this LinphoneProxyConfig
* @param privacy_mask a or'd int of values defined in interface {@link org.linphone.core.Privacy}
*/
void setPrivacy(int privacy_mask);
/**
* Get the privacy mask requested for this proxy config.
* @return the privacy mask as defined in interface {@link org.linphone.core.Privacy}
*/
int getPrivacy();
/**
* Indicates whether AVPF/SAVPF must be used for calls using this proxy config.
* @param enable True to enable AVPF/SAVF, false to disable it.
*/
void enableAvpf(boolean enable);
/**
* Whether AVPF is used for calls through this proxy.
* @return
* @return
*/
boolean avpfEnabled();
/**
* Set the interval between regular RTCP reports when using AVPF/SAVPF.
* @param interval The interval in seconds (between 0 and 5 seconds).
*/
void setAvpfRRInterval(int interval);
/**
* Get the interval between regular RTCP reports when using AVPF/SAVPF.
* @return The interval in seconds.
*/
int getAvpfRRInterval();
/**
* Indicates whether quality reporting must be used for calls using this proxy config.
* @param enable True to enable quality reporting, false to disable it.
*/
void enableQualityReporting(boolean enable);
/**
* Whether quality reporting is used for calls through this proxy.
* @return
* @return
*/
boolean qualityReportingEnabled();
/**
* Set the interval between quality interval reports during a call when using quality reporting.
* @param interval The interval in seconds (should be greater than 120 seconds to avoid too much).
*/
void setQualityReportingInterval(int interval);
/**
* Get the interval between quality interval reports during a call when using quality reporting.
* @return The interval in seconds.
*/
int getQualityReportingInterval();
/**
* Set the collector SIP URI to collect reports when using quality reporting.
* @param collector The collector SIP URI which should be configured server side too.
*/
void setQualityReportingCollector(String collector);
/**
* Get the collector SIP URI collecting reports when using quality reporting.
* @return The SIP URI collector address.
*/
String getQualityReportingCollector();
/**
* Set the outbound proxy realm. It is used in digest authentication to avoid
* re-authentication if a previous token has already been provided.
* @param The new outbound proxy realm.
*/
void setRealm(String realm);
/**
* Get the outbound proxy realm.
* @return The outbound proxy realm.
*/
String getRealm();
/**
* Set optional contact parameters that will be added to the contact information sent in the registration.
* @param contact_params a string containing the additional parameters in text form, like "myparam=something;myparam2=something_else"
@ -235,13 +245,13 @@ public interface LinphoneProxyConfig {
* As an example, the contact address in the SIP register sent will look like <sip:joe@15.128.128.93:50421>;android-push-id=43143-DFE23F-2323-FA2232.
**/
public void setContactParameters(String contact_params);
/**
* Get the contact's parameters.
* @return
*/
public String getContactParameters();
/**
* Set optional contact parameters that will be added to the contact information sent in the registration, inside the URI.
* @param params a string containing the additional parameters in text form, like "myparam=something;myparam2=something_else"
@ -250,34 +260,55 @@ public interface LinphoneProxyConfig {
* As an example, the contact address in the SIP register sent will look like <sip:joe@15.128.128.93:50421;apple-push-id=43143-DFE23F-2323-FA2232>.
**/
public void setContactUriParameters(String params);
/**
* Get the contact's URI parameters.
* @return
*/
public String getContactUriParameters();
/**
* Return the international prefix for the given country
* @param country iso code
*/
public int lookupCCCFromIso(String iso);
/**
* Return the international prefix for the given country
* @param e164 phone number
*/
public int lookupCCCFromE164(String e164);
/**
* Return reason error code.
* @return reason code.
*/
public Reason getError();
/**
* Get full error information about last error occured on the proxy config.
* @return an ErrorInfo.
*/
public ErrorInfo getErrorInfo();
/**
* Set the publish expiration time in second.
* @param expires in second
*/
public void setPublishExpires(int expires);
/**
* @return the publish expiration time in second. Default value is the registration expiration value.
*/
public int getPublishExpires();
/**
* attached a user data to a proxy config
**/
void setUserData(Object obj);
/**
* Returns user data from a proxy config. return null if any
* @return an Object.
*/
Object getUserData();
}

View file

@ -37,7 +37,7 @@ class LinphoneAuthInfoImpl implements LinphoneAuthInfo {
boolean ownPtr = false;
protected LinphoneAuthInfoImpl(String username,String password, String realm, String domain) {
this(username, null, password, null, null, domain);
this(username, null, password, null, realm, domain);
}
protected LinphoneAuthInfoImpl(String username, String userid, String passwd, String ha1, String realm, String domain) {
nativePtr = newLinphoneAuthInfo();
@ -46,6 +46,7 @@ class LinphoneAuthInfoImpl implements LinphoneAuthInfo {
this.setPassword(passwd);
this.setHa1(ha1);
this.setDomain(domain);
this.setRealm(realm);
ownPtr = true;
}
protected LinphoneAuthInfoImpl(long aNativePtr) {

View file

@ -22,6 +22,7 @@ class LinphoneCallImpl implements LinphoneCall {
protected final long nativePtr;
boolean ownPtr = false;
Object userData;
private LinphoneCallStats audioStats;
private LinphoneCallStats videoStats;
@ -236,4 +237,12 @@ class LinphoneCallImpl implements LinphoneCall {
public ErrorInfo getErrorInfo() {
return new ErrorInfoImpl(getErrorInfo(nativePtr));
}
@Override
public void setUserData(Object obj) {
userData = obj;
}
@Override
public Object getUserData() {
return userData;
}
}

View file

@ -48,6 +48,12 @@ public class LinphoneChatMessageImpl implements LinphoneChatMessage {
return new LinphoneAddressImpl(getFrom(nativePtr),LinphoneAddressImpl.WrapMode.FromConst);
}
private native long getTo(long ptr);
@Override
public LinphoneAddress getTo() {
return new LinphoneAddressImpl(getTo(nativePtr),LinphoneAddressImpl.WrapMode.FromConst);
}
private native void addCustomHeader(long nativePtr, String name, String value);
@Override
public void addCustomHeader(String name, String value) {
@ -93,7 +99,32 @@ public class LinphoneChatMessageImpl implements LinphoneChatMessage {
public ErrorInfo getErrorInfo() {
return new ErrorInfoImpl(getErrorInfo(nativePtr));
}
protected void finalize(){
protected void finalize() throws Throwable{
unref(nativePtr);
super.finalize();
}
private native void startFileDownload(long ptr, StateListener listener);
@Override
public void startFileDownload(StateListener listener) {
startFileDownload(nativePtr, listener);
}
private native Object getFileTransferInformation(long ptr);
@Override
public LinphoneContent getFileTransferInformation() {
return (LinphoneContent) getFileTransferInformation(nativePtr);
}
private native void setAppData(long ptr, String data);
@Override
public void setAppData(String data) {
setAppData(nativePtr, data);
}
private native String getAppData(long ptr);
@Override
public String getAppData() {
return getAppData(nativePtr);
}
}

View file

@ -27,9 +27,11 @@ class LinphoneChatRoomImpl implements LinphoneChatRoom {
private native long getPeerAddress(long ptr);
private native void sendMessage(long ptr, String message);
private native void sendMessage2(long ptr, Object msg, long messagePtr, StateListener listener);
private native long[] getHistoryRange(long ptr, int begin, int end);
private native long[] getHistory(long ptr, int limit);
private native void destroy(long ptr);
private native int getUnreadMessagesCount(long ptr);
private native int getHistorySize(long ptr);
private native void deleteHistory(long ptr);
private native void compose(long ptr);
private native boolean isRemoteComposing(long ptr);
@ -44,100 +46,106 @@ class LinphoneChatRoomImpl implements LinphoneChatRoom {
nativePtr = aNativePtr;
}
public synchronized LinphoneAddress getPeerAddress() {
public LinphoneAddress getPeerAddress() {
return new LinphoneAddressImpl(getPeerAddress(nativePtr),LinphoneAddressImpl.WrapMode.FromConst);
}
public synchronized void sendMessage(String message) {
public void sendMessage(String message) {
synchronized(getCore()){
sendMessage(nativePtr,message);
}
}
@Override
public synchronized void sendMessage(LinphoneChatMessage message, StateListener listener) {
public void sendMessage(LinphoneChatMessage message, StateListener listener) {
synchronized(getCore()){
sendMessage2(nativePtr, message, ((LinphoneChatMessageImpl)message).getNativePtr(), listener);
}
}
@Override
public synchronized LinphoneChatMessage createLinphoneChatMessage(String message) {
public LinphoneChatMessage createLinphoneChatMessage(String message) {
synchronized(getCore()){
return new LinphoneChatMessageImpl(createLinphoneChatMessage(nativePtr, message));
}
}
public synchronized LinphoneChatMessage[] getHistory() {
public LinphoneChatMessage[] getHistory() {
synchronized(getCore()){
return getHistory(0);
}
}
public synchronized LinphoneChatMessage[] getHistory(int limit) {
public LinphoneChatMessage[] getHistoryRange(int begin, int end) {
synchronized(getCore()){
long[] typesPtr = getHistory(nativePtr, limit);
if (typesPtr == null) return null;
LinphoneChatMessage[] messages = new LinphoneChatMessage[typesPtr.length];
for (int i=0; i < messages.length; i++) {
messages[i] = new LinphoneChatMessageImpl(typesPtr[i]);
}
return messages;
long[] typesPtr = getHistoryRange(nativePtr, begin, end);
return getHistoryPrivate(typesPtr);
}
}
public synchronized void destroy() {
public LinphoneChatMessage[] getHistory(int limit) {
synchronized(getCore()){
long[] typesPtr = getHistory(nativePtr, limit);
return getHistoryPrivate(typesPtr);
}
}
public void destroy() {
destroy(nativePtr);
}
public synchronized int getUnreadMessagesCount() {
public int getUnreadMessagesCount() {
synchronized(getCore()){
return getUnreadMessagesCount(nativePtr);
}
}
public synchronized void deleteHistory() {
public int getHistorySize() {
synchronized(getCore()){
return getHistorySize(nativePtr);
}
}
public void deleteHistory() {
synchronized(getCore()){
deleteHistory(nativePtr);
}
}
public synchronized void compose() {
public void compose() {
synchronized(getCore()){
compose(nativePtr);
}
}
public synchronized boolean isRemoteComposing() {
public boolean isRemoteComposing() {
synchronized(getCore()){
return isRemoteComposing(nativePtr);
}
}
public synchronized void markAsRead() {
public void markAsRead() {
synchronized(getCore()){
markAsRead(nativePtr);
}
}
public synchronized void deleteMessage(LinphoneChatMessage message) {
public void deleteMessage(LinphoneChatMessage message) {
synchronized(getCore()){
if (message != null)
deleteMessage(nativePtr, ((LinphoneChatMessageImpl)message).getNativePtr());
}
}
public synchronized void updateUrl(LinphoneChatMessage message) {
public void updateUrl(LinphoneChatMessage message) {
synchronized(getCore()){
if (message != null)
updateUrl(nativePtr, ((LinphoneChatMessageImpl)message).getNativePtr());
}
}
@Override
public synchronized LinphoneChatMessage createLinphoneChatMessage(String message,
public LinphoneChatMessage createLinphoneChatMessage(String message,
String url, State state, long timestamp, boolean isRead,
boolean isIncoming) {
synchronized(getCore()){
@ -150,4 +158,30 @@ class LinphoneChatRoomImpl implements LinphoneChatRoom {
public synchronized LinphoneCore getCore() {
return (LinphoneCore)getCore(nativePtr);
}
private LinphoneChatMessage[] getHistoryPrivate(long[] typesPtr) {
if (typesPtr == null) return null;
LinphoneChatMessage[] messages = new LinphoneChatMessage[typesPtr.length];
for (int i=0; i < messages.length; i++) {
messages[i] = new LinphoneChatMessageImpl(typesPtr[i]);
}
return messages;
}
private native long createFileTransferMessage(long ptr, String name, String type, String subtype, int size);
@Override
public LinphoneChatMessage createFileTransferMessage(LinphoneContent content) {
synchronized(getCore()) {
return new LinphoneChatMessageImpl(createFileTransferMessage(nativePtr, content.getName(), content.getType(), content.getSubtype(), content.getRealSize()));
}
}
private native void cancelFileTransfer(long ptr, long messagePtr);
@Override
public void cancelFileTransfer(LinphoneChatMessage message) {
synchronized(getCore()) {
cancelFileTransfer(nativePtr, ((LinphoneChatMessageImpl)message).getNativePtr());
}
}
}

Some files were not shown because too many files have changed in this diff Show more