diff --git a/.gitignore b/.gitignore
index 6a94843fa..85a6aed1d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -73,3 +73,8 @@ tools/xml2lpc_test
coreapi/help/filetransfer
tester/receive_file.dump
tester/tmp.db
+.DS_Store
+Linphone.app
+*.dmg
+tester/linphone*.log
+tester/linphone_log.txt
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 470df4585..4311101fd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -20,7 +20,7 @@
#
############################################################################
-cmake_minimum_required(VERSION 2.6)
+cmake_minimum_required(VERSION 2.8.12)
project(LINPHONE C CXX)
@@ -61,6 +61,13 @@ endif()
find_package(BelleSIP REQUIRED)
find_package(MS2 REQUIRED)
find_package(XML2 REQUIRED)
+if(ENABLE_TUNNEL)
+ find_package(Tunnel)
+ if(NOT TUNNEL_FOUND)
+ message(WARNING "Could not find the tunnel library!")
+ set(ENABLE_TUNNEL OFF CACHE BOOL "Enable tunnel support" FORCE)
+ endif()
+endif()
include_directories(
@@ -72,6 +79,9 @@ include_directories(
${MS2_INCLUDE_DIRS}
${XML2_INCLUDE_DIRS}
)
+if(ENABLE_TUNNEL)
+ include_directories(${TUNNEL_INCLUDE_DIRS})
+endif()
if(MSVC)
include_directories(${CMAKE_PREFIX_PATH}/include/MSVC)
@@ -94,6 +104,9 @@ add_definitions(-DHAVE_CONFIG_H)
add_subdirectory(coreapi)
add_subdirectory(share)
+if(ENABLE_TOOLS)
+ add_subdirectory(tools)
+endif()
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/FindLinphone.cmake
diff --git a/FindLinphone.cmake b/FindLinphone.cmake
index fdb582c72..6c6871330 100644
--- a/FindLinphone.cmake
+++ b/FindLinphone.cmake
@@ -26,6 +26,7 @@
# 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)
@@ -55,15 +56,19 @@ find_library(LINPHONE_LIBRARIES
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_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 LINPHONE_CPPFLAGS
+ LINPHONE_INCLUDE_DIRS LINPHONE_LIBRARIES
)
-mark_as_advanced(LINPHONE_INCLUDE_DIRS LINPHONE_LIBRARIES LINPHONE_CPPFLAGS)
+mark_as_advanced(LINPHONE_INCLUDE_DIRS LINPHONE_LIBRARIES LINPHONE_CPPFLAGS LINPHONE_LDFLAGS)
diff --git a/Makefile.am b/Makefile.am
index ff729400c..dd66874b2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -51,7 +51,7 @@ PACKAGE_BUNDLE_FILE=$(top_srcdir)/build/macos/$(PACKAGE).bundle
EXTRA_DIST = BUGS \
README.arm \
README.mingw \
- README.macos \
+ README.macos.md \
autogen.sh \
linphone.spec \
linphone.spec.in \
@@ -172,7 +172,7 @@ filelist: zip
setup.exe: filelist
cp $(ISS_SCRIPT) $(INSTALLDIR_WITH_PREFIX)/.
cd $(INSTALLDIR_WITH_PREFIX) && \
- $(ISCC) $(ISS_SCRIPT)
+ $(ISCC) $(ISS_SCRIPT)
mv $(INSTALLDIR_WITH_PREFIX)/Output/setup.exe $(PACKAGE)-$(VERSION)-setup.exe
rm -rf $(INSTALLDIR_WITH_PREFIX)/Output
rm -f $(INSTALLDIR_WITH_PREFIX)/$(PACKAGE_WIN32_FILELIST)
diff --git a/README b/README
index a2fe5301e..30666070a 100644
--- a/README
+++ b/README
@@ -11,12 +11,12 @@ This is Linphone, a free (GPL) video softphone based on the SIP protocol.
- belle-sip>=1.3.0
- speex>=1.2.0 (including libspeexdsp part)
- libxml2
-
+
+ if you want the gtk/glade interface:
- libgtk >=2.16.0
+ if you want video support:
- libvpx (VP8 codec)
- - libavcodec (ffmpeg)
+ - libavcodec (ffmpeg)
- libswscale (part of ffmpeg too) for better scaling performance
- libxv (x11 video extension)
- libgl1-mesa (OpenGL API -- GLX development files)
@@ -31,31 +31,31 @@ This is Linphone, a free (GPL) video softphone based on the SIP protocol.
+ if you want uPnP support (optional):
- libupnp (version 1.6 branch (not patched with 18-url-upnpstrings.patch))
- Here is the command line to get these dependencies installed for Ubuntu && Debian
+ 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
- $ cd srtp && autoconf && ./configure && make
- $ sudo make install
+ $ cd srtp && autoconf && ./configure && make
+ $ sudo make install
- + Install zrtpcpp (optional), for unbreakable call encryption
- $ sudo apt-get install cmake
- $ git clone https://github.com/wernerd/ZRTPCPP.git
- $ cd ZRTPCPP
- $ cmake -DCORE_LIB=true -DSDES=false . && make
- $ sudo make install
- If you get this error: "cc1plus: error: unrecognized command line option ‘-std=c++11’", edit CMakeLists.txt and replace c++11 by c++0x .
+ + Install zrtp (optional), for unbreakable call encryption
+ $ git clone git://git.linphone.org:bzrtp
+ $ cd bzrtp && ./autogen.sh && ./configure && make
+ $ sudo make install
- Compile linphone
$ ./autogen.sh
- $ ./configure
- $ make && sudo make install
+ $ ./configure
+ $ make && sudo make install
$ sudo ldconfig
@@ -68,10 +68,10 @@ For macOS X, see README.macos
Here is a short description of the content of the source tree.
-- oRTP/ is a poweful implementation of the RTP protocol. See the oRTP/README for more details.
+- oRTP/ is a poweful implementation of the RTP protocol. See the oRTP/README for more details.
It is used by the mediastreamer to send and receive streams to the network.
-- mediastreamer2/ is one of the important part of linphone. It is a framework library for audio
+- mediastreamer2/ is one of the important part of linphone. It is a framework library for audio
and video processing. It contains several objects for grabing audio and video and outputing
it (through rtp, to file).
It contains also codec objects to compress audio and video streams.
@@ -86,6 +86,6 @@ Here is a short description of the content of the source tree.
* linphonec.c is the main file for the console version of linphone.
* sipomatic.c / sipomatic.h contains the code for sipomatic, the test program that auto-answer to linphone calls.
* shell.c (program name: linphonecsh) is a small utilities to send interactive commands to a running linphonec daemon.
-
+
- share/ contains translation, documentation, rings and hello sound files.
diff --git a/README.macos b/README.macos
deleted file mode 100644
index 05a00e080..000000000
--- a/README.macos
+++ /dev/null
@@ -1,145 +0,0 @@
-**********************************
-* Compiling linphone on macos X *
-**********************************
-
-You need:
- - Xcode (download from apple or using appstore application)
- - Macports: http://www.macports.org/
- Download and install macports using its user friendly installer.
-
-- In order to enable generation of bundle for multiple macos version and 32 bit processors, it is recommended to:
- 1) edit /opt/local/etc/macports/macports.conf to add the following line:
- macosx_deployment_target 10.6
- 2) edit /opt/local/etc/macports/variants.conf to add the following line:
- +universal
-
-- Install build time dependencies
- $ 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 ffmpeg-devel -gpl2
-
-- Install gtk. It is recommended to use the quartz backend for better integration.
- $ sudo port install gtk2 +quartz +no_x11
- $ sudo port install gtk-osx-application -python27
- $ sudo port install hicolor-icon-theme
-
-The next pieces need to be compiled manually. To ensure compatibility with multiple mac os version it is recommended to do:
- $ export MACOSX_DEPLOYMENT_TARGET=10.6
- $ export CFLAGS="-arch i386 -arch x86_64 -mmacosx-version-min=10.5"
- $ export OBJCFLAGS="-arch i386 -arch x86_64 -mmacosx-version-min=10.5"
- $ export CXXFLAGS="-arch i386 -arch x86_64 -mmacosx-version-min=10.5"
- $ export LDFLAGS="-arch i386 -arch x86_64 -mmacosx-version-min=10.5 -Wl,-headerpad_max_install_names -Wl,-read_only_relocs -Wl,suppress"
-
-- (Optional) libvpx-1.2 has a bug on macos resulting in ugly video. It is recommended to upgrade it manually to 1.3 from source.
- The libvpx build isn't able to produce dual architecture files. To workaround this, configure libvpx twice and use lipo to create a dual architecture
- libvpx.a .
-
-- Install libantlr3c (library used by belle-sip for parsing)
- $ git clone -b linphone git://git.linphone.org/antlr3.git
- $ cd antlr3/runtime/C
- $ ./autogen.sh
- $ ./configure --disable-static --prefix=/opt/local && make
- $ sudo make install
-
-- Install polarssl (encryption library used by belle-sip)
- $ git clone git://git.linphone.org/polarssl.git -b linphone
- $ cd polarssl
- $ ./autogen.sh && ./configure --prefix=/opt/local && make
- $ sudo make install
-
-- Install belle-sip (sip stack)
- $ git clone git://git.linphone.org/belle-sip.git
- $ cd belle-sip
- $ ./autogen.sh && ./configure --prefix=/opt/local && make
- $ sudo make install
-
-- Install srtp (optional) for call encryption
- $ git clone git://git.linphone.org/srtp.git
- $ cd srtp && autoconf && ./configure --prefix=/opt/local && make libsrtp.a
- $ sudo make install
-
-- Install zrtpcpp (optional), for unbreakable call encryption
- $ sudo port install cmake
- $ git clone https://github.com/wernerd/ZRTPCPP.git
- $ cd ZRTPCPP
- $ cmake -DCORE_LIB=true -DSDES=false CMAKE_INSTALL_NAME_DIR=/usr/local/lib/ -DCMAKE_C_FLAGS="-arch i386 -arch x86_64 -mmacosx-version-min=10.5" -DCMAKE_CXX_FLAGS="-arch i386 -arch x86_64 --stdlib=libstdc++ -std=c++11 -lstdc++ -mmacosx-version-min=10.5" -DCMAKE_C_COMPILER=`xcrun --find clang` -DCMAKE_CXX_COMPILER=`xcrun --find clang` .
-$ sudo make install
-
-
-- Install gsm codec (optional)
- $ git clone git://git.linphone.org/gsm.git
- $ cd gsm
- $ make CCFLAGS="$CFLAGS -c -O2 -DNeedFunctionPrototypes=1"
- $ sudo make install INSTALL_ROOT=/opt/local GSM_INSTALL_INC=/opt/local/include
-
-- Compile and install the tunnel library (optional, proprietary extension only)
-
- If you got the source code from git, run ./autogen.sh first.
- Then or otherwise, do:
-
- $ ./configure --prefix=/opt/local && make && sudo make install
-
-- Compile linphone
-
- If you got the source code from git, run ./autogen.sh first.
-
- Then or otherwise, do:
-
- $ PKG_CONFIG_PATH=/usr/local/lib/pkgconfig ./configure --prefix=/opt/local --with-readline=/opt/local --disable-x11 --with-srtp=/opt/local --with-gsm=/opt/local --enable-zrtp --disable-strict && make
-
- Install to /opt/local
-
- $ sudo make install
-
- Done.
-
-If you want to generate a portable bundle, then install gtk-mac-bundler.
-Use git:
- $ git clone https://github.com/jralls/gtk-mac-bundler.git
- $ cd gtk-mac-bundler && make install
- $ export PATH=$PATH:~/.local/bin
- #make this dummy charset.alias file for the bundler to be happy:
- $ sudo touch touch /opt/local/lib/charset.alias
-
-The bundler file in build/macos/linphone.bundle expects some plugins to be installed in /opt/local/lib/mediastreamer/plugins .
-If you don't need plugins, remove or comment out this line from the bundler file:
-
- ${prefix:ms2plugins}/lib/mediastreamer/plugins/*.*.so
-
-
-Then run, inside linphone source tree:
- Run configure as told before but with "--enable-relativeprefix" appended.
- $ make
- $ make bundle
-
-The resulting bundle is located in linphone build directory, together with a zipped version.
-
-For a better appearance, you can install the gtk-quartz-engine (a gtk theme) that make gtk application more similar to other mac applications (but not perfect).
-
- $ git clone https://github.com/jralls/gtk-quartz-engine.git
- $ cd gtk-quartz-engine
- $ autoreconf -i
- $ ./configure --prefix=/opt/local CFLAGS="$CFLAGS -Wno-error" && make
- $ sudo make install
-
-Generate a new bundle to have it included.
-
-libiconv hack
-*************
-
-The Makefile.am rules used to generate the bundle fetch a libiconv.2.dylib from a linphone download page.
-This library adds some additional symbols so that dependencies requiring the iconv from /usr/lib and the ones requiring from the bundle are both satisfied.
-In case this library needs to generated, here are the commands:
- $ wget http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.14.tar.gz
- $ cd libiconv-1.14
- $ patch -p1 < ../linphone/build/macos/libiconv-macos.patch
- $ ./configure --prefix=/opt/local --disable-static 'CFLAGS=-arch i386 -arch x86_64 -mmacosx-version-min=10.5' 'LDFLAGS=-arch i386 -arch x86_64 -mmacosx-version-min=10.5' CXXFLAGS="-arch i386 -arch x86_64 -mmacosx-version-min=10.5" && make
- $ make install DESTDIR=/tmp
-
-The resulted library can be found in /tmp/opt/local/lib
-
-
-
-
diff --git a/README.macos.md b/README.macos.md
new file mode 100644
index 000000000..cbdd4c24c
--- /dev/null
+++ b/README.macos.md
@@ -0,0 +1,184 @@
+# Compiling Linphone on MacOS X
+
+## Dependencies
+
+* Xcode (download from apple or using appstore application)
+* Java SE
+* [HomeBrew](http://brew.sh) or [Macports](http://www.macports.org/).
+
+### Multiple MacOS version support
+
+In order to enable generation of bundle for multiple MacOS version and 32 bit processors, it is recommended to:
+
+1. Edit `/opt/local/etc/macports/macports.conf` to add the following line:
+
+ > macosx_deployment_target 10.6
+
+2. Edit `/opt/local/etc/macports/variants.conf` to add the following line:
+
+ > +universal
+
+### Build time dependencies
+
+#### Using MacPorts
+
+* Linphone core dependencies
+
+ sudo port install automake autoconf libtool intltool wget cunit \
+ antlr3 speex libvpx readline sqlite3 libsoup openldap libupnp \
+ ffmpeg-devel -gpl2
+
+* UI dependencies: install `GTK`. It is recommended to use the `quartz` backend for better integration.
+
+ sudo port install gtk2 +quartz +no_x11
+ sudo port install gtk-osx-application -python27
+ sudo port install hicolor-icon-theme
+
+ #### Using HomeBrew
+
+ brew install automake intltool libtool pkg-config coreutils \
+ yasm nasm wget imagemagick gettext gtk+ speex ffmpeg pygtk
+ brew link gettext --force
+ # readline is required from linphonec.c otherwise compilation will fail
+ brew link readline --force
+
+ # then you have to install antlr3 from a tap.
+ wget https://gist.githubusercontent.com/Gui13/f5cf103f50d34c28c7be/raw/f50242f5e0c3a6d25ed7fca1462bce3a7b738971/antlr3.rb
+ mv antlr3.rb /usr/local/Library/Formula/
+ brew install antlr3
+
+ brew tap marekjelen/gtk
+ brew install gtk+-quartz
+
+ # gtk-mac-integration is not available in main repository or Brew yet.
+ wget https://gist.github.com/Gui13/cdcad37faa6b8ffa0588/raw/bf2277d45e261ad48ae1344c4c97f2684974ed87/gtk-mac-integration.rb
+ mv gtk-mac-integration.rb /usr/local/Library/Formula/
+ brew install gtk-mac-integration
+
+### Building Linphone
+
+The next pieces need to be compiled manually.
+
+* To ensure compatibility with multiple MacOS versions it is recommended to do:
+
+ export MACOSX_DEPLOYMENT_TARGET=10.6
+ export CFLAGS="-arch i386 -arch x86_64 -mmacosx-version-min=10.5"
+ export OBJCFLAGS="-arch i386 -arch x86_64 -mmacosx-version-min=10.5"
+ export CXXFLAGS="-arch i386 -arch x86_64 -mmacosx-version-min=10.5"
+ export LDFLAGS="-arch i386 -arch x86_64 -mmacosx-version-min=10.5 -Wl,-headerpad_max_install_names -Wl,-read_only_relocs -Wl,suppress"
+
+* Install libantlr3c (library used by belle-sip for parsing)
+
+ git clone -b linphone git://git.linphone.org/antlr3.git
+ cd antlr3/runtime/C
+ ./autogen.sh
+ ./configure --disable-static --prefix=/opt/local && make
+ sudo make install
+
+* Install polarssl (encryption library used by belle-sip)
+
+ git clone git://git.linphone.org/polarssl.git -b linphone
+ cd polarssl
+ ./autogen.sh && ./configure --prefix=/opt/local && make
+ sudo make install
+
+* Install belle-sip (sip stack)
+
+ git clone git://git.linphone.org/belle-sip.git
+ cd belle-sip
+ ./autogen.sh && ./configure --prefix=/opt/local && make
+ sudo make install
+
+* (Optional) Install srtp for call encryption
+
+ git clone git://git.linphone.org/srtp.git
+ cd srtp && autoconf && ./configure --prefix=/opt/local && make libsrtp.a
+ sudo make install
+
+* (Optional) Install zrtp, for unbreakable call encryption
+
+ git clone git://git.linphone.org:bzrtp
+ cd bzrtp && ./autogen.sh && ./configure --prefix=/opt/local && make
+ sudo make install
+
+* (Optional) Install gsm codec
+
+ git clone git://git.linphone.org/gsm.git
+ cd gsm
+ make CCFLAGS="$CFLAGS -c -O2 -DNeedFunctionPrototypes=1"
+ sudo make install INSTALL_ROOT=/opt/local GSM_INSTALL_INC=/opt/local/include
+
+* (Optional) libvpx-1.2 has a bug on MacOS resulting in ugly video. It is recommended to upgrade it manually to 1.3 from source.
+The libvpx build isn't able to produce dual architecture files. To workaround this, configure libvpx twice and use lipo to create a dual architecture `libvpx.a`.
+
+* (Optional, proprietary extension only) Compile and install the tunnel library
+
+ If you got the source code from git, run `./autogen.sh` first.
+ Then or otherwise, do:
+
+ ./configure --prefix=/opt/local && make && sudo make install
+
+* Compile Linphone
+
+ If you got the source code from git, run `./autogen.sh` first.
+
+ Then or otherwise, do:
+
+ PKG_CONFIG_PATH=/usr/local/lib/pkgconfig ./configure --prefix=/opt/local --with-readline=/opt/local --disable-x11 --with-srtp=/opt/local --with-gsm=/opt/local --enable-zrtp --disable-strict && make
+
+* Install on the system
+
+ sudo make install
+
+You are done.
+
+### Generate portable bundle
+
+If you want to generate a portable bundle, then install `gtk-mac-bundler`:
+
+ git clone https://github.com/jralls/gtk-mac-bundler.git
+ cd gtk-mac-bundler && make install
+ export PATH=$PATH:~/.local/bin
+ #make this dummy charset.alias file for the bundler to be happy:
+ sudo touch /opt/local/lib/charset.alias
+
+The bundler file in `build/MacOS/linphone.bundle` expects some plugins to be installed in `/opt/local/lib/mediastreamer/plugins`.
+If you don't need plugins, remove or comment out this line from the bundler file:
+
+
+ ${prefix:ms2plugins}/lib/mediastreamer/plugins/*.*.so
+
+
+Then run, inside Linphone source tree configure as told before but with `--enable-relativeprefix` appended.
+
+ make && make bundle
+
+The resulting bundle is located in Linphone build directory, together with a zipped version.
+
+* For a better appearance, you can install `gtk-quartz-engine` (a GTK theme) that makes GTK application more similar to other Mac applications (but not perfect).
+
+ git clone https://github.com/jralls/gtk-quartz-engine.git
+ cd gtk-quartz-engine
+ autoreconf -i
+ ./configure --prefix=/opt/local CFLAGS="$CFLAGS -Wno-error" && make
+ sudo make install
+
+Generate a new bundle to have it included.
+
+### libiconv hack
+
+The `Makefile.am` rules used to generate the bundle fetch a `libiconv.2.dylib` from a Linphone download page.
+This library adds some additional symbols so that dependencies requiring the `iconv` from `/usr/lib` and the ones requiring from the bundle are both satisfied.
+In case this library needs to generated, here are the commands:
+
+ wget http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.14.tar.gz
+ cd libiconv-1.14
+ patch -p1 < ../linphone/build/MacOS/libiconv-MacOS.patch
+ ./configure --prefix=/opt/local --disable-static 'CFLAGS=-arch i386 -arch x86_64 -mmacosx-version-min=10.5' 'LDFLAGS=-arch i386 -arch x86_64 -mmacosx-version-min=10.5' CXXFLAGS="-arch i386 -arch x86_64 -mmacosx-version-min=10.5" && make
+ make install DESTDIR=/tmp
+
+The resulted library can be found in `/tmp/opt/local/lib`.
+
+
+
+
diff --git a/README.mingw b/README.mingw
index 8b97ea1ef..5e859680b 100644
--- a/README.mingw
+++ b/README.mingw
@@ -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 /:
@@ -60,9 +60,12 @@ General rules for compilation
- all other commands (configure, autogen.sh, make) must be done within the mingw shell (msys).
In both msys and msys-git windows, change into the directory you created for sources:
cd /c/sources
+- make sure pkg-config works by adding this env variable to your terminal:
+ export PKG_CONFIG_PATH=/usr/lib/pkgconfig
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
diff --git a/autogen.sh b/autogen.sh
index cf357cd66..9cedbf164 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -22,6 +22,7 @@ if test -f /opt/local/bin/glibtoolize ; then
else
LIBTOOLIZE=libtoolize
fi
+
if test -d /opt/local/share/aclocal ; then
ACLOCAL_ARGS="-I /opt/local/share/aclocal"
fi
@@ -30,13 +31,7 @@ if test -d /share/aclocal ; then
ACLOCAL_ARGS="$ACLOCAL_ARGS -I /share/aclocal"
fi
-if test -f /opt/local/bin/intltoolize ; then
- #darwin
- INTLTOOLIZE=/opt/local/bin/intltoolize
-else
- #on mingw, it is important to invoke intltoolize with an absolute path to avoid a bug
- INTLTOOLIZE=/usr/bin/intltoolize
-fi
+INTLTOOLIZE=$(which intltoolize)
echo "Generating build scripts in linphone..."
set -x
diff --git a/build/android/Android.mk b/build/android/Android.mk
index 817aba539..c281b241d 100755
--- a/build/android/Android.mk
+++ b/build/android/Android.mk
@@ -65,10 +65,14 @@ LOCAL_SRC_FILES := \
xml2lpc.c \
lpc2xml.c \
remote_provisioning.c \
- quality_reporting.c
-
-ifndef LINPHONE_VERSION
-LINPHONE_VERSION = "Devel"
+ quality_reporting.c \
+ call_log.c \
+ call_params.c \
+ player.c \
+ localplayer.c
+
+ifndef LIBLINPHONE_VERSION
+LIBLINPHONE_VERSION = "Devel"
endif
LOCAL_CFLAGS += \
@@ -77,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
@@ -262,5 +266,8 @@ LOCAL_MODULE_FILENAME := liblinphone-$(TARGET_ARCH_ABI)
include $(BUILD_SHARED_LIBRARY)
+LOCAL_CPPFLAGS=$(LOCAL_CFLAGS)
+LOCAL_CFLAGS += -Wdeclaration-after-statement
+
$(call import-module,android/cpufeatures)
diff --git a/build/android/liblinphone_gitversion.h b/build/android/liblinphone_gitversion.h
deleted file mode 100644
index 50e8a106e..000000000
--- a/build/android/liblinphone_gitversion.h
+++ /dev/null
@@ -1 +0,0 @@
-#define LIBLINPHONE_GIT_VERSION "unknown"
diff --git a/build/android/liblinphone_tester.mk b/build/android/liblinphone_tester.mk
index cada1aba4..5ca3732be 100644
--- a/build/android/liblinphone_tester.mk
+++ b/build/android/liblinphone_tester.mk
@@ -13,7 +13,10 @@ common_SRC_FILES := \
flexisip_tester.c \
tester.c \
remote_provisioning_tester.c \
- quality_reporting_tester.c
+ quality_reporting_tester.c \
+ log_collection_tester.c \
+ transport_tester.c \
+ player_tester.c
common_C_INCLUDES += \
$(LOCAL_PATH) \
diff --git a/build/wp8/LibLinphone.vcxproj b/build/wp8/LibLinphone.vcxproj
index 797b2517d..cca41bb87 100644
--- a/build/wp8/LibLinphone.vcxproj
+++ b/build/wp8/LibLinphone.vcxproj
@@ -53,8 +53,8 @@
Level4
- $(ProjectDir)..\..\..\belle-sip\include;$(ProjectDir)..\..\oRTP\include;$(ProjectDir)..\..\mediastreamer2\include;$(ProjectDIr)..\..\..\tunnel\include;$(ProjectDir)..\..\coreapi;$(ProjectDir)..\..\include;$(SolutionDir)$(Platform)\$(Configuration)\include;%(AdditionalIncludeDirectories)
- __STDC_CONSTANT_MACROS;_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;_USRDLL;WINDOW_NATIVE;_TRUE_TIME;IN_LINPHONE;USE_BELLESIP;TUNNEL_ENABLED;VIDEO_ENABLED;LINPHONE_PACKAGE_NAME="linphone";LINPHONE_VERSION="Devel";LIBLINPHONE_EXPORTS;LINPHONE_PLUGINS_DIR=".";UNICODE;_XKEYCHECK_H;%(PreprocessorDefinitions)
+ $(ProjectDir)..\..\..\belle-sip\include;$(ProjectDir)..\..\oRTP\include;$(ProjectDir)..\..\mediastreamer2\include;$(ProjectDir)..\..\..\tunnel\include;$(ProjectDir)..\..\coreapi;$(ProjectDir)..\..\include;$(SolutionDir)$(Platform)\$(Configuration)\include;$(ProjectDir)..\..\..\zlib;$(ProjectDir)..\..\..\sqlite\;$(ProjectDir);%(AdditionalIncludeDirectories)
+ __STDC_CONSTANT_MACROS;_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;_USRDLL;WINDOW_NATIVE;_TRUE_TIME;IN_LINPHONE;USE_BELLESIP;TUNNEL_ENABLED;VIDEO_ENABLED;LINPHONE_PACKAGE_NAME="linphone";LIBLINPHONE_EXPORTS;LINPHONE_PLUGINS_DIR=".";UNICODE;_XKEYCHECK_H;HAVE_ZLIB;HAVE_CONFIG_H;%(PreprocessorDefinitions)
Default
NotUsing
false
@@ -68,13 +68,16 @@
$(SolutionDir)$(Platform)\$(Configuration);%(AdditionalLibraryDirectories)
$(TargetDir)$(TargetName).lib
-
- $(TargetDir)$(TargetName)_dll.lib;%(Outputs)
-
+
+ version.bat
+
+
+ Batch script to get the git version
+
- _DEBUG;%(PreprocessorDefinitions)
+ _DEBUG;MSG_STORAGE_ENABLED;%(PreprocessorDefinitions)
true
@@ -82,7 +85,7 @@
- NDEBUG;%(PreprocessorDefinitions)
+ NDEBUG;MSG_STORAGE_ENABLED;%(PreprocessorDefinitions)
MaxSpeed
true
true
@@ -107,6 +110,8 @@
+
+
@@ -119,11 +124,13 @@
+
+
@@ -148,6 +155,8 @@
+
+
@@ -186,6 +195,9 @@
{0565952a-ea62-46a2-8261-f5b4b490da42}
+
+ {a45d63b9-60de-476c-8836-f8eedbe139d0}
+
{59500dd1-b192-4ddf-a402-8a8e3739e032}
@@ -198,6 +210,9 @@
{5dfa07b4-0be9-46a9-ba32-fdf5a55c580b}
+
+ {7afac3bb-d97b-4578-b9fe-5e1d2b94ea2f}
+
diff --git a/build/wp8/LibLinphoneTester-native/LibLinphoneTester-native.vcxproj b/build/wp8/LibLinphoneTester-native/LibLinphoneTester-native.vcxproj
index 424044515..021ab6328 100644
--- a/build/wp8/LibLinphoneTester-native/LibLinphoneTester-native.vcxproj
+++ b/build/wp8/LibLinphoneTester-native/LibLinphoneTester-native.vcxproj
@@ -100,11 +100,13 @@
+
+
true
@@ -153,4 +155,4 @@
-
\ No newline at end of file
+
diff --git a/build/wp8/version.bat b/build/wp8/version.bat
new file mode 100644
index 000000000..55ee42831
--- /dev/null
+++ b/build/wp8/version.bat
@@ -0,0 +1,22 @@
+@ECHO off
+
+SET gitlog=
+FOR /f "delims=" %%a IN ('git log -1 "--pretty=format:%%H" ../../configure.ac') DO SET gitlog=%%a
+
+IF [%gitlog%] == [] GOTO UnknownGitVersion
+
+FOR /f "delims=" %%a IN ('git describe --always') DO SET gitdescribe=%%a
+GOTO End
+
+:UnknownGitVersion
+SET gitdescribe=unknown
+
+:End
+ECHO #define LIBLINPHONE_GIT_VERSION "%gitdescribe%" > liblinphone_gitversion.h
+
+
+FOR /F "delims=" %%a IN ('findstr /B AC_INIT ..\..\configure.ac') DO (
+ FOR /F "tokens=1,2,3 delims=[,]" %%1 IN ("%%a") DO (
+ ECHO #define LIBLINPHONE_VERSION "%%3" > config.h
+ )
+)
diff --git a/build/wp8/zlib/zconf.h b/build/wp8/zlib/zconf.h
new file mode 100644
index 000000000..a3a6b54fc
--- /dev/null
+++ b/build/wp8/zlib/zconf.h
@@ -0,0 +1,513 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-2013 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#ifndef ZCONF_H
+#define ZCONF_H
+/* #undef Z_PREFIX */
+#define Z_HAVE_UNISTD_H
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ * Even better than compiling with -DZ_PREFIX would be to use configure to set
+ * this permanently in zconf.h using "./configure --zprefix".
+ */
+#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */
+# define Z_PREFIX_SET
+
+/* all linked symbols */
+# define _dist_code z__dist_code
+# define _length_code z__length_code
+# define _tr_align z__tr_align
+# define _tr_flush_bits z__tr_flush_bits
+# define _tr_flush_block z__tr_flush_block
+# define _tr_init z__tr_init
+# define _tr_stored_block z__tr_stored_block
+# define _tr_tally z__tr_tally
+# define adler32 z_adler32
+# define adler32_combine z_adler32_combine
+# define adler32_combine64 z_adler32_combine64
+# ifndef Z_SOLO
+# define compress z_compress
+# define compress2 z_compress2
+# define compressBound z_compressBound
+# endif
+# define crc32 z_crc32
+# define crc32_combine z_crc32_combine
+# define crc32_combine64 z_crc32_combine64
+# define deflate z_deflate
+# define deflateBound z_deflateBound
+# define deflateCopy z_deflateCopy
+# define deflateEnd z_deflateEnd
+# define deflateInit2_ z_deflateInit2_
+# define deflateInit_ z_deflateInit_
+# define deflateParams z_deflateParams
+# define deflatePending z_deflatePending
+# define deflatePrime z_deflatePrime
+# define deflateReset z_deflateReset
+# define deflateResetKeep z_deflateResetKeep
+# define deflateSetDictionary z_deflateSetDictionary
+# define deflateSetHeader z_deflateSetHeader
+# define deflateTune z_deflateTune
+# define deflate_copyright z_deflate_copyright
+# define get_crc_table z_get_crc_table
+# ifndef Z_SOLO
+# define gz_error z_gz_error
+# define gz_intmax z_gz_intmax
+# define gz_strwinerror z_gz_strwinerror
+# define gzbuffer z_gzbuffer
+# define gzclearerr z_gzclearerr
+# define gzclose z_gzclose
+# define gzclose_r z_gzclose_r
+# define gzclose_w z_gzclose_w
+# define gzdirect z_gzdirect
+# define gzdopen z_gzdopen
+# define gzeof z_gzeof
+# define gzerror z_gzerror
+# define gzflush z_gzflush
+# define gzgetc z_gzgetc
+# define gzgetc_ z_gzgetc_
+# define gzgets z_gzgets
+# define gzoffset z_gzoffset
+# define gzoffset64 z_gzoffset64
+# define gzopen z_gzopen
+# define gzopen64 z_gzopen64
+# ifdef _WIN32
+# define gzopen_w z_gzopen_w
+# endif
+# define gzprintf z_gzprintf
+# define gzvprintf z_gzvprintf
+# define gzputc z_gzputc
+# define gzputs z_gzputs
+# define gzread z_gzread
+# define gzrewind z_gzrewind
+# define gzseek z_gzseek
+# define gzseek64 z_gzseek64
+# define gzsetparams z_gzsetparams
+# define gztell z_gztell
+# define gztell64 z_gztell64
+# define gzungetc z_gzungetc
+# define gzwrite z_gzwrite
+# endif
+# define inflate z_inflate
+# define inflateBack z_inflateBack
+# define inflateBackEnd z_inflateBackEnd
+# define inflateBackInit_ z_inflateBackInit_
+# define inflateCopy z_inflateCopy
+# define inflateEnd z_inflateEnd
+# define inflateGetHeader z_inflateGetHeader
+# define inflateInit2_ z_inflateInit2_
+# define inflateInit_ z_inflateInit_
+# define inflateMark z_inflateMark
+# define inflatePrime z_inflatePrime
+# define inflateReset z_inflateReset
+# define inflateReset2 z_inflateReset2
+# define inflateSetDictionary z_inflateSetDictionary
+# define inflateGetDictionary z_inflateGetDictionary
+# define inflateSync z_inflateSync
+# define inflateSyncPoint z_inflateSyncPoint
+# define inflateUndermine z_inflateUndermine
+# define inflateResetKeep z_inflateResetKeep
+# define inflate_copyright z_inflate_copyright
+# define inflate_fast z_inflate_fast
+# define inflate_table z_inflate_table
+# ifndef Z_SOLO
+# define uncompress z_uncompress
+# endif
+# define zError z_zError
+# ifndef Z_SOLO
+# define zcalloc z_zcalloc
+# define zcfree z_zcfree
+# endif
+# define zlibCompileFlags z_zlibCompileFlags
+# define zlibVersion z_zlibVersion
+
+/* all zlib typedefs in zlib.h and zconf.h */
+# define Byte z_Byte
+# define Bytef z_Bytef
+# define alloc_func z_alloc_func
+# define charf z_charf
+# define free_func z_free_func
+# ifndef Z_SOLO
+# define gzFile z_gzFile
+# endif
+# define gz_header z_gz_header
+# define gz_headerp z_gz_headerp
+# define in_func z_in_func
+# define intf z_intf
+# define out_func z_out_func
+# define uInt z_uInt
+# define uIntf z_uIntf
+# define uLong z_uLong
+# define uLongf z_uLongf
+# define voidp z_voidp
+# define voidpc z_voidpc
+# define voidpf z_voidpf
+
+/* all zlib structs in zlib.h and zconf.h */
+# define gz_header_s z_gz_header_s
+# define internal_state z_internal_state
+
+#endif
+
+#if defined(__MSDOS__) && !defined(MSDOS)
+# define MSDOS
+#endif
+#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
+# define OS2
+#endif
+#if defined(_WINDOWS) && !defined(WINDOWS)
+# define WINDOWS
+#endif
+#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
+# ifndef WIN32
+# define WIN32
+# endif
+#endif
+#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
+# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
+# ifndef SYS16BIT
+# define SYS16BIT
+# endif
+# endif
+#endif
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#ifdef SYS16BIT
+# define MAXSEG_64K
+#endif
+#ifdef MSDOS
+# define UNALIGNED_OK
+#endif
+
+#ifdef __STDC_VERSION__
+# ifndef STDC
+# define STDC
+# endif
+# if __STDC_VERSION__ >= 199901L
+# ifndef STDC99
+# define STDC99
+# endif
+# endif
+#endif
+#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
+# define STDC
+#endif
+
+#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */
+# define STDC
+#endif
+
+#ifndef STDC
+# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+# define const /* note: need a more gentle solution here */
+# endif
+#endif
+
+#if defined(ZLIB_CONST) && !defined(z_const)
+# define z_const const
+#else
+# define z_const
+#endif
+
+/* Some Mac compilers merge all .h files incorrectly: */
+#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
+# define NO_DUMMY_DECL
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+# ifdef MAXSEG_64K
+# define MAX_MEM_LEVEL 8
+# else
+# define MAX_MEM_LEVEL 9
+# endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+# define MAX_WBITS 15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+ (1 << (windowBits+2)) + (1 << (memLevel+9))
+ that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+ make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+ The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+ /* Type declarations */
+
+#ifndef OF /* function prototypes */
+# ifdef STDC
+# define OF(args) args
+# else
+# define OF(args) ()
+# endif
+#endif
+
+#ifndef Z_ARG /* function prototypes for stdarg */
+# if defined(STDC) || defined(Z_HAVE_STDARG_H)
+# define Z_ARG(args) args
+# else
+# define Z_ARG(args) ()
+# endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#ifdef SYS16BIT
+# if defined(M_I86SM) || defined(M_I86MM)
+ /* MSC small or medium model */
+# define SMALL_MEDIUM
+# ifdef _MSC_VER
+# define FAR _far
+# else
+# define FAR far
+# endif
+# endif
+# if (defined(__SMALL__) || defined(__MEDIUM__))
+ /* Turbo C small or medium model */
+# define SMALL_MEDIUM
+# ifdef __BORLANDC__
+# define FAR _far
+# else
+# define FAR far
+# endif
+# endif
+#endif
+
+#if defined(WINDOWS) || defined(WIN32)
+ /* If building or using zlib as a DLL, define ZLIB_DLL.
+ * This is not mandatory, but it offers a little performance increase.
+ */
+# ifdef ZLIB_DLL
+# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
+# ifdef ZLIB_INTERNAL
+# define ZEXTERN extern __declspec(dllexport)
+# else
+# define ZEXTERN extern __declspec(dllimport)
+# endif
+# endif
+# endif /* ZLIB_DLL */
+ /* If building or using zlib with the WINAPI/WINAPIV calling convention,
+ * define ZLIB_WINAPI.
+ * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
+ */
+# ifdef ZLIB_WINAPI
+# ifdef FAR
+# undef FAR
+# endif
+# include
+ /* No need for _export, use ZLIB.DEF instead. */
+ /* For complete Windows compatibility, use WINAPI, not __stdcall. */
+# define ZEXPORT WINAPI
+# ifdef WIN32
+# define ZEXPORTVA WINAPIV
+# else
+# define ZEXPORTVA FAR CDECL
+# endif
+# endif
+#endif
+
+#if defined (__BEOS__)
+# ifdef ZLIB_DLL
+# ifdef ZLIB_INTERNAL
+# define ZEXPORT __declspec(dllexport)
+# define ZEXPORTVA __declspec(dllexport)
+# else
+# define ZEXPORT __declspec(dllimport)
+# define ZEXPORTVA __declspec(dllimport)
+# endif
+# endif
+#endif
+
+#ifndef ZEXTERN
+# define ZEXTERN extern
+#endif
+#ifndef ZEXPORT
+# define ZEXPORT
+#endif
+#ifndef ZEXPORTVA
+# define ZEXPORTVA
+#endif
+
+#ifndef FAR
+# define FAR
+#endif
+
+#if !defined(__MACTYPES__)
+typedef unsigned char Byte; /* 8 bits */
+#endif
+typedef unsigned int uInt; /* 16 bits or more */
+typedef unsigned long uLong; /* 32 bits or more */
+
+#ifdef SMALL_MEDIUM
+ /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
+# define Bytef Byte FAR
+#else
+ typedef Byte FAR Bytef;
+#endif
+typedef char FAR charf;
+typedef int FAR intf;
+typedef uInt FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+ typedef void const *voidpc;
+ typedef void FAR *voidpf;
+ typedef void *voidp;
+#else
+ typedef Byte const *voidpc;
+ typedef Byte FAR *voidpf;
+ typedef Byte *voidp;
+#endif
+
+#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC)
+# include
+# if (UINT_MAX == 0xffffffffUL)
+# define Z_U4 unsigned
+# elif (ULONG_MAX == 0xffffffffUL)
+# define Z_U4 unsigned long
+# elif (USHRT_MAX == 0xffffffffUL)
+# define Z_U4 unsigned short
+# endif
+#endif
+
+#ifdef Z_U4
+ typedef Z_U4 z_crc_t;
+#else
+ typedef unsigned long z_crc_t;
+#endif
+
+#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */
+# define Z_HAVE_UNISTD_H
+#endif
+
+#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */
+# define Z_HAVE_STDARG_H
+#endif
+
+#ifdef STDC
+# ifndef Z_SOLO
+# include /* for off_t */
+# endif
+#endif
+
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
+# ifndef Z_SOLO
+# include /* for va_list */
+# endif
+#endif
+
+#ifdef _WIN32
+# ifndef Z_SOLO
+# include /* for wchar_t */
+# endif
+#endif
+
+/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and
+ * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even
+ * though the former does not conform to the LFS document), but considering
+ * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as
+ * equivalently requesting no 64-bit operations
+ */
+#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1
+# undef _LARGEFILE64_SOURCE
+#endif
+
+#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H)
+# define Z_HAVE_UNISTD_H
+#endif
+#ifndef Z_SOLO
+# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)
+# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */
+# ifdef VMS
+# include /* for off_t */
+# endif
+# ifndef z_off_t
+# define z_off_t off_t
+# endif
+# endif
+#endif
+
+#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0
+# define Z_LFS64
+#endif
+
+#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64)
+# define Z_LARGE64
+#endif
+
+#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64)
+# define Z_WANT64
+#endif
+
+#if !defined(SEEK_SET) && !defined(Z_SOLO)
+# define SEEK_SET 0 /* Seek from beginning of file. */
+# define SEEK_CUR 1 /* Seek from current position. */
+# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
+#endif
+
+#ifndef z_off_t
+# define z_off_t long
+#endif
+
+#if !defined(_WIN32) && defined(Z_LARGE64)
+# define z_off64_t off64_t
+#else
+# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO)
+# define z_off64_t __int64
+# else
+# define z_off64_t z_off_t
+# endif
+#endif
+
+/* MVS linker does not support external names larger than 8 bytes */
+#if defined(__MVS__)
+ #pragma map(deflateInit_,"DEIN")
+ #pragma map(deflateInit2_,"DEIN2")
+ #pragma map(deflateEnd,"DEEND")
+ #pragma map(deflateBound,"DEBND")
+ #pragma map(inflateInit_,"ININ")
+ #pragma map(inflateInit2_,"ININ2")
+ #pragma map(inflateEnd,"INEND")
+ #pragma map(inflateSync,"INSY")
+ #pragma map(inflateSetDictionary,"INSEDI")
+ #pragma map(compressBound,"CMBND")
+ #pragma map(inflate_table,"INTABL")
+ #pragma map(inflate_fast,"INFA")
+ #pragma map(inflate_copyright,"INCOPY")
+#endif
+
+#endif /* ZCONF_H */
diff --git a/build/wp8/zlib/zlib.sln b/build/wp8/zlib/zlib.sln
new file mode 100644
index 000000000..97b0cc6a9
--- /dev/null
+++ b/build/wp8/zlib/zlib.sln
@@ -0,0 +1,26 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Express 2012 for Windows Phone
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "zlib.vcxproj", "{7AFAC3BB-D97B-4578-B9FE-5E1D2B94EA2F}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|ARM = Debug|ARM
+ Debug|Win32 = Debug|Win32
+ Release|ARM = Release|ARM
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {7AFAC3BB-D97B-4578-B9FE-5E1D2B94EA2F}.Debug|ARM.ActiveCfg = Debug|ARM
+ {7AFAC3BB-D97B-4578-B9FE-5E1D2B94EA2F}.Debug|ARM.Build.0 = Debug|ARM
+ {7AFAC3BB-D97B-4578-B9FE-5E1D2B94EA2F}.Debug|Win32.ActiveCfg = Debug|Win32
+ {7AFAC3BB-D97B-4578-B9FE-5E1D2B94EA2F}.Debug|Win32.Build.0 = Debug|Win32
+ {7AFAC3BB-D97B-4578-B9FE-5E1D2B94EA2F}.Release|ARM.ActiveCfg = Release|ARM
+ {7AFAC3BB-D97B-4578-B9FE-5E1D2B94EA2F}.Release|ARM.Build.0 = Release|ARM
+ {7AFAC3BB-D97B-4578-B9FE-5E1D2B94EA2F}.Release|Win32.ActiveCfg = Release|Win32
+ {7AFAC3BB-D97B-4578-B9FE-5E1D2B94EA2F}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/build/wp8/zlib/zlib.vcxproj b/build/wp8/zlib/zlib.vcxproj
new file mode 100644
index 000000000..34c9aa46f
--- /dev/null
+++ b/build/wp8/zlib/zlib.vcxproj
@@ -0,0 +1,135 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ ARM
+
+
+ Release
+ Win32
+
+
+ Release
+ ARM
+
+
+
+ {7afac3bb-d97b-4578-b9fe-5e1d2b94ea2f}
+ zlib
+ en-US
+ 11.0
+
+
+
+ DynamicLibrary
+ true
+ v110_wp80
+ false
+
+
+ DynamicLibrary
+ false
+ true
+ v110_wp80
+ false
+
+
+
+
+
+
+
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(SolutionDir)$(Platform)\$(Configuration)\$(TargetName)\
+
+
+ false
+
+
+
+ Level4
+ $(ProjectDir);$(ProjectDir)..\..\..\..\zlib;%(AdditionalIncludeDirectories)
+ _WIN32;_WINDLL;_USRDLL;_CRT_SECURE_NO_WARNINGS;UNICODE;%(PreprocessorDefinitions)
+ Default
+ NotUsing
+ false
+ $(WindowsSDK_MetadataPath);$(AdditionalUsingDirectories)
+
+
+ Console
+ false
+ false
+ $(TargetDir)$(TargetName).lib
+ Ws2_32.lib;%(AdditionalDependencies)
+ $(ProjectDir)..\..\..\..\zlib\win32\zlib.def
+
+
+
+
+ _DEBUG;%(PreprocessorDefinitions)
+
+
+ true
+
+
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+ MaxSpeed
+ true
+ true
+ true
+
+
+ false
+
+
+
+
+ true
+
+
+ true
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/config.h.cmake b/config.h.cmake
index aa49b3b98..f348cf3f9 100644
--- a/config.h.cmake
+++ b/config.h.cmake
@@ -24,6 +24,7 @@
#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}"
diff --git a/configure.ac b/configure.ac
index 6d295b694..02452ce7c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -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.
@@ -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`
@@ -794,13 +809,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"
@@ -894,11 +909,11 @@ dnl ##################################################
dnl # Check for doxygen
dnl ##################################################
-AC_PATH_PROG(DOXYGEN,doxygen,false)
-AM_CONDITIONAL(HAVE_DOXYGEN, test $DOXYGEN != false)
+AC_CHECK_PROG(DOXYGEN,doxygen,doxygen,false)
+AM_CONDITIONAL(HAVE_DOXYGEN, test "$DOXYGEN" != "false")
-AC_CONFIG_FILES([
+AC_CONFIG_FILES([
Makefile
build/Makefile
build/macos/Makefile
diff --git a/console/Makefile.am b/console/Makefile.am
index 314f5d612..482948329 100644
--- a/console/Makefile.am
+++ b/console/Makefile.am
@@ -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) \
diff --git a/console/commands.c b/console/commands.c
index f0b44bdd5..9f6d0c1c2 100644
--- a/console/commands.c
+++ b/console/commands.c
@@ -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;
}
@@ -1600,7 +1601,7 @@ linphonec_proxy_add(LinphoneCore *lc)
*/
if ( enable_register==TRUE )
{
- long int expires=0;
+ int expires=0;
while (1)
{
char *input=linphonec_readline("Specify register expiration time"
@@ -1612,13 +1613,8 @@ linphonec_proxy_add(LinphoneCore *lc)
return;
}
- expires=strtol(input, (char **)NULL, 10);
- if ( expires == LONG_MIN || expires == LONG_MAX )
- {
- linphonec_out("Invalid value: %s\n", strerror(errno));
- free(input);
- continue;
- }
+ expires=atoi(input);
+ if (expires==0) expires=600;
linphone_proxy_config_set_expires(cfg, expires);
linphonec_out("Expiration: %d seconds\n", linphone_proxy_config_get_expires (cfg));
@@ -2441,8 +2437,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;
diff --git a/console/linphonec.c b/console/linphonec.c
index ff16e1387..439702b85 100644
--- a/console/linphonec.c
+++ b/console/linphonec.c
@@ -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);
@@ -500,7 +500,6 @@ static void *pipe_thread(void*p){
}
static void start_pipe_reader(void){
- ms_mutex_init(&prompt_mutex,NULL);
pipe_reader_run=TRUE;
ortp_thread_create(&pipe_reader_th,NULL,pipe_thread,NULL);
}
@@ -536,6 +535,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 +546,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;
-
- if (PeekMessage(&msg, NULL, 0, 0,1)) {
- TranslateMessage(&msg);
- DispatchMessage(&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);
+ }
}
#else
usleep(20000);
@@ -802,6 +804,7 @@ linphonec_finish(int exit_status)
if (mylogfile != NULL && mylogfile != stdout)
{
fclose (mylogfile);
+ mylogfile=stdout;
}
printf("\n");
exit(exit_status);
@@ -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);
diff --git a/console/shell.c b/console/shell.c
index bfc758bf8..016992397 100644
--- a/console/shell.c
+++ b/console/shell.c
@@ -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,
diff --git a/coreapi/CMakeLists.txt b/coreapi/CMakeLists.txt
index 2be82be73..8ed8185ab 100644
--- a/coreapi/CMakeLists.txt
+++ b/coreapi/CMakeLists.txt
@@ -42,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
@@ -51,13 +53,13 @@ set(SOURCE_FILES
info.c
linphonecall.c
linphonecore.c
- linphone_tunnel_stubs.c
linphone_tunnel_config.c
lpconfig.c
lsd.c
message_storage.c
misc.c
offeranswer.c
+ player.c
presence.c
proxy.c
quality_reporting.c
@@ -86,6 +88,8 @@ if(ENABLE_TUNNEL)
TunnelManager.cc
)
add_definitions(-DTUNNEL_ENABLED)
+else()
+ list(APPEND SOURCE_FILES linphone_tunnel_stubs.c)
endif()
set(GENERATED_SOURCE_FILES
@@ -94,7 +98,7 @@ set(GENERATED_SOURCE_FILES
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} -DOUTPUT_DIR=${CMAKE_CURRENT_BINARY_DIR} -P ${CMAKE_CURRENT_SOURCE_DIR}/gitversion.cmake)
+ 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(
-DIN_LINPHONE
@@ -113,6 +117,12 @@ set(LIBS
${MS2_LIBRARIES}
${XML2_LIBRARIES}
)
+if(ENABLE_TUNNEL)
+ list(APPEND LIBS ${TUNNEL_LIBRARIES})
+endif()
+if(WIN32)
+ list(APPEND LIBS shlwapi)
+endif()
if(ENABLE_STATIC)
add_library(linphone STATIC ${SOURCE_FILES} ${GENERATED_SOURCE_FILES})
@@ -139,7 +149,20 @@ install(TARGETS linphone
)
-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
diff --git a/coreapi/Makefile.am b/coreapi/Makefile.am
index 5b4460c79..2bb8498d9 100644
--- a/coreapi/Makefile.am
+++ b/coreapi/Makefile.am
@@ -6,10 +6,10 @@ 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,
+## 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 $(top_srcdir)/configure.ac)
+GITLOG=$(shell git log -1 --pretty=format:%H $(top_srcdir)/configure.ac)
ECHO=/bin/echo
@@ -24,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
@@ -59,12 +59,16 @@ liblinphone_la_SOURCES=\
lpc2xml.c \
remote_provisioning.c \
quality_reporting.c quality_reporting.h\
+ call_log.c \
+ call_params.c \
+ player.c \
+ localplayer.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 \
@@ -79,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
@@ -138,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) \
@@ -155,15 +160,16 @@ 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:
diff --git a/coreapi/TunnelManager.cc b/coreapi/TunnelManager.cc
index 2bc8cd3e0..77e26fb1b 100644
--- a/coreapi/TunnelManager.cc
+++ b/coreapi/TunnelManager.cc
@@ -1,7 +1,7 @@
/*
* C Implementation: tunnel
*
- * Description:
+ * Description:
*
*
* Author: Simon Morlat , (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
#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,30 +90,26 @@ 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) {
- mTunnelClient = new TunnelClient();
- mTunnelClient->setCallback((StateCallback)tunnelCallback,this);
- list::iterator it;
- for(it=mServerAddrs.begin();it!=mServerAddrs.end();++it){
- const ServerAddr &addr=*it;
- mTunnelClient->addServer(addr.mAddr.c_str(), addr.mPort);
- }
- mTunnelClient->setHttpProxy(mHttpProxyHost.c_str(), mHttpProxyPort, mHttpUserName.c_str(), mHttpPasswd.c_str());
+void TunnelManager::startClient() {
+ ms_message("TunnelManager: Starting tunnel client");
+ mTunnelClient = new TunnelClient();
+ mTunnelClient->setCallback((TunnelClientController::StateCallback)tunnelCallback,this);
+ list::iterator it;
+ for(it=mServerAddrs.begin();it!=mServerAddrs.end();++it){
+ const ServerAddr &addr=*it;
+ mTunnelClient->addServer(addr.mAddr.c_str(), addr.mPort);
}
+ mTunnelClient->setHttpProxy(mHttpProxyHost.c_str(), mHttpProxyPort, mHttpUserName.c_str(), mHttpPasswd.c_str());
mTunnelClient->start();
}
-bool TunnelManager::isStarted() {
- return mTunnelClient != 0 && mTunnelClient->isStarted();
-}
-
-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 +127,19 @@ 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),
+ mState(disabled),
+ mTunnelizeSipPackets(true),
+ mTunnelClient(NULL),
+ mHttpProxyPort(0),
+ mVTable(NULL)
+{
linphone_core_add_iterate_hook(mCore,(LinphoneCoreIterateHook)sOnIterate,this);
mTransportFactories.audio_rtcp_func=sCreateRtpTransport;
mTransportFactories.audio_rtcp_func_data=this;
@@ -153,104 +149,103 @@ TunnelManager::TunnelManager(LinphoneCore* lc) :TunnelClientController()
mTransportFactories.video_rtcp_func_data=this;
mTransportFactories.video_rtp_func=sCreateRtpTransport;
mTransportFactories.video_rtp_func_data=this;
+ mVTable = linphone_core_v_table_new();
+ mVTable->network_reachable = networkReachableCb;
+ linphone_core_add_listener(mCore, mVTable);
}
TunnelManager::~TunnelManager(){
- stopClient();
-}
-
-void TunnelManager::stopClient(){
- sal_disable_tunnel(mCore->sal);
- if (mTunnelClient){
- delete mTunnelClient;
- mTunnelClient=NULL;
+ for(UdpMirrorClientList::iterator udpMirror = mUdpMirrorClients.begin(); udpMirror != mUdpMirrorClients.end(); udpMirror++) {
+ udpMirror->stop();
}
+ if(mTunnelClient) delete mTunnelClient;
+ linphone_core_remove_listener(mCore, mVTable);
+ linphone_core_v_table_destroy(mVTable);
}
-void TunnelManager::processTunnelEvent(const Event &ev){
+void TunnelManager::doRegistration(){
LinphoneProxyConfig* lProxy;
linphone_core_get_default_proxy(mCore, &lProxy);
+ if (lProxy) {
+ ms_message("TunnelManager: New registration");
+ lProxy->commit = TRUE;
+ }
+}
- if (mEnabled && mTunnelClient->isReady()){
- 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);
+void TunnelManager::doUnregistration() {
+ LinphoneProxyConfig *lProxy;
+ linphone_core_get_default_proxy(mCore, &lProxy);
+ if(lProxy) {
+ _linphone_proxy_config_unregister(lProxy);
+ }
+}
- //register
- if (lProxy) {
- linphone_proxy_config_refresh_register(lProxy);
+void TunnelManager::processTunnelEvent(const Event &ev){
+ if (ev.mData.mConnected){
+ ms_message("TunnelManager: tunnel is connected");
+ if(mState == connecting) {
+ linphone_core_set_rtp_transport_factories(mCore,&mTransportFactories);
+ if(mTunnelizeSipPackets) {
+ doUnregistration();
+ sal_enable_tunnel(mCore->sal, mTunnelClient);
+ doRegistration();
+ }
+ mState = ready;
}
- mReady=true;
- }else if (mEnabled && !mTunnelClient->isReady()){
- /* we got disconnected from the tunnel */
- mReady=false;
+ } else {
+ ms_error("TunnelManager: tunnel has been disconnected");
}
}
-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;
+void TunnelManager::setMode(LinphoneTunnelMode mode) {
+ if(mMode == mode) return;
+ if((mode==LinphoneTunnelModeDisable && mState==disabled)
+ || (mode==LinphoneTunnelModeEnable && mState==ready)) {
+ return;
+ }
+ ms_message("TunnelManager: switching mode from %s to %s",
+ tunnel_mode_to_string(mMode),
+ tunnel_mode_to_string(mode));
+ switch(mode) {
+ case LinphoneTunnelModeEnable:
+ if(mState == disabled) {
+ startClient();
+ mState = connecting;
+ mMode = mode;
+ } else {
+ ms_error("TunnelManager: could not change mode. Bad state");
+ }
+ break;
+ case LinphoneTunnelModeDisable:
+ if(mState == ready) {
+ linphone_core_set_rtp_transport_factories(mCore,NULL);
+ if(mTunnelizeSipPackets) {
+ doUnregistration();
+ sal_disable_tunnel(mCore->sal);
}
- i++;
- }while(linphone_proxy_config_get_state(lProxy)!=LinphoneRegistrationCleared);
- }
-}
-
-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
- 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);
+ delete mTunnelClient;
+ mTunnelClient=NULL;
+ if(mTunnelizeSipPackets) {
+ doRegistration();
+ }
+ mState = disabled;
+ mMode = mode;
+ } else {
+ ms_error("TunnelManager: could not change mode. Bad state");
}
-
+ break;
+ case LinphoneTunnelModeAuto:
+ if(mState == disabled || mState == ready) {
+ if(startAutoDetection()) {
+ mState = autodetecting;
+ mMode = mode;
+ }
+ } else {
+ ms_error("TunnelManager: could not change mode. Bad state");
+ }
+ break;
+ default:
+ ms_error("TunnelManager::setMode(): invalid mode (%d)", mode);
}
}
@@ -320,30 +315,39 @@ 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(mState != autodetecting) return;
if (ev.mData.mHaveUdp) {
- LOGI("Tunnel is not required, disabling");
- enable(false);
- mAutoDetectStarted = false;
+ ms_message("TunnelManager: UDP mirror test succeed");
+ if(mTunnelClient) {
+ if(mTunnelizeSipPackets) doUnregistration();
+ delete mTunnelClient;
+ mTunnelClient = NULL;
+ if(mTunnelizeSipPackets) doRegistration();
+ }
+ mState = disabled;
} else {
+ ms_message("TunnelManager: UDP mirror test failed");
mCurrentUdpMirrorClient++;
if (mCurrentUdpMirrorClient !=mUdpMirrorClients.end()) {
- // enable tunnel but also try backup server
- LOGI("Tunnel is required, enabling; Trying backup udp mirror");
-
+ ms_message("TunnelManager: trying another UDP mirror");
UdpMirrorClient &lUdpMirrorClient=*mCurrentUdpMirrorClient;
lUdpMirrorClient.start(TunnelManager::sUdpMirrorClientCallback,(void*)this);
} else {
- LOGI("Tunnel is required, enabling; no backup udp mirror available");
- mAutoDetectStarted = false;
+ ms_message("TunnelManager: all UDP mirror tests failed");
+ if(mTunnelClient==NULL) {
+ startClient();
+ mState = connecting;
+ } else {
+ mState = ready;
+ }
}
- enable(true);
}
}
@@ -361,21 +365,24 @@ void TunnelManager::sUdpMirrorClientCallback(bool isUdpAvailable, void* data) {
thiz->postEvent(ev);
}
-void TunnelManager::autoDetect() {
- // first check if udp mirrors was provisionned
- if (mUdpMirrorClients.empty()) {
- LOGE("No UDP mirror server configured aborting auto detection");
- return;
+void TunnelManager::networkReachableCb(LinphoneCore *lc, bool_t reachable) {
+ TunnelManager *tunnel = bcTunnel(linphone_core_get_tunnel(lc));
+ if(reachable && tunnel->getMode() == LinphoneTunnelModeAuto && tunnel->mState != connecting && tunnel->mState != autodetecting) {
+ tunnel->startAutoDetection();
+ tunnel->mState = autodetecting;
}
- if (mAutoDetectStarted) {
- LOGE("auto detection already in progress, restarting");
- (*mCurrentUdpMirrorClient).stop();
+}
+
+bool TunnelManager::startAutoDetection() {
+ if (mUdpMirrorClients.empty()) {
+ ms_error("TunnelManager: No UDP mirror server configured aborting auto detection");
+ return false;
}
- mAutoDetectStarted=true;
- mCurrentUdpMirrorClient =mUdpMirrorClients.begin();
+ ms_message("TunnelManager: Starting auto-detection");
+ mCurrentUdpMirrorClient = mUdpMirrorClients.begin();
UdpMirrorClient &lUdpMirrorClient=*mCurrentUdpMirrorClient;
lUdpMirrorClient.start(TunnelManager::sUdpMirrorClientCallback,(void*)this);
-
+ return true;
}
void TunnelManager::setHttpProxyAuthInfo(const char* username,const char* passwd) {
@@ -384,6 +391,14 @@ void TunnelManager::setHttpProxyAuthInfo(const char* username,const char* passwd
if (mTunnelClient) mTunnelClient->setHttpProxyAuthInfo(username,passwd);
}
+void TunnelManager::tunnelizeSipPackets(bool enable){
+ mTunnelizeSipPackets = enable;
+}
+
+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 +407,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;
}
diff --git a/coreapi/TunnelManager.hh b/coreapi/TunnelManager.hh
index 9ca29ad86..58475aab3 100644
--- a/coreapi/TunnelManager.hh
+++ b/coreapi/TunnelManager.hh
@@ -1,7 +1,7 @@
/*
* C Implementation: tunnel
*
- * Description:
+ * Description:
*
*
*
@@ -12,35 +12,35 @@
#define __TUNNEL_CLIENT_MANAGER_H__
#include
#include
-#include "tunnel/client.hh"
+#include
+#include
#include "linphonecore.h"
+#include "linphone_tunnel.h"
#ifndef USE_BELLESIP
extern "C" {
- #include "eXosip2/eXosip_transport_hook.h"
+ #include
}
#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.
- *
In case of success, the tunnel is automatically turned off. Otherwise, if no udp commmunication is feasible, tunnel mode is turned on.
- *
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,25 +96,60 @@ 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 State {
+ disabled,
+ connecting,
+ ready,
+ autodetecting
+ };
+
enum EventType{
UdpMirrorClientEvent,
TunnelEvent,
@@ -146,8 +162,6 @@ class UdpMirrorClient;
}mData;
};
typedef std::list 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 +170,39 @@ class UdpMirrorClient;
static void tunnelCallback(bool connected, TunnelManager *zis);
static void sOnIterate(TunnelManager *zis);
static void sUdpMirrorClientCallback(bool result, void* data);
- void waitUnRegistration();
+ static void networkReachableCb(LinphoneCore *lc, bool_t reachable);
+
+ private:
+ void onIterate();
+ void doRegistration();
+ void doUnregistration();
+ void startClient();
+ bool startAutoDetection();
void processTunnelEvent(const Event &ev);
void processUdpMirrorEvent(const Event &ev);
void postEvent(const Event &ev);
+
+ private:
LinphoneCore* mCore;
- LCSipTransports mRegularTransport;
-#ifndef USE_BELLESIP
- TunnelSocket *mSipSocket;
- eXosip_transport_hooks_t mExosipTransport;
-#endif
- StateCallback mCallback;
- void * mCallbackData;
- bool mEnabled;
- std::queue mEvq;
- std::list mServerAddrs;
- UdpMirrorClientList mUdpMirrorClients;
- UdpMirrorClientList::iterator mCurrentUdpMirrorClient;
+ LinphoneTunnelMode mMode;
+ State mState;
+ bool mTunnelizeSipPackets;
TunnelClient* mTunnelClient;
- void stopClient();
- Mutex mMutex;
- static Mutex sMutex;
- bool mAutoDetectStarted;
- bool mReady;
- LinphoneRtpTransportFactories mTransportFactories;
std::string mHttpUserName;
std::string mHttpPasswd;
std::string mHttpProxyHost;
int mHttpProxyPort;
- LinphoneFirewallPolicy mPreviousFirewallPolicy;
+ LinphoneCoreVTable *mVTable;
+ std::list mServerAddrs;
+ UdpMirrorClientList mUdpMirrorClients;
+ UdpMirrorClientList::iterator mCurrentUdpMirrorClient;
+ LinphoneRtpTransportFactories mTransportFactories;
+ Mutex mMutex;
+ std::queue mEvq;
+#ifndef USE_BELLESIP
+ TunnelSocket *mSipSocket;
+ eXosip_transport_hooks_t mExosipTransport;
+#endif
};
/**
diff --git a/coreapi/authentication.c b/coreapi/authentication.c
index 59b3ea1b5..de7248316 100644
--- a/coreapi/authentication.c
+++ b/coreapi/authentication.c
@@ -378,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;
diff --git a/coreapi/bellesip_sal/sal_impl.c b/coreapi/bellesip_sal/sal_impl.c
index ab7714fa9..6c2e84483 100644
--- a/coreapi/bellesip_sal/sal_impl.c
+++ b/coreapi/bellesip_sal/sal_impl.c
@@ -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);
+ }
}
}
@@ -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;
}
diff --git a/coreapi/bellesip_sal/sal_impl.h b/coreapi/bellesip_sal/sal_impl.h
index a20150de2..07124feb3 100644
--- a/coreapi/bellesip_sal/sal_impl.h
+++ b/coreapi/bellesip_sal/sal_impl.h
@@ -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_ */
diff --git a/coreapi/bellesip_sal/sal_op_call.c b/coreapi/bellesip_sal/sal_op_call.c
index 26bbdb038..fbed2cf18 100644
--- a/coreapi/bellesip_sal/sal_op_call.c
+++ b/coreapi/bellesip_sal/sal_op_call.c
@@ -75,22 +75,33 @@ static void sdp_process(SalOp *h){
static int set_sdp(belle_sip_message_t *msg,belle_sdp_session_description_t* session_desc) {
belle_sip_header_content_type_t* content_type ;
belle_sip_header_content_length_t* content_length;
- belle_sip_error_code error = BELLE_SIP_OK;
+ belle_sip_error_code error = BELLE_SIP_BUFFER_OVERFLOW;
size_t length = 0;
- char buff[2048];
if (session_desc) {
+ size_t bufLen = 2048;
+ size_t hardlimit = 16*1024; /* 16k SDP limit seems reasonable */
+ char* buff = belle_sip_malloc(bufLen);
content_type = belle_sip_header_content_type_create("application","sdp");
- error = belle_sip_object_marshal(BELLE_SIP_OBJECT(session_desc),buff,sizeof(buff),&length);
- if (error != BELLE_SIP_OK) {
- ms_error("Buffer too small or sdp too big");
+
+ /* try to marshal the description. This could go higher than 2k so we iterate */
+ while( error != BELLE_SIP_OK && bufLen <= hardlimit && buff != NULL){
+ error = belle_sip_object_marshal(BELLE_SIP_OBJECT(session_desc),buff,bufLen,&length);
+ if( error != BELLE_SIP_OK ){
+ bufLen *= 2;
+ buff = belle_sip_realloc(buff,bufLen);
+ }
+ }
+ /* give up if hard limit reached */
+ if (error != BELLE_SIP_OK || buff == NULL) {
+ ms_error("Buffer too small (%d) or not enough memory, giving up SDP", (int)bufLen);
return -1;
}
- content_length= belle_sip_header_content_length_create(length);
+ content_length = belle_sip_header_content_length_create(length);
belle_sip_message_add_header(msg,BELLE_SIP_HEADER(content_type));
belle_sip_message_add_header(msg,BELLE_SIP_HEADER(content_length));
- belle_sip_message_set_body(msg,buff,length);
+ belle_sip_message_assign_body(msg,buff,length);
return 0;
} else {
return -1;
@@ -185,6 +196,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 +205,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 +250,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 +279,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:
@@ -314,6 +329,8 @@ static void call_process_transaction_terminated(void *user_ctx, const belle_sip_
belle_sip_server_transaction_t *server_transaction=belle_sip_transaction_terminated_event_get_server_transaction(event);
belle_sip_request_t* req;
belle_sip_response_t* resp;
+ bool_t release_call=FALSE;
+
if (client_transaction) {
req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction));
resp=belle_sip_transaction_get_response(BELLE_SIP_TRANSACTION(client_transaction));
@@ -324,9 +341,21 @@ static void call_process_transaction_terminated(void *user_ctx, const belle_sip_
if (op->state ==SalOpStateTerminating
&& strcmp("BYE",belle_sip_request_get_method(req))==0
&& (!resp || (belle_sip_response_get_status_code(resp) !=401
- && belle_sip_response_get_status_code(resp) !=407))) {
- if (op->dialog==NULL) call_set_released(op);
+ && belle_sip_response_get_status_code(resp) !=407))
+ && op->dialog==NULL) {
+ release_call=TRUE;
+ }
+ if (server_transaction){
+ if (op->pending_server_trans==server_transaction){
+ belle_sip_object_unref(op->pending_server_trans);
+ op->pending_server_trans=NULL;
+ }
+ if (op->pending_update_server_trans==server_transaction){
+ belle_sip_object_unref(op->pending_update_server_trans);
+ op->pending_update_server_trans=NULL;
+ }
}
+ if (release_call) call_set_released(op);
}
static void call_terminated(SalOp* op,belle_sip_server_transaction_t* server_transaction, belle_sip_request_t* request,int status_code) {
@@ -419,6 +448,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 +520,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 +552,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 +603,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);
@@ -627,7 +650,7 @@ static void sal_op_fill_invite(SalOp *op, belle_sip_request_t* invite) {
belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite),BELLE_SIP_HEADER(create_allow(op->base.root->enable_sip_update)));
if (op->base.root->session_expires!=0){
- belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite),belle_sip_header_create( "Session-expires", "200"));
+ belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite),belle_sip_header_create( "Session-expires", "600;refresher=uas"));
belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite),belle_sip_header_create( "Supported", "timer"));
}
if (op->base.local_media){
@@ -754,9 +777,10 @@ int sal_call_accept(SalOp*h){
}
belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_HEADER(create_allow(h->base.root->enable_sip_update)));
if (h->base.root->session_expires!=0){
- if (h->supports_session_timers) {
+/* if (h->supports_session_timers) {*/
belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),belle_sip_header_create("Supported", "timer"));
- }
+ belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),belle_sip_header_create( "Session-expires", "600;refresher=uac"));
+ /*}*/
}
if ((contact_header=sal_op_create_contact(h))) {
@@ -779,6 +803,7 @@ int sal_call_decline(SalOp *op, SalReason reason, const char *redirection /*opti
belle_sip_response_t* response;
belle_sip_header_contact_t* contact=NULL;
int status=sal_reason_to_sip_code(reason);
+ belle_sip_transaction_t *trans;
if (reason==SalReasonRedirect){
if (redirection!=NULL) {
@@ -790,19 +815,27 @@ int sal_call_decline(SalOp *op, SalReason reason, const char *redirection /*opti
ms_error("Cannot redirect to null");
}
}
- response = sal_op_create_response_from_request(op,belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_server_trans)),status);
+ trans=(belle_sip_transaction_t*)op->pending_server_trans;
+ if (!trans) trans=(belle_sip_transaction_t*)op->pending_update_server_trans;
+ if (!trans){
+ ms_error("sal_call_decline(): no pending transaction to decline.");
+ return -1;
+ }
+ response = sal_op_create_response_from_request(op,belle_sip_transaction_get_request(trans),status);
if (contact) belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_HEADER(contact));
- belle_sip_server_transaction_send_response(op->pending_server_trans,response);
+ belle_sip_server_transaction_send_response(BELLE_SIP_SERVER_TRANSACTION(trans),response);
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 {
diff --git a/coreapi/bellesip_sal/sal_op_impl.c b/coreapi/bellesip_sal/sal_op_impl.c
index e548cec43..ed18f52d0 100644
--- a/coreapi/bellesip_sal/sal_op_impl.c
+++ b/coreapi/bellesip_sal/sal_op_impl.c
@@ -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;
@@ -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;
}
diff --git a/coreapi/call_log.c b/coreapi/call_log.c
new file mode 100644
index 000000000..7ce488096
--- /dev/null
+++ b/coreapi/call_log.c
@@ -0,0 +1,300 @@
+/*
+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
+#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(;imax_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();
+ cl->connected_date_time=0;
+ 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
+);
diff --git a/coreapi/call_log.h b/coreapi/call_log.h
new file mode 100644
index 000000000..6a3ec8dab
--- /dev/null
+++ b/coreapi/call_log.h
@@ -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 since connected.
+ * @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__ */
diff --git a/coreapi/call_params.c b/coreapi/call_params.c
new file mode 100644
index 000000000..a48066169
--- /dev/null
+++ b/coreapi/call_params.c
@@ -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
+);
diff --git a/coreapi/call_params.h b/coreapi/call_params.h
new file mode 100644
index 000000000..9c942826b
--- /dev/null
+++ b/coreapi/call_params.h
@@ -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 javascript \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__ */
diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c
index c64a5d7e3..bb6b5b9fb 100644
--- a/coreapi/callbacks.c
+++ b/coreapi/callbacks.c
@@ -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){
@@ -152,7 +152,7 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia
ms_message("Network parameters have changed, update them.");
linphone_core_update_streams_destinations(lc, call, oldmd, new_md);
}
- if (md_changed & SAL_MEDIA_DESCRIPTION_CRYPTO_CHANGED) {
+ if (md_changed & SAL_MEDIA_DESCRIPTION_CRYPTO_KEYS_CHANGED) {
ms_message("Crypto parameters have changed, update them.");
linphone_call_update_crypto_parameters(call, oldmd, 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;
}
}
@@ -234,12 +234,12 @@ static bool_t already_a_call_pending(LinphoneCore *lc){
static void call_received(SalOp *h){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(h));
LinphoneCall *call;
- const char *from,*to;
char *alt_contact;
- LinphoneAddress *from_addr, *to_addr;
+ LinphoneAddress *from_addr=NULL;
+ LinphoneAddress *to_addr=NULL;
/*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);
@@ -272,10 +272,26 @@ static void call_received(SalOp *h){
sal_op_release(h);
return;
}
- from=sal_op_get_from(h);
- to=sal_op_get_to(h);
- from_addr=linphone_address_new(from);
- to_addr=linphone_address_new(to);
+ /*in some situation, better to trust the network rather than the UAC*/
+ if (lp_config_get_int(lc->config,"sip","call_logs_use_asserted_id_instead_of_from",0)) {
+ const char * p_asserted_id = sal_custom_header_find(sal_op_get_recv_custom_header(h),"P-Asserted-Identity");
+ LinphoneAddress *p_asserted_id_addr;
+ if (!p_asserted_id) {
+ ms_warning("No P-Asserted-Identity header found so cannot use it for op [%p] instead of from",h);
+ } else {
+ p_asserted_id_addr = linphone_address_new(p_asserted_id);
+ if (!p_asserted_id_addr) {
+ ms_warning("Unsupported P-Asserted-Identity header for op [%p] ",h);
+ } else {
+ ms_message("Using P-Asserted-Identity [%s] instead of from [%s] for op [%p]",p_asserted_id,sal_op_get_from(h),h);
+ from_addr=p_asserted_id_addr;
+ }
+ }
+ }
+
+ if (!from_addr)
+ from_addr=linphone_address_new(sal_op_get_from(h));
+ to_addr=linphone_address_new(sal_op_get_to(h));
if ((already_a_call_with_remote_address(lc,from_addr) && prevent_colliding_calls) || already_a_call_pending(lc)){
ms_warning("Receiving another call while one is ringing or initiated, refusing this one with busy message.");
@@ -285,14 +301,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 +329,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;inb_streams;++i){
if (!sal_stream_description_active(&cur_md->streams[i])) continue;
ref_stream=&cur_md->streams[i];
@@ -345,15 +361,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);
+ call->current_params->privacy=(LinphonePrivacyMask)sal_op_get_privacy(call->op);
+
+ linphone_core_notify_display_status(lc,_("Remote ringing."));
- if (lc->vtable.display_status)
- lc->vtable.display_status(lc,_("Remote ringing."));
-
md=sal_call_get_final_media_description(h);
if (md==NULL){
linphone_core_stop_dtmf_stream(lc);
@@ -364,11 +379,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 +393,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 +411,14 @@ 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;
-
+ bool_t update_state=TRUE;
+
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,51 +432,58 @@ 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);
-
- if (call->state==LinphoneCallOutgoingProgress ||
- 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);
+ call->params->has_video &= linphone_core_media_description_contains_video_stream(md);
+
+ switch (call->state){
+ case LinphoneCallOutgoingProgress:
+ case LinphoneCallOutgoingRinging:
+ case LinphoneCallOutgoingEarlyMedia:
+ linphone_call_set_state(call,LinphoneCallConnected,"Connected");
+ if (call->referer) linphone_core_notify_refer_state(lc,call->referer,call);
+ break;
+ case LinphoneCallEarlyUpdating:
+ linphone_call_set_state(call,call->prevstate,"Early update accepted");
+ update_state=FALSE;
+ break;
+ default:
+ break;
}
+
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);
}
linphone_core_update_streams (lc,call,md);
- linphone_call_set_state(call,LinphoneCallPaused,"Call paused");
+ if (update_state) linphone_call_set_state(call,LinphoneCallPaused,"Call paused");
if (call->refer_pending)
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);
}
linphone_core_update_streams (lc,call,md);
- linphone_call_set_state(call,LinphoneCallPausedByRemote,"Call paused by remote");
+ if (update_state) linphone_call_set_state(call,LinphoneCallPausedByRemote,"Call paused by remote");
}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,10 +493,9 @@ 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");
+ if (update_state) linphone_call_set_state(call, LinphoneCallStreamsRunning, "Streams running");
}
}else{
/*send a bye*/
@@ -503,81 +525,74 @@ 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_POLICY_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_call_set_state(call, LinphoneCallEarlyUpdatedByRemote, "EarlyUpdatedByRemote");
+ _linphone_core_accept_call_update(lc,call,NULL,call->prevstate,linphone_call_state_to_string(call->prevstate));
}
}
/* 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 +600,47 @@ 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:
+ case LinphoneCallEarlyUpdatedByRemote:
+ case LinphoneCallEarlyUpdating:
+ ms_warning("Receiving reINVITE or UPDATE while in state [%s], should not happen.",linphone_call_state_to_string(call->state));
+ break;
}
}
@@ -609,7 +649,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 +672,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);
@@ -645,15 +683,14 @@ static void call_terminated(SalOp *op, const char *from){
}
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);
}else {
- ms_message("!!!!!!!!!!resume_call_after_failed_transfer, salop was busy");
+ ms_message("resume_call_after_failed_transfer(), salop was busy");
return BELLE_SIP_CONTINUE;
}
}
@@ -677,25 +714,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 +749,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: /*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 +803,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 +824,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 +833,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 +855,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 +899,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 +937,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 +950,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 +1077,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 +1161,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 +1179,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 +1197,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 +1234,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){
diff --git a/coreapi/chat.c b/coreapi/chat.c
index c9ec8b6d5..45e1fc1ce 100644
--- a/coreapi/chat.c
+++ b/coreapi/chat.c
@@ -36,29 +36,19 @@
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;
-
-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_upload(void *data, const belle_sip_io_error_event_t *event){
LinphoneChatMessage* msg=(LinphoneChatMessage *)data;
- 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);
+ ms_error("I/O Error during file upload to %s - msg [%p] chat room[%p]", linphone_core_get_file_transfer_server(msg->chat_room->lc), msg, msg->chat_room);
if (msg->cb) {
- msg->cb(msg, LinphoneChatMessageStateNotDelivered, msg->chat_room->lc);
+ msg->cb(msg, LinphoneChatMessageStateNotDelivered, msg->cb_ud);
}
}
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);
+ ms_error("Error during file upload : auth requested to connect %s - msg [%p] chat room[%p]", linphone_core_get_file_transfer_server(msg->chat_room->lc), msg, msg->chat_room);
if (msg->cb) {
- msg->cb(msg, LinphoneChatMessageStateNotDelivered, msg->chat_room->lc);
+ msg->cb(msg, LinphoneChatMessageStateNotDelivered, msg->cb_ud);
}
}
@@ -66,14 +56,14 @@ static void process_io_error_download(void *data, const belle_sip_io_error_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);
+ msg->cb(msg, LinphoneChatMessageStateFileTransferError, msg->cb_ud);
}
}
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);
+ msg->cb(msg, LinphoneChatMessageStateFileTransferError, msg->cb_ud);
}
}
@@ -85,9 +75,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, offset, total);
return;
}
@@ -107,28 +95,12 @@ static int linphone_chat_message_file_transfer_on_send_body(belle_sip_user_body_
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 (offsetfile_transfer_information->size){
/* get data from call back */
- lc->vtable.file_transfer_send(lc, chatMsg, chatMsg->file_transfer_information, buf, size);
+ linphone_core_notify_file_transfer_send(lc, chatMsg, chatMsg->file_transfer_information, buf, size);
}
- belle_sip_free(content_type);
return BELLE_SIP_CONTINUE;
}
@@ -152,29 +124,35 @@ 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);
-
- /* 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);
-
- 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);
+ belle_sip_multipart_body_handler_t *bh;
+ char* ua;
+ char *first_part_header;
+ 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());
+ /* 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);
- belle_sip_free(content_type);
- content_type=belle_sip_strdup_printf("multipart/form-data; boundary=%s",multipart_boundary);
+ /* create a user body handler to take care of the file and add the content disposition and content-type headers */
+ if (msg->file_transfer_filepath != NULL) {
+ first_part_bh=(belle_sip_body_handler_t *)belle_sip_file_body_handler_new(msg->file_transfer_filepath,NULL,msg);
+ } else {
+ first_part_bh=(belle_sip_body_handler_t *)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(first_part_bh, belle_sip_header_create("Content-disposition", first_part_header));
+ belle_sip_free(first_part_header);
+ belle_sip_body_handler_add_header(first_part_bh, (belle_sip_header_t *)belle_sip_header_content_type_create(msg->file_transfer_information->type, msg->file_transfer_information->subtype));
- uri=belle_generic_uri_parse(msg->chat_room->lc->file_transfer_server);
+ /* insert it in a multipart body handler which will manage the boundaries of multipart message */
+ bh=belle_sip_multipart_body_handler_new(linphone_chat_message_file_transfer_on_progress, msg, first_part_bh);
+ /* create the http request: do not include the message header at this point, it is done by bellesip when setting the multipart body handler in the message */
+ ua = ms_strdup_printf("%s/%s", linphone_core_get_user_agent_name(), linphone_core_get_user_agent_version());
+ uri=belle_generic_uri_parse(linphone_core_get_file_transfer_server(msg->chat_room->lc));
req=belle_http_request_create("POST",
uri,
belle_sip_header_create("User-Agent",ua),
- belle_sip_header_create("Content-type",content_type),
NULL);
ms_free(ua);
- 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_upload;
@@ -191,10 +169,10 @@ static void linphone_chat_message_process_response_from_post_file(void *data, co
}
body = belle_sip_message_get_body((belle_sip_message_t *)event->response);
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");
+ if (msg->cb) {
+ msg->cb(msg, LinphoneChatMessageStateFileTransferDone, msg->cb_ud);
+ }
_linphone_chat_room_send_message(msg->chat_room, msg);
}
}
@@ -246,44 +224,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;
-
- 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 bool_t linphone_chat_room_matches(LinphoneChatRoom *cr, const LinphoneAddress *from){
+ return linphone_address_weak_equal(cr->peer_url,from);
+}
+
+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;
@@ -291,17 +284,63 @@ 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) {
- if(cr->lc->sal)
+ if(cr-> lc && 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;
@@ -310,7 +349,7 @@ 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) {
- if(cr->lc->sal)
+ if(cr->lc && 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;
@@ -319,29 +358,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) {
- if(cr->lc->sal)
+ if(cr->lc && 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){
@@ -352,14 +417,14 @@ 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;
belle_generic_uri_t *uri;
belle_http_request_t *req;
- uri=belle_generic_uri_parse(cr->lc->file_transfer_server);
+ uri=belle_generic_uri_parse(linphone_core_get_file_transfer_server(cr->lc));
req=belle_http_request_create("POST",
uri,
@@ -409,6 +474,9 @@ static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatM
sal_text_send(op, identity, cr->peer,msg->message);
} else {
sal_message_send(op, identity, cr->peer, msg->content_type, msg->message);
+ // Remove the message to prevent the xml from the file uplaod to be stored in the database
+ ms_free(msg->message);
+ msg->message = NULL;
}
}
msg->dir=LinphoneChatMessageOutgoing;
@@ -439,31 +507,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){
@@ -567,6 +614,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);
ms_free(from);
}
@@ -576,8 +624,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;
}
@@ -622,8 +669,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);
}
}
@@ -665,20 +711,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
@@ -995,9 +1027,7 @@ static void on_recv_body(belle_sip_user_body_handler_t *bh, belle_sip_message_t
return;
}
/* call back given by application level */
- if (lc->vtable.file_transfer_recv != NULL) {
- lc->vtable.file_transfer_recv(lc, chatMsg, chatMsg->file_transfer_information, (char *)buffer, size);
- }
+ linphone_core_notify_file_transfer_recv(lc, chatMsg, chatMsg->file_transfer_information, (char *)buffer, size);
return;
}
@@ -1045,16 +1075,21 @@ static void linphone_chat_process_response_headers_from_get_file(void *data, con
body_size = message->file_transfer_information->size;
}
- belle_sip_message_set_body_handler(
- (belle_sip_message_t*)event->response,
- (belle_sip_body_handler_t*)belle_sip_user_body_handler_new(body_size, linphone_chat_message_file_transfer_on_progress,on_recv_body,NULL,message)
- );
+ if (message->file_transfer_filepath == NULL) {
+ belle_sip_message_set_body_handler(
+ (belle_sip_message_t*)event->response,
+ (belle_sip_body_handler_t*)belle_sip_user_body_handler_new(body_size, linphone_chat_message_file_transfer_on_progress,on_recv_body,NULL,message)
+ );
+ } else {
+ belle_sip_message_set_body_handler(
+ (belle_sip_message_t *)event->response,
+ (belle_sip_body_handler_t *)belle_sip_file_body_handler_new(message->file_transfer_filepath, linphone_chat_message_file_transfer_on_progress, message)
+ );
+ }
}
}
static void linphone_chat_process_response_from_get_file(void *data, const belle_http_response_event_t *event){
- //LinphoneChatMessage* msg=(LinphoneChatMessage *)data;
-
/* check the answer code */
if (event->response){
int code=belle_http_response_get_status_code(event->response);
@@ -1062,8 +1097,9 @@ static void linphone_chat_process_response_from_get_file(void *data, const belle
LinphoneChatMessage* chatMsg=(LinphoneChatMessage *)data;
LinphoneCore *lc = chatMsg->chat_room->lc;
/* file downloaded succesfully, call again the callback with size at zero */
- if (lc->vtable.file_transfer_recv != NULL) {
- lc->vtable.file_transfer_recv(lc, chatMsg, chatMsg->file_transfer_information, NULL, 0);
+ linphone_core_notify_file_transfer_recv(lc, chatMsg, chatMsg->file_transfer_information, NULL, 0);
+ if (chatMsg->cb) {
+ chatMsg->cb(chatMsg, LinphoneChatMessageStateFileTransferDone, chatMsg->cb_ud);
}
}
}
@@ -1075,7 +1111,7 @@ static void linphone_chat_process_response_from_get_file(void *data, const belle
* @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(LinphoneChatMessage *message, LinphoneChatMessageStateChangedCb status_cb) {
+void linphone_chat_message_start_file_download(LinphoneChatMessage *message, LinphoneChatMessageStateChangedCb status_cb, void *ud) {
belle_http_request_listener_callbacks_t cbs={0};
belle_http_request_listener_t *l;
belle_generic_uri_t *uri;
@@ -1100,6 +1136,7 @@ void linphone_chat_message_start_file_download(LinphoneChatMessage *message, Lin
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->cb_ud = ud;
message->state = LinphoneChatMessageStateInProgress; /* start the download, status is In Progress */
belle_http_provider_send_request(message->chat_room->lc->http_provider,req,l);
}
@@ -1109,51 +1146,51 @@ void linphone_chat_message_start_file_download(LinphoneChatMessage *message, Lin
* @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);
+ ms_message("Cancelled file transfer %s - msg [%p] chat room[%p]", (msg->external_body_url==NULL)?linphone_core_get_file_transfer_server(msg->chat_room->lc):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);
+ msg->cb(msg, LinphoneChatMessageStateNotDelivered, msg->cb_ud);
}
}
/**
* 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;
@@ -1265,6 +1302,7 @@ LinphoneChatMessage* linphone_chat_message_clone(const LinphoneChatMessage* msg)
new_message->state=msg->state;
new_message->storage_id=msg->storage_id;
if (msg->from) new_message->from=linphone_address_clone(msg->from);
+ if (msg->file_transfer_filepath) new_message->file_transfer_filepath=ms_strdup(msg->file_transfer_filepath);
return new_message;
}
@@ -1292,6 +1330,10 @@ static void _linphone_chat_message_destroy(LinphoneChatMessage* msg) {
linphone_content_uninit(msg->file_transfer_information);
ms_free(msg->file_transfer_information);
}
+ if (msg->file_transfer_filepath != NULL) {
+ ms_free(msg->file_transfer_filepath);
+ }
+ ms_message("LinphoneChatMessage [%p] destroyed.",msg);
}
@@ -1327,6 +1369,27 @@ LinphoneReason linphone_chat_message_get_reason(LinphoneChatMessage* msg) {
}
+/**
+ * Set the path to the file to read from or write to during the file transfer.
+ * @param[in] msg LinphoneChatMessage object
+ * @param[in] filepath The path to the file to use for the file transfer.
+ */
+void linphone_chat_message_set_file_transfer_filepath(LinphoneChatMessage *msg, const char *filepath) {
+ if (msg->file_transfer_filepath != NULL) {
+ ms_free(msg->file_transfer_filepath);
+ }
+ msg->file_transfer_filepath = ms_strdup(filepath);
+}
+
+/**
+ * Get the path to the file to read from or write to during the file transfer.
+ * @param[in] msg LinphoneChatMessage object
+ * @return The path to the file to use for the file transfer.
+ */
+const char * linphone_chat_message_get_file_transfer_filepath(LinphoneChatMessage *msg) {
+ return msg->file_transfer_filepath;
+}
+
/**
* Create a message attached to a dedicated chat room with a particular content. Use #linphone_chat_room_send_message2 to initiate the transfer
@@ -1347,7 +1410,6 @@ LinphoneChatMessage* linphone_chat_room_create_file_transfer_message(LinphoneCha
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;
}
diff --git a/coreapi/conference.c b/coreapi/conference.c
index 7bee313dd..f860c33ad 100644
--- a/coreapi/conference.c
+++ b/coreapi/conference.c
@@ -41,6 +41,7 @@ static void conference_check_init(LinphoneConference *ctx, int samplerate){
MSAudioConferenceParams params;
params.samplerate=samplerate;
ctx->conf=ms_audio_conference_new(¶ms);
+ 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);
}
}
diff --git a/coreapi/event.c b/coreapi/event.c
index 992d058ab..372e0a953 100644
--- a/coreapi/event.c
+++ b/coreapi/event.c
@@ -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);
diff --git a/coreapi/friend.c b/coreapi/friend.c
index 7b0ddd816..d1ecd560c 100644
--- a/coreapi/friend.c
+++ b/coreapi/friend.c
@@ -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;
}
diff --git a/coreapi/gitversion.cmake b/coreapi/gitversion.cmake
index 1a6ec406c..5c6facdab 100644
--- a/coreapi/gitversion.cmake
+++ b/coreapi/gitversion.cmake
@@ -23,16 +23,17 @@
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 GIT_VERSION \"${GIT_REVISION}\""
+ 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 GIT_VERSION \"unknown\""
+ COMMAND ${CMAKE_COMMAND} -E echo "#define LIBLINPHONE_GIT_VERSION \"unknown\""
OUTPUT_FILE ${OUTPUT_DIR}/liblinphone_gitversion.h
)
endif()
diff --git a/coreapi/help/CMakeLists.txt b/coreapi/help/CMakeLists.txt
index 8f7b9b125..af624006e 100644
--- a/coreapi/help/CMakeLists.txt
+++ b/coreapi/help/CMakeLists.txt
@@ -26,9 +26,17 @@ 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)
- add_custom_target(doc ALL
- ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
- DEPENDS ${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()
diff --git a/coreapi/help/Doxyfile.in b/coreapi/help/Doxyfile.in
index 27068c53d..12facea9b 100644
--- a/coreapi/help/Doxyfile.in
+++ b/coreapi/help/Doxyfile.in
@@ -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 \1 \endxmlonly"
OPTIMIZE_OUTPUT_FOR_C = YES
OPTIMIZE_OUTPUT_JAVA = NO
SUBGROUPING = YES
diff --git a/coreapi/help/Makefile.am b/coreapi/help/Makefile.am
index 84822e51c..479d2b31d 100644
--- a/coreapi/help/Makefile.am
+++ b/coreapi/help/Makefile.am
@@ -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
diff --git a/coreapi/help/buddy_status.c b/coreapi/help/buddy_status.c
index 40db6458e..cd7f13d52 100644
--- a/coreapi/help/buddy_status.c
+++ b/coreapi/help/buddy_status.c
@@ -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*/
diff --git a/coreapi/help/chatroom.c b/coreapi/help/chatroom.c
index 51fc4a237..1f0f200a0 100644
--- a/coreapi/help/chatroom.c
+++ b/coreapi/help/chatroom.c
@@ -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*/
diff --git a/coreapi/help/filetransfer.c b/coreapi/help/filetransfer.c
index 25edc2d39..035a05597 100644
--- a/coreapi/help/filetransfer.c
+++ b/coreapi/help/filetransfer.c
@@ -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
@@ -48,11 +48,11 @@ static void stop(int signum){
/**
* function invoked to report file transfer progress.
* */
-static void file_transfer_progress_indication(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, size_t progress) {
+static void file_transfer_progress_indication(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, size_t offset, size_t total) {
const LinphoneAddress* from_address = linphone_chat_message_get_from(message);
const LinphoneAddress* to_address = linphone_chat_message_get_to(message);
char *address = linphone_chat_message_is_outgoing(message)?linphone_address_as_string(to_address):linphone_address_as_string(from_address);
- printf(" File transfer [%d%%] %s of type [%s/%s] %s [%s] \n", (int)progress
+ printf(" File transfer [%d%%] %s of type [%s/%s] %s [%s] \n", (int)((offset *100)/total)
,(linphone_chat_message_is_outgoing(message)?"sent":"received")
, content->type
, content->subtype
@@ -133,7 +133,7 @@ static void message_received(LinphoneCore *lc, LinphoneChatRoom *cr, LinphoneCha
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);
+ linphone_chat_message_start_file_download(msg, linphone_file_transfer_state_changed, NULL);
}
@@ -144,6 +144,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;i1){
@@ -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);
}
diff --git a/coreapi/help/registration.c b/coreapi/help/registration.c
index 70ab4f4ca..8dbab6440 100644
--- a/coreapi/help/registration.c
+++ b/coreapi/help/registration.c
@@ -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*/
- }
-
- // 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*/
-
- 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*/
+ 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*/
+ 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*/
/* main loop for receiving notifications and doing background linphonecore work: */
diff --git a/coreapi/info.c b/coreapi/info.c
index 2bf2b85ad..ad8cd1f8e 100644
--- a/coreapi/info.c
+++ b/coreapi/info.c
@@ -192,8 +192,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);
}
}
diff --git a/coreapi/ldap/ldapprovider.c b/coreapi/ldap/ldapprovider.c
index f9a4add67..75b6b19a1 100644
--- a/coreapi/ldap/ldapprovider.c
+++ b/coreapi/ldap/ldapprovider.c
@@ -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;
diff --git a/coreapi/linphone_tunnel.cc b/coreapi/linphone_tunnel.cc
index 2e77bbd95..beabd43a8 100644
--- a/coreapi/linphone_tunnel.cc
+++ b/coreapi/linphone_tunnel.cc
@@ -29,14 +29,15 @@
#include "private.h"
#include "lpconfig.h"
-LinphoneTunnel* linphone_core_get_tunnel(LinphoneCore *lc){
+static const char *_tunnel_mode_str[3] = { "disable", "enable", "auto" };
+
+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,16 +46,19 @@ 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);
}
@@ -100,12 +104,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, ":");
@@ -121,12 +125,12 @@ 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) {
+static void linphone_tunnel_save_config(const LinphoneTunnel *tunnel) {
MSList *elem = NULL;
char *tmp = NULL, *old_tmp = NULL, *tc_str = NULL;
for(elem = tunnel->config_list; elem != NULL; elem = elem->next) {
@@ -152,12 +156,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);
@@ -209,38 +213,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;
@@ -316,27 +319,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);
}
+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;
+ }
+}
+
+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;
+}
diff --git a/coreapi/linphone_tunnel.h b/coreapi/linphone_tunnel.h
index 336351267..8bf94fcef 100644
--- a/coreapi/linphone_tunnel.h
+++ b/coreapi/linphone_tunnel.h
@@ -50,6 +50,30 @@ extern "C"
typedef struct _LinphoneTunnelConfig LinphoneTunnelConfig;
+/**
+ * Enum describing the tunnel modes.
+**/
+typedef enum _LinphoneTunnelMode {
+ LinphoneTunnelModeDisable, /**< The tunnel is disabled. */
+ LinphoneTunnelModeEnable, /**< The tunnel is enabled. */
+ LinphoneTunnelModeAuto /**< The tunnel is enabled automatically if it is required. */
+} LinphoneTunnelMode;
+
+/**
+ * @brief Convert a string into LinphoneTunnelMode enum
+ * @param string String to convert
+ * @return An LinphoneTunnelMode enum. If the passed string is NULL or
+ * does not match with any mode, the LinphoneTunnelModeDisable is returned.
+ */
+LINPHONE_PUBLIC LinphoneTunnelMode string_to_tunnel_mode(const char *string);
+
+/**
+ * @brief Convert a tunnel mode enum into string
+ * @param mode Enum to convert
+ * @return "disable", "enable" or "auto"
+ */
+LINPHONE_PUBLIC const char *tunnel_mode_to_string(LinphoneTunnelMode mode);
+
/**
* Create a new tunnel configuration
*/
@@ -131,51 +155,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 +209,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.
- *
In case of success, the tunnel is automatically turned off. Otherwise, if no udp commmunication is feasible, tunnel mode is turned on.
- *
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 +242,49 @@ 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.
+ *
In case of success, the tunnel is automatically turned off. Otherwise, if no udp commmunication is feasible, tunnel mode is turned on.
+ *
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);
/**
* @}
diff --git a/coreapi/linphone_tunnel_stubs.c b/coreapi/linphone_tunnel_stubs.c
index c208dd249..72693463b 100644
--- a/coreapi/linphone_tunnel_stubs.c
+++ b/coreapi/linphone_tunnel_stubs.c
@@ -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; }
diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c
index c650894b3..7608c47ba 100644
--- a/coreapi/linphonecall.c
+++ b/coreapi/linphonecall.c
@@ -37,6 +37,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "mediastreamer2/mseventqueue.h"
#include "mediastreamer2/mssndcard.h"
+static const char EC_STATE_STORE[] = ".linphone.ecstate";
+
static void linphone_call_stats_uninit(LinphoneCallStats *stats);
#ifdef VIDEO_ENABLED
@@ -151,17 +153,14 @@ static uint16_t linphone_call_get_avpf_rr_interval(const LinphoneCall *call) {
}
static void propagate_encryption_changed(LinphoneCall *call){
- LinphoneCore *lc=call->core;
if (!linphone_call_all_streams_encrypted(call)) {
ms_message("Some streams are not encrypted");
- call->current_params.media_encryption=LinphoneMediaEncryptionNone;
- if (lc->vtable.call_encryption_changed)
- lc->vtable.call_encryption_changed(call->core, call, FALSE, call->auth_token);
+ call->current_params->media_encryption=LinphoneMediaEncryptionNone;
+ linphone_core_notify_call_encryption_changed(call->core, call, FALSE, call->auth_token);
} else {
ms_message("All streams are encrypted");
- call->current_params.media_encryption=LinphoneMediaEncryptionZRTP;
- if (lc->vtable.call_encryption_changed)
- lc->vtable.call_encryption_changed(call->core, call, TRUE, call->auth_token);
+ call->current_params->media_encryption=LinphoneMediaEncryptionZRTP;
+ linphone_core_notify_call_encryption_changed(call->core, call, TRUE, call->auth_token);
}
}
@@ -171,9 +170,9 @@ static void linphone_call_audiostream_encryption_changed(void *data, bool_t encr
call = (LinphoneCall *)data;
- if (encrypted && call->core->vtable.display_status != NULL) {
+ if (encrypted) {
snprintf(status,sizeof(status)-1,_("Authentication token is %s"),call->auth_token);
- call->core->vtable.display_status(call->core, status);
+ linphone_core_notify_display_status(call->core, status);
}
propagate_encryption_changed(call);
@@ -236,6 +235,14 @@ static MSList *make_codec_list(LinphoneCore *lc, const MSList *codecs, int bandw
for(it=codecs;it!=NULL;it=it->next){
PayloadType *pt=(PayloadType*)it->data;
if (pt->flags & PAYLOAD_TYPE_ENABLED){
+ int sample_rate = payload_type_get_rate(pt);
+
+ if( strcasecmp("G722",pt->mime_type) == 0 ){
+ /* G722 spec says 8000 but the codec actually requires 16000 */
+ ms_debug("Correcting sample rate for G722");
+ sample_rate = 16000;
+ }
+
if (bandwidth_limit>0 && !linphone_core_is_payload_type_usable_for_bandwidth(lc,pt,bandwidth_limit)){
ms_message("Codec %s/%i eliminated because of audio bandwidth constraint of %i kbit/s",
pt->mime_type,pt->clock_rate,bandwidth_limit);
@@ -244,7 +251,7 @@ static MSList *make_codec_list(LinphoneCore *lc, const MSList *codecs, int bandw
if (linphone_core_check_payload_type_usability(lc,pt)){
l=ms_list_append(l,payload_type_clone(pt));
nb++;
- if (max_sample_rate && payload_type_get_rate(pt)>*max_sample_rate) *max_sample_rate=payload_type_get_rate(pt);
+ if (max_sample_rate && sample_rate>*max_sample_rate) *max_sample_rate=sample_rate;
}
}
if ((nb_codecs_limit > 0) && (nb >= nb_codecs_limit)) break;
@@ -305,7 +312,7 @@ static void setup_encryption_keys(LinphoneCall *call, SalMediaDescription *md){
for(i=0; inb_streams; i++) {
if (!sal_stream_description_active(&md->streams[i])) continue;
if (sal_stream_description_has_srtp(&md->streams[i]) == TRUE) {
- if (keep_srtp_keys && old_md && sal_stream_description_has_srtp(&old_md->streams[i]) == TRUE){
+ if (keep_srtp_keys && old_md && (sal_stream_description_active(&old_md->streams[i]) == TRUE) && (sal_stream_description_has_srtp(&old_md->streams[i]) == TRUE)) {
int j;
ms_message("Keeping same crypto keys.");
for(j=0;jstreams[i])) continue;
for (pt_it = md->streams[i].payloads; pt_it != NULL; pt_it = pt_it->next) {
pt = (PayloadType *)pt_it->data;
- if (call->params.avpf_enabled == TRUE) {
+ if (call->params->avpf_enabled == TRUE) {
payload_type_set_flag(pt, PAYLOAD_TYPE_RTCP_FEEDBACK_ENABLED);
avpf_params = payload_type_get_avpf_params(pt);
- avpf_params.trr_interval = call->params.avpf_rr_interval;
+ avpf_params.trr_interval = call->params->avpf_rr_interval;
} else {
payload_type_unset_flag(pt, PAYLOAD_TYPE_RTCP_FEEDBACK_ENABLED);
memset(&avpf_params, 0, sizeof(avpf_params));
@@ -348,20 +355,20 @@ static void setup_rtcp_xr(LinphoneCall *call, SalMediaDescription *md) {
LinphoneCore *lc = call->core;
int i;
- md->rtcp_xr.enabled = lp_config_get_int(lc->config, "rtp", "rtcp_xr_enabled", 0);
+ md->rtcp_xr.enabled = lp_config_get_int(lc->config, "rtp", "rtcp_xr_enabled", 1);
if (md->rtcp_xr.enabled == TRUE) {
- const char *rcvr_rtt_mode = lp_config_get_string(lc->config, "rtp", "rtcp_xr_rcvr_rtt_mode", "none");
+ const char *rcvr_rtt_mode = lp_config_get_string(lc->config, "rtp", "rtcp_xr_rcvr_rtt_mode", "all");
if (strcasecmp(rcvr_rtt_mode, "all") == 0) md->rtcp_xr.rcvr_rtt_mode = OrtpRtcpXrRcvrRttAll;
else if (strcasecmp(rcvr_rtt_mode, "sender") == 0) md->rtcp_xr.rcvr_rtt_mode = OrtpRtcpXrRcvrRttSender;
else md->rtcp_xr.rcvr_rtt_mode = OrtpRtcpXrRcvrRttNone;
if (md->rtcp_xr.rcvr_rtt_mode != OrtpRtcpXrRcvrRttNone) {
- md->rtcp_xr.rcvr_rtt_max_size = lp_config_get_int(lc->config, "rtp", "rtcp_xr_rcvr_rtt_max_size", 0);
+ md->rtcp_xr.rcvr_rtt_max_size = lp_config_get_int(lc->config, "rtp", "rtcp_xr_rcvr_rtt_max_size", 10000);
}
- md->rtcp_xr.stat_summary_enabled = lp_config_get_int(lc->config, "rtp", "rtcp_xr_stat_summary_enabled", 0);
+ md->rtcp_xr.stat_summary_enabled = lp_config_get_int(lc->config, "rtp", "rtcp_xr_stat_summary_enabled", 1);
if (md->rtcp_xr.stat_summary_enabled == TRUE) {
md->rtcp_xr.stat_summary_flags = OrtpRtcpXrStatSummaryLoss | OrtpRtcpXrStatSummaryDup | OrtpRtcpXrStatSummaryJitt | OrtpRtcpXrStatSummaryTTL;
}
- md->rtcp_xr.voip_metrics_enabled = lp_config_get_int(lc->config, "rtp", "rtcp_xr_voip_metrics_enabled", 0);
+ md->rtcp_xr.voip_metrics_enabled = lp_config_get_int(lc->config, "rtp", "rtcp_xr_voip_metrics_enabled", 1);
}
for (i = 0; i < md->nb_streams; i++) {
if (!sal_stream_description_active(&md->streams[i])) continue;
@@ -374,13 +381,6 @@ void linphone_call_increment_local_media_description(LinphoneCall *call){
md->session_ver++;
}
-static 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;
-}
-
void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *call){
MSList *l;
PayloadType *pt;
@@ -391,9 +391,9 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *
SalMediaDescription *md=sal_media_description_new();
LinphoneAddress *addr;
char* local_ip=call->localip;
- const char *subject=linphone_call_params_get_session_name(&call->params);
+ const char *subject=linphone_call_params_get_session_name(call->params);
- linphone_core_adapt_to_network(lc,call->ping_time,&call->params);
+ linphone_core_adapt_to_network(lc,call->ping_time,call->params);
if (call->dest_proxy)
me=linphone_proxy_config_get_identity(call->dest_proxy);
@@ -409,8 +409,8 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *
strncpy(md->username,linphone_address_get_username(addr),sizeof(md->username));
if (subject) strncpy(md->name,subject,sizeof(md->name));
- if (call->params.down_bw)
- md->bandwidth=call->params.down_bw;
+ if (call->params->down_bw)
+ md->bandwidth=call->params->down_bw;
else md->bandwidth=linphone_core_get_download_bandwidth(lc);
/*set audio capabilities */
@@ -419,19 +419,19 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *
strncpy(md->streams[0].name,"Audio",sizeof(md->streams[0].name)-1);
md->streams[0].rtp_port=call->media_ports[0].rtp_port;
md->streams[0].rtcp_port=call->media_ports[0].rtcp_port;
- md->streams[0].proto=get_proto_from_call_params(&call->params);
+ md->streams[0].proto=get_proto_from_call_params(call->params);
md->streams[0].type=SalAudio;
- if (call->params.down_ptime)
- md->streams[0].ptime=call->params.down_ptime;
+ if (call->params->down_ptime)
+ md->streams[0].ptime=call->params->down_ptime;
else
md->streams[0].ptime=linphone_core_get_download_ptime(lc);
- l=make_codec_list(lc,lc->codecs_conf.audio_codecs,call->params.audio_bw,&md->streams[0].max_rate,-1);
+ l=make_codec_list(lc,lc->codecs_conf.audio_codecs,call->params->audio_bw,&md->streams[0].max_rate,-1);
pt=payload_type_clone(rtp_profile_get_payload_from_mime(lc->default_profile,"telephone-event"));
l=ms_list_append(l,pt);
md->streams[0].payloads=l;
nb_active_streams++;
- if (call->params.has_video){
+ if (call->params->has_video){
strncpy(md->streams[1].rtp_addr,local_ip,sizeof(md->streams[1].rtp_addr));
strncpy(md->streams[1].rtcp_addr,local_ip,sizeof(md->streams[1].rtcp_addr));
strncpy(md->streams[1].name,"Video",sizeof(md->streams[1].name)-1);
@@ -562,15 +562,12 @@ static void port_config_set(LinphoneCall *call, int stream_index, int min_port,
static void linphone_call_init_common(LinphoneCall *call, LinphoneAddress *from, LinphoneAddress *to){
int min_port, max_port;
ms_message("New LinphoneCall [%p] initialized (LinphoneCore version: %s)",call,linphone_core_get_version());
- call->magic=linphone_call_magic;
- call->refcnt=1;
call->state=LinphoneCallIdle;
call->transfer_state = LinphoneCallIdle;
- call->media_start_time=0;
- call->log=linphone_call_log_new(call, from, to);
- call->owns_call_log=TRUE;
+ call->log=linphone_call_log_new(call->dir, from, to);
call->camera_enabled=TRUE;
- call->current_params.media_encryption=LinphoneMediaEncryptionNone;
+ call->current_params = linphone_call_params_new();
+ call->current_params->media_encryption=LinphoneMediaEncryptionNone;
linphone_core_get_audio_port_range(call->core, &min_port, &max_port);
port_config_set(call,0,min_port,max_port);
@@ -612,11 +609,11 @@ void linphone_call_create_op(LinphoneCall *call){
if (call->op) sal_op_release(call->op);
call->op=sal_op_new(call->core->sal);
sal_op_set_user_pointer(call->op,call);
- if (call->params.referer)
- sal_call_set_referer(call->op,call->params.referer->op);
- linphone_configure_op(call->core,call->op,call->log->to,call->params.custom_headers,FALSE);
- if (call->params.privacy != LinphonePrivacyDefault)
- sal_op_set_privacy(call->op,(SalPrivacyMask)call->params.privacy);
+ if (call->params->referer)
+ sal_call_set_referer(call->op,call->params->referer->op);
+ linphone_configure_op(call->core,call->op,call->log->to,call->params->custom_headers,FALSE);
+ if (call->params->privacy != LinphonePrivacyDefault)
+ sal_op_set_privacy(call->op,(SalPrivacyMask)call->params->privacy);
/*else privacy might be set by proxy */
}
@@ -639,21 +636,70 @@ static void linphone_call_outgoing_select_ip_version(LinphoneCall *call, Linphon
}else call->af=AF_INET;
}
+/**
+ * Fill the local ip that routes to the internet according to the destination, or guess it by other special means (upnp).
+ */
+static void linphone_call_get_local_ip(LinphoneCall *call, const LinphoneAddress *remote_addr){
+ const char *ip;
+ int af = call->af;
+ const char *dest = NULL;
+ if (call->dest_proxy == NULL) {
+ struct addrinfo hints;
+ struct addrinfo *res = NULL;
+ int err;
+ const char *domain = linphone_address_get_domain(remote_addr);
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_flags = AI_NUMERICHOST;
+ err = getaddrinfo(domain, NULL, &hints, &res);
+ if (err == 0) {
+ dest = domain;
+ }
+ if (res != NULL) freeaddrinfo(res);
+ }
+ if (_linphone_core_get_firewall_policy(call->core)==LinphonePolicyUseNatAddress
+ && (ip=linphone_core_get_nat_address_resolved(call->core))!=NULL){
+ strncpy(call->localip,ip,LINPHONE_IPADDR_SIZE);
+ return;
+ }
+#ifdef BUILD_UPNP
+ else if (call->core->upnp != NULL && linphone_core_get_firewall_policy(call->core)==LinphonePolicyUseUpnp &&
+ linphone_upnp_context_get_state(call->core->upnp) == LinphoneUpnpStateOk) {
+ ip = linphone_upnp_context_get_external_ipaddress(call->core->upnp);
+ strncpy(call->localip,ip,LINPHONE_IPADDR_SIZE);
+ return;
+ }
+#endif //BUILD_UPNP
+ linphone_core_get_local_ip(call->core, af, dest, call->localip);
+}
+
+static void linphone_call_destroy(LinphoneCall *obj);
+
+BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneCall);
+
+BELLE_SIP_INSTANCIATE_VPTR(LinphoneCall, belle_sip_object_t,
+ (belle_sip_object_destroy_t)linphone_call_destroy,
+ NULL, // clone
+ NULL, // marshal
+ FALSE
+);
+
LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, const LinphoneCallParams *params, LinphoneProxyConfig *cfg){
- LinphoneCall *call=ms_new0(LinphoneCall,1);
+ LinphoneCall *call = belle_sip_object_new(LinphoneCall);
call->dir=LinphoneCallOutgoing;
call->core=lc;
linphone_call_outgoing_select_ip_version(call,to,cfg);
- linphone_core_get_local_ip(lc,call->af,call->localip);
+ linphone_call_get_local_ip(call, to);
linphone_call_init_common(call,from,to);
- _linphone_call_params_copy(&call->params,params);
+ call->params = linphone_call_params_copy(params);
- if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) {
+ if (_linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) {
call->ice_session = ice_session_new();
ice_session_set_role(call->ice_session, IR_Controlling);
}
- if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseStun) {
+ if (_linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseStun) {
call->ping_time=linphone_core_run_stun_tests(call->core,call);
}
#ifdef BUILD_UPNP
@@ -683,24 +729,24 @@ static void linphone_call_incoming_select_ip_version(LinphoneCall *call){
* Fix call parameters on incoming call to eg. enable AVPF if the incoming call propose it and it is not enabled locally.
*/
void linphone_call_set_compatible_incoming_call_parameters(LinphoneCall *call, const SalMediaDescription *md) {
- call->params.has_video &= linphone_core_media_description_contains_video_stream(md);
+ call->params->has_video &= linphone_core_media_description_contains_video_stream(md);
/* Handle AVPF and SRTP. */
- call->params.avpf_enabled = sal_media_description_has_avpf(md);
- if (call->params.avpf_enabled == TRUE) {
+ call->params->avpf_enabled = sal_media_description_has_avpf(md);
+ if (call->params->avpf_enabled == TRUE) {
if (call->dest_proxy != NULL) {
- call->params.avpf_rr_interval = linphone_proxy_config_get_avpf_rr_interval(call->dest_proxy) * 1000;
+ call->params->avpf_rr_interval = linphone_proxy_config_get_avpf_rr_interval(call->dest_proxy) * 1000;
} else {
- call->params.avpf_rr_interval = 5000;
+ call->params->avpf_rr_interval = linphone_core_get_avpf_rr_interval(call->core)*1000;
}
}
if ((sal_media_description_has_srtp(md) == TRUE) && (media_stream_srtp_supported() == TRUE)) {
- call->params.media_encryption = LinphoneMediaEncryptionSRTP;
+ call->params->media_encryption = LinphoneMediaEncryptionSRTP;
}
}
LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, SalOp *op){
- LinphoneCall *call=ms_new0(LinphoneCall,1);
+ LinphoneCall *call = belle_sip_object_new(LinphoneCall);
const SalMediaDescription *md;
LinphoneFirewallPolicy fpol;
@@ -731,27 +777,28 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro
}
linphone_address_clean(from);
- linphone_core_get_local_ip(lc,call->af,call->localip);
+ linphone_call_get_local_ip(call, from);
linphone_call_init_common(call, from, to);
+ call->params = linphone_call_params_new();
call->log->call_id=ms_strdup(sal_op_get_call_id(op)); /*must be known at that time*/
call->dest_proxy = linphone_core_lookup_known_proxy(call->core, to);
- linphone_core_init_default_params(lc, &call->params);
+ linphone_core_init_default_params(lc, call->params);
/*
* Initialize call parameters according to incoming call parameters. This is to avoid to ask later (during reINVITEs) for features that the remote
* end apparently does not support. This features are: privacy, video
*/
/*set privacy*/
- call->current_params.privacy=(LinphonePrivacyMask)sal_op_get_privacy(call->op);
+ call->current_params->privacy=(LinphonePrivacyMask)sal_op_get_privacy(call->op);
/*set video support */
md=sal_call_get_remote_media_description(op);
- call->params.has_video = lc->video_policy.automatically_accept;
+ call->params->has_video = linphone_core_video_enabled(lc) && lc->video_policy.automatically_accept;
if (md) {
// It is licit to receive an INVITE without SDP
// In this case WE chose the media parameters according to policy.
linphone_call_set_compatible_incoming_call_parameters(call, md);
}
- fpol=linphone_core_get_firewall_policy(call->core);
+ fpol=_linphone_core_get_firewall_policy(call->core);
/*create the ice session now if ICE is required*/
if (fpol==LinphonePolicyUseIce){
if (md){
@@ -810,7 +857,6 @@ static void linphone_call_set_terminated(LinphoneCall *call){
linphone_core_update_allocated_audio_bandwidth(lc);
linphone_call_stats_uninit(&call->stats[0]);
linphone_call_stats_uninit(&call->stats[1]);
- call->owns_call_log=FALSE;
linphone_call_log_completed(call);
@@ -831,10 +877,10 @@ static void linphone_call_set_terminated(LinphoneCall *call){
}
void linphone_call_fix_call_parameters(LinphoneCall *call){
- call->params.has_video=call->current_params.has_video;
+ call->params->has_video=call->current_params->has_video;
- if (call->params.media_encryption != LinphoneMediaEncryptionZRTP) /*in case of ZRTP call parameter are handle after zrtp negociation*/
- call->params.media_encryption=call->current_params.media_encryption;
+ if (call->params->media_encryption != LinphoneMediaEncryptionZRTP) /*in case of ZRTP call parameter are handle after zrtp negociation*/
+ call->params->media_encryption=call->current_params->media_encryption;
}
const char *linphone_call_state_to_string(LinphoneCallState cs){
@@ -877,11 +923,19 @@ const char *linphone_call_state_to_string(LinphoneCallState cs){
return "LinphoneCallUpdating";
case LinphoneCallReleased:
return "LinphoneCallReleased";
+ case LinphoneCallEarlyUpdatedByRemote:
+ return "LinphoneCallEarlyUpdatedByRemote";
+ case LinphoneCallEarlyUpdating:
+ return "LinphoneCallEarlyUpdating";
}
return "undefined state";
}
-void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const char *message){
+void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const char *message) {
+ linphone_call_set_state_base(call, cstate, message,FALSE);
+}
+
+void linphone_call_set_state_base(LinphoneCall *call, LinphoneCallState cstate, const char *message,bool_t silently){
LinphoneCore *lc=call->core;
if (call->state!=cstate){
@@ -917,11 +971,11 @@ void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const
}
if (cstate == LinphoneCallConnected) {
call->log->status=LinphoneCallSuccess;
- call->media_start_time=time(NULL);
+ call->log->connected_date_time=time(NULL);
}
- if (lc->vtable.call_state_changed)
- lc->vtable.call_state_changed(lc,call,cstate,message);
+ if (!silently)
+ linphone_core_notify_call_state_changed(lc,call,cstate,message);
linphone_reporting_call_state_updated(call);
@@ -983,15 +1037,17 @@ static void linphone_call_destroy(LinphoneCall *obj)
if (obj->transfer_target){
linphone_call_unref(obj->transfer_target);
}
- if (obj->owns_call_log)
- linphone_call_log_destroy(obj->log);
+ if (obj->log)
+ linphone_call_log_unref(obj->log);
if (obj->auth_token) {
ms_free(obj->auth_token);
}
- linphone_call_params_uninit(&obj->params);
- linphone_call_params_uninit(&obj->current_params);
+ linphone_call_params_unref(obj->params);
+ linphone_call_params_unref(obj->current_params);
+ if (obj->remote_params != NULL) {
+ linphone_call_params_unref(obj->remote_params);
+ }
sal_error_info_reset(&obj->non_op_error);
- ms_free(obj);
}
/**
@@ -999,27 +1055,13 @@ static void linphone_call_destroy(LinphoneCall *obj)
* @{
**/
-/**
- * Increments the call 's reference count.
- * 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().
-**/
LinphoneCall * linphone_call_ref(LinphoneCall *obj){
- obj->refcnt++;
+ belle_sip_object_ref(obj);
return obj;
}
-/**
- * Decrements the call object reference count.
- * See linphone_call_ref().
-**/
void linphone_call_unref(LinphoneCall *obj){
- obj->refcnt--;
- if (obj->refcnt==0){
- linphone_call_destroy(obj);
- }
+ belle_sip_object_unref(obj);
}
/**
@@ -1029,35 +1071,35 @@ const LinphoneCallParams * linphone_call_get_current_params(LinphoneCall *call){
#ifdef VIDEO_ENABLED
VideoStream *vstream;
#endif
- MS_VIDEO_SIZE_ASSIGN(call->current_params.sent_vsize, UNKNOWN);
- MS_VIDEO_SIZE_ASSIGN(call->current_params.recv_vsize, UNKNOWN);
+ MS_VIDEO_SIZE_ASSIGN(call->current_params->sent_vsize, UNKNOWN);
+ MS_VIDEO_SIZE_ASSIGN(call->current_params->recv_vsize, UNKNOWN);
#ifdef VIDEO_ENABLED
vstream = call->videostream;
if (vstream != NULL) {
- call->current_params.sent_vsize = video_stream_get_sent_video_size(vstream);
- call->current_params.recv_vsize = video_stream_get_received_video_size(vstream);
- call->current_params.sent_fps = video_stream_get_sent_framerate(vstream);
- call->current_params.received_fps = video_stream_get_received_framerate(vstream);
+ call->current_params->sent_vsize = video_stream_get_sent_video_size(vstream);
+ call->current_params->recv_vsize = video_stream_get_received_video_size(vstream);
+ call->current_params->sent_fps = video_stream_get_sent_framerate(vstream);
+ call->current_params->received_fps = video_stream_get_received_framerate(vstream);
}
#endif
if (linphone_call_all_streams_encrypted(call)) {
if (linphone_call_get_authentication_token(call)) {
- call->current_params.media_encryption=LinphoneMediaEncryptionZRTP;
+ call->current_params->media_encryption=LinphoneMediaEncryptionZRTP;
} else {
- call->current_params.media_encryption=LinphoneMediaEncryptionSRTP;
+ call->current_params->media_encryption=LinphoneMediaEncryptionSRTP;
}
} else {
- call->current_params.media_encryption=LinphoneMediaEncryptionNone;
+ call->current_params->media_encryption=LinphoneMediaEncryptionNone;
}
- call->current_params.avpf_enabled = linphone_call_all_streams_avpf_enabled(call);
- if (call->current_params.avpf_enabled == TRUE) {
- call->current_params.avpf_rr_interval = linphone_call_get_avpf_rr_interval(call);
+ call->current_params->avpf_enabled = linphone_call_all_streams_avpf_enabled(call);
+ if (call->current_params->avpf_enabled == TRUE) {
+ call->current_params->avpf_rr_interval = linphone_call_get_avpf_rr_interval(call);
} else {
- call->current_params.avpf_rr_interval = 0;
+ call->current_params->avpf_rr_interval = 0;
}
- return &call->current_params;
+ return call->current_params;
}
/**
@@ -1067,10 +1109,12 @@ const LinphoneCallParams * linphone_call_get_current_params(LinphoneCall *call){
* supports video, encryption or whatever.
**/
const LinphoneCallParams * linphone_call_get_remote_params(LinphoneCall *call){
- LinphoneCallParams *cp=&call->remote_params;
- memset(cp,0,sizeof(*cp));
if (call->op){
- SalMediaDescription *md=sal_call_get_remote_media_description(call->op);
+ LinphoneCallParams *cp;
+ SalMediaDescription *md;
+ if (call->remote_params != NULL) linphone_call_params_unref(call->remote_params);
+ cp = call->remote_params = linphone_call_params_new();
+ md=sal_call_get_remote_media_description(call->op);
if (md) {
SalStreamDescription *sd;
unsigned int i;
@@ -1093,7 +1137,7 @@ const LinphoneCallParams * linphone_call_get_remote_params(LinphoneCall *call){
}
if (md->name[0]!='\0') linphone_call_params_set_session_name(cp,md->name);
}
- cp->custom_headers=(SalCustomHeader*)sal_op_get_recv_custom_header(call->op);
+ cp->custom_headers=sal_custom_header_clone((SalCustomHeader*)sal_op_get_recv_custom_header(call->op));
return cp;
}
return NULL;
@@ -1140,27 +1184,26 @@ const LinphoneErrorInfo *linphone_call_get_error_info(const LinphoneCall *call){
}
/**
- * Get the user_pointer in the LinphoneCall
+ * Get the user pointer associated with the LinphoneCall
*
* @ingroup call_control
- *
- * return user_pointer an opaque user pointer that can be retrieved at any time
+ * @return an opaque user pointer that can be retrieved at any time
**/
-void *linphone_call_get_user_pointer(LinphoneCall *call)
+void *linphone_call_get_user_data(const LinphoneCall *call)
{
- return call->user_pointer;
+ return call->user_data;
}
/**
- * Set the user_pointer in the LinphoneCall
+ * Set the user pointer associated with the LinphoneCall
*
* @ingroup call_control
*
- * the user_pointer is an opaque user pointer that can be retrieved at any time in the LinphoneCall
+ * the user pointer is an opaque user pointer that can be retrieved at any time in the LinphoneCall
**/
-void linphone_call_set_user_pointer(LinphoneCall *call, void *user_pointer)
+void linphone_call_set_user_data(LinphoneCall *call, void *user_pointer)
{
- call->user_pointer = user_pointer;
+ call->user_data = user_pointer;
}
/**
@@ -1240,8 +1283,8 @@ bool_t linphone_call_has_transfer_pending(const LinphoneCall *call){
* Returns call's duration in seconds.
**/
int linphone_call_get_duration(const LinphoneCall *call){
- if (call->media_start_time==0) return 0;
- return time(NULL)-call->media_start_time;
+ if (call->log->connected_date_time==0) return 0;
+ return time(NULL)-call->log->connected_date_time;
}
/**
@@ -1304,7 +1347,6 @@ int linphone_call_take_video_snapshot(LinphoneCall *call, const char *file){
return ms_filter_call_method(call->videostream->jpegwriter,MS_JPEG_WRITER_TAKE_SNAPSHOT,(void*)file);
}
ms_warning("Cannot take snapshot: no currently running video stream on this call.");
- return -1;
#endif
return -1;
}
@@ -1334,194 +1376,6 @@ bool_t linphone_call_camera_enabled (const LinphoneCall *call){
return call->camera_enabled;
}
-/**
- * Enable video stream.
-**/
-void linphone_call_params_enable_video(LinphoneCallParams *cp, bool_t enabled){
- cp->has_video=enabled;
-}
-
-/**
- * Returns the audio codec used in the call, described as a PayloadType structure.
-**/
-const PayloadType* linphone_call_params_get_used_audio_codec(const LinphoneCallParams *cp) {
- return cp->audio_codec;
-}
-
-
-/**
- * Returns the video codec used in the call, described as a PayloadType structure.
-**/
-const PayloadType* linphone_call_params_get_used_video_codec(const LinphoneCallParams *cp) {
- return cp->video_codec;
-}
-
-MSVideoSize linphone_call_params_get_sent_video_size(const LinphoneCallParams *cp) {
- return cp->sent_vsize;
-}
-
-MSVideoSize linphone_call_params_get_received_video_size(const LinphoneCallParams *cp) {
- return cp->recv_vsize;
-}
-
-/**
- * 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.
- */
-float linphone_call_params_get_sent_framerate(const LinphoneCallParams *cp){
- return cp->sent_fps;
-}
-
-/**
- * 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.
- */
-float linphone_call_params_get_received_framerate(const LinphoneCallParams *cp){
- return cp->received_fps;
-}
-
-const char * linphone_call_params_get_rtp_profile(const LinphoneCallParams *cp) {
- return sal_media_proto_to_string(get_proto_from_call_params(cp));
-}
-
-/**
- * @ingroup call_control
- * Use to know if this call has been configured in low bandwidth mode.
- * This mode can be automatically discovered thanks to a stun server when activate_edge_workarounds=1 in section [net] of configuration file.
- * 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.
- * @return TRUE if low bandwidth has been configured/detected
- */
-bool_t linphone_call_params_low_bandwidth_enabled(const LinphoneCallParams *cp) {
- return cp->low_bandwidth;
-}
-
-/**
- * @ingroup call_control
- * Indicate low bandwith mode.
- * Configuring a call to low bandwidth mode will result in the core to activate several settings for the call in order to ensure that bitrate usage
- * is lowered to the minimum possible. Typically, ptime (packetization time) will be increased, audio codec's output bitrate will be targetted to 20kbit/s provided
- * that it is achievable by the codec selected after SDP handshake. Video is automatically disabled.
- *
-**/
-void linphone_call_params_enable_low_bandwidth(LinphoneCallParams *cp, bool_t enabled){
- cp->low_bandwidth=enabled;
-}
-
-/**
- * Returns whether video is enabled.
-**/
-bool_t linphone_call_params_video_enabled(const LinphoneCallParams *cp){
- return cp->has_video;
-}
-
-/**
- * Returns kind of media encryption selected for the call.
-**/
-LinphoneMediaEncryption linphone_call_params_get_media_encryption(const LinphoneCallParams *cp) {
- return cp->media_encryption;
-}
-
-/**
- * Set requested media encryption for a call.
-**/
-void linphone_call_params_set_media_encryption(LinphoneCallParams *cp, LinphoneMediaEncryption e) {
- cp->media_encryption = e;
-}
-
-
-/**
- * Enable sending of real early media (during outgoing calls).
-**/
-void linphone_call_params_enable_early_media_sending(LinphoneCallParams *cp, bool_t enabled){
- cp->real_early_media=enabled;
-}
-
-/**
- * Indicates whether sending of early media was enabled.
-**/
-bool_t linphone_call_params_early_media_sending_enabled(const LinphoneCallParams *cp){
- return cp->real_early_media;
-}
-
-/**
- * Returns true if the call is part of the locally managed conference.
-**/
-bool_t linphone_call_params_get_local_conference_mode(const LinphoneCallParams *cp){
- return cp->in_conference;
-}
-
-/**
- * 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.
-**/
-void linphone_call_params_set_audio_bandwidth_limit(LinphoneCallParams *cp, int bandwidth){
- cp->audio_bw=bandwidth;
-}
-
-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);
-}
-
-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);
-}
-
-/**
- * Returns 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 cp the call parameters.
-**/
-const char *linphone_call_params_get_session_name(const LinphoneCallParams *cp){
- return cp->session_name;
-}
-
-/**
- * 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 cp the call parameters.
- * @param name the session name
-**/
-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);
-}
-
-void _linphone_call_params_copy(LinphoneCallParams *ncp, const LinphoneCallParams *cp){
- if (ncp==cp) return;
- 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);
-}
-
-/**
- * @ingroup call_control
- * Set requested level of privacy for the call.
- * \xmlonly javascript \endxmlonly
- * @param params the call parameters to be modified
- * @param privacy LinphonePrivacy to configure privacy
- * */
-void linphone_call_params_set_privacy(LinphoneCallParams *params, LinphonePrivacyMask privacy) {
- params->privacy=privacy;
-}
-
-/**
- * @ingroup call_control
- * Get requested level of privacy for the call.
- * @param params the call parameters
- * @return Privacy mode
- * */
-LinphonePrivacyMask linphone_call_params_get_privacy(const LinphoneCallParams *params) {
- return params->privacy;
-}
/**
* @ingroup call_control
@@ -1539,27 +1393,6 @@ const char* linphone_privacy_to_string(LinphonePrivacy privacy) {
default: return "Unknown privacy mode";
}
}
-/**
- * Copy existing LinphoneCallParams to a new LinphoneCallParams object.
-**/
-LinphoneCallParams * linphone_call_params_copy(const LinphoneCallParams *cp){
- LinphoneCallParams *ncp=ms_new0(LinphoneCallParams,1);
- _linphone_call_params_copy(ncp,cp);
- return ncp;
-}
-
-void linphone_call_params_uninit(LinphoneCallParams *p){
- if (p->record_file) ms_free(p->record_file);
- if (p->custom_headers) sal_custom_header_free(p->custom_headers);
-}
-
-/**
- * Destroy LinphoneCallParams.
-**/
-void linphone_call_params_destroy(LinphoneCallParams *p){
- linphone_call_params_uninit(p);
- ms_free(p);
-}
/**
@@ -1594,7 +1427,7 @@ static void video_stream_event_cb(void *user_pointer, const MSFilter *f, const u
case MS_VIDEO_DECODER_FIRST_IMAGE_DECODED:
ms_message("First video frame decoded successfully");
if (call->nextVideoFrameDecoded._func != NULL)
- call->nextVideoFrameDecoded._func(call, call->nextVideoFrameDecoded._user_data);
+ call->nextVideoFrameDecoded._func(call, call->nextVideoFrameDecoded._user_data);
break;
case MS_VIDEO_DECODER_SEND_PLI:
case MS_VIDEO_DECODER_SEND_SLI:
@@ -1624,7 +1457,7 @@ static void port_config_set_random_choosed(LinphoneCall *call, int stream_index,
static void _linphone_call_prepare_ice_for_stream(LinphoneCall *call, int stream_index, bool_t create_checklist){
MediaStream *ms=stream_index == 0 ? (MediaStream*)call->audiostream : (MediaStream*)call->videostream;
- if ((linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) && (call->ice_session != NULL)){
+ if ((_linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) && (call->ice_session != NULL)){
IceCheckList *cl;
rtp_session_set_pktinfo(ms->sessions.rtp_session, TRUE);
rtp_session_set_symmetric_rtp(ms->sessions.rtp_session, FALSE);
@@ -1645,11 +1478,11 @@ int linphone_call_prepare_ice(LinphoneCall *call, bool_t incoming_offer){
SalMediaDescription *remote = NULL;
bool_t has_video=FALSE;
- if ((linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) && (call->ice_session != NULL)){
+ if ((_linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) && (call->ice_session != NULL)){
if (incoming_offer){
remote=sal_call_get_remote_media_description(call->op);
- has_video=call->params.has_video && linphone_core_media_description_contains_video_stream(remote);
- }else has_video=call->params.has_video;
+ has_video=call->params->has_video && linphone_core_media_description_contains_video_stream(remote);
+ }else has_video=call->params->has_video;
_linphone_call_prepare_ice_for_stream(call,0,TRUE);
if (has_video) _linphone_call_prepare_ice_for_stream(call,1,TRUE);
@@ -1679,6 +1512,7 @@ int linphone_call_prepare_ice(LinphoneCall *call, bool_t incoming_offer){
void linphone_call_init_audio_stream(LinphoneCall *call){
LinphoneCore *lc=call->core;
AudioStream *audiostream;
+ const char *location;
int dscp;
if (call->audiostream != NULL) return;
@@ -1702,16 +1536,24 @@ void linphone_call_init_audio_stream(LinphoneCall *call){
else if (strcasecmp(type,"full")==0)
audio_stream_enable_echo_limiter(audiostream,ELControlFull);
}
+
+ /* equalizer location in the graph: 'mic' = in input graph, otherwise in output graph.
+ Any other value than mic will default to output graph for compatibility */
+ location = lp_config_get_string(lc->config,"sound","eq_location","hp");
+ audiostream->eq_loc = (strcasecmp(location,"mic") == 0) ? MSEqualizerMic : MSEqualizerHP;
+ ms_message("Equalizer location: %s", location);
+
audio_stream_enable_gain_control(audiostream,TRUE);
if (linphone_core_echo_cancellation_enabled(lc)){
int len,delay,framesize;
- const char *statestr=lp_config_get_string(lc->config,"sound","ec_state",NULL);
+ char *statestr=lp_config_read_relative_file(lc->config, EC_STATE_STORE);
len=lp_config_get_int(lc->config,"sound","ec_tail_len",0);
delay=lp_config_get_int(lc->config,"sound","ec_delay",0);
framesize=lp_config_get_int(lc->config,"sound","ec_framesize",0);
audio_stream_set_echo_canceller_params(audiostream,len,delay,framesize);
if (statestr && audiostream->ec){
ms_filter_call_method(audiostream->ec,MS_ECHO_CANCELLER_SET_STATE_STRING,(void*)statestr);
+ ms_free(statestr);
}
}
audio_stream_enable_automatic_gain_control(audiostream,linphone_core_agc_enabled(lc));
@@ -1725,7 +1567,11 @@ void linphone_call_init_audio_stream(LinphoneCall *call){
if (lc->rtptf){
RtpTransport *artp=lc->rtptf->audio_rtp_func(lc->rtptf->audio_rtp_func_data, call->media_ports[0].rtp_port);
RtpTransport *artcp=lc->rtptf->audio_rtcp_func(lc->rtptf->audio_rtcp_func_data, call->media_ports[0].rtcp_port);
- rtp_session_set_transports(audiostream->ms.sessions.rtp_session,artp,artcp);
+ RtpTransport *meta_rtp;
+ RtpTransport *meta_rtcp;
+ meta_rtp_transport_new(&meta_rtp,TRUE,artp, 0);
+ meta_rtp_transport_new(&meta_rtcp,FALSE,artcp, 0);
+ rtp_session_set_transports(audiostream->ms.sessions.rtp_session,meta_rtp,meta_rtcp);
}
call->audiostream_app_evq = ortp_ev_queue_new();
@@ -1763,9 +1609,13 @@ void linphone_call_init_video_stream(LinphoneCall *call){
if (lc->rtptf){
RtpTransport *vrtp=lc->rtptf->video_rtp_func(lc->rtptf->video_rtp_func_data, call->media_ports[1].rtp_port);
RtpTransport *vrtcp=lc->rtptf->video_rtcp_func(lc->rtptf->video_rtcp_func_data, call->media_ports[1].rtcp_port);
- rtp_session_set_transports(call->videostream->ms.sessions.rtp_session,vrtp,vrtcp);
+ RtpTransport *meta_rtp;
+ RtpTransport *meta_rtcp;
+ meta_rtp_transport_new(&meta_rtp,TRUE,vrtp, 0);
+ meta_rtp_transport_new(&meta_rtcp,FALSE,vrtcp, 0);
+ rtp_session_set_transports(call->videostream->ms.sessions.rtp_session,meta_rtp,meta_rtcp);
}
- call->videostream_app_evq = ortp_ev_queue_new();
+ call->videostream_app_evq = ortp_ev_queue_new();
rtp_session_register_event_queue(call->videostream->ms.sessions.rtp_session,call->videostream_app_evq);
_linphone_call_prepare_ice_for_stream(call,1,FALSE);
#ifdef TEST_EXT_RENDERER
@@ -1790,8 +1640,7 @@ static void linphone_core_dtmf_received(LinphoneCore *lc, int dtmf){
ms_warning("Bad dtmf value %i",dtmf);
return;
}
- if (lc->vtable.dtmf_received != NULL)
- lc->vtable.dtmf_received(lc, linphone_core_get_current_call(lc), dtmf_tab[dtmf]);
+ linphone_core_notify_dtmf_received(lc, linphone_core_get_current_call(lc), dtmf_tab[dtmf]);
}
static void parametrize_equalizer(LinphoneCore *lc, AudioStream *st){
@@ -1816,6 +1665,19 @@ static void parametrize_equalizer(LinphoneCore *lc, AudioStream *st){
}
}
+void set_mic_gain_db(AudioStream *st, float gain){
+ if (st->volsend){
+ ms_filter_call_method(st->volsend,MS_VOLUME_SET_DB_GAIN,&gain);
+ }else ms_warning("Could not apply mic gain: gain control wasn't activated.");
+}
+
+void set_playback_gain_db(AudioStream *st, float gain){
+ if (st->volrecv){
+ ms_filter_call_method(st->volrecv,MS_VOLUME_SET_DB_GAIN,&gain);
+ }else ms_warning("Could not apply playback gain: gain control wasn't activated.");
+}
+
+/*This function is not static because used internally in linphone-daemon project*/
void _post_configure_audio_stream(AudioStream *st, LinphoneCore *lc, bool_t muted){
float mic_gain=lc->sound_conf.soft_mic_lev;
float thres = 0;
@@ -1832,13 +1694,13 @@ void _post_configure_audio_stream(AudioStream *st, LinphoneCore *lc, bool_t mute
int spk_agc;
if (!muted)
- linphone_core_set_mic_gain_db (lc, mic_gain);
+ set_mic_gain_db(st,mic_gain);
else
audio_stream_set_mic_gain(st,0);
recv_gain = lc->sound_conf.soft_play_lev;
if (recv_gain != 0) {
- linphone_core_set_playback_gain_db (lc,recv_gain);
+ set_playback_gain_db(st,recv_gain);
}
if (st->volsend){
@@ -1874,11 +1736,11 @@ void _post_configure_audio_stream(AudioStream *st, LinphoneCore *lc, bool_t mute
parametrize_equalizer(lc,st);
}
-static void post_configure_audio_streams(LinphoneCall*call){
+static void post_configure_audio_streams(LinphoneCall *call, bool_t muted){
AudioStream *st=call->audiostream;
LinphoneCore *lc=call->core;
- _post_configure_audio_stream(st,lc,call->audio_muted);
- if (lc->vtable.dtmf_received!=NULL){
+ _post_configure_audio_stream(st,lc,muted);
+ if (linphone_core_dtmf_received_has_listener(lc)){
audio_stream_play_received_dtmfs(call->audiostream,FALSE);
}
if (call->record_active)
@@ -1889,7 +1751,7 @@ static int get_ideal_audio_bw(LinphoneCall *call, const SalMediaDescription *md,
int remote_bw=0;
int upload_bw;
int total_upload_bw=linphone_core_get_upload_bandwidth(call->core);
- const LinphoneCallParams *params=&call->params;
+ const LinphoneCallParams *params=call->params;
bool_t will_use_video=linphone_core_media_description_contains_video_stream(md);
bool_t forced=FALSE;
@@ -1936,7 +1798,7 @@ static RtpProfile *make_profile(LinphoneCall *call, const SalMediaDescription *m
bool_t first=TRUE;
LinphoneCore *lc=call->core;
int up_ptime=0;
- const LinphoneCallParams *params=&call->params;
+ const LinphoneCallParams *params=call->params;
*used_pt=-1;
@@ -2044,6 +1906,7 @@ static void configure_rtp_session_for_rtcp_xr(LinphoneCore *lc, LinphoneCall *ca
static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cname, bool_t muted, bool_t send_ringbacktone, bool_t use_arc){
LinphoneCore *lc=call->core;
+ LpConfig* conf;
int used_pt=-1;
char rtcp_tool[128]={0};
const SalStreamDescription *stream;
@@ -2068,7 +1931,7 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna
call->audio_profile=make_profile(call,call->resultdesc,stream,&used_pt);
if (used_pt!=-1){
- call->current_params.audio_codec = rtp_profile_get_payload(call->audio_profile, used_pt);
+ call->current_params->audio_codec = rtp_profile_get_payload(call->audio_profile, used_pt);
if (playcard==NULL) {
ms_warning("No card defined for playback !");
}
@@ -2088,15 +1951,20 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna
/*playfile=NULL;*/
}
if (send_ringbacktone){
+ conf = linphone_core_get_config(lc);
captcard=NULL;
playfile=NULL;/* it is setup later*/
+ if( conf && lp_config_get_int(conf,"sound","send_ringback_without_playback", 0) == 1){
+ playcard = NULL;
+ recfile = NULL;
+ }
}
/*if playfile are supplied don't use soundcards*/
if (lc->use_files) {
captcard=NULL;
playcard=NULL;
}
- if (call->params.in_conference){
+ if (call->params->in_conference){
/* first create the graph without soundcard resources*/
captcard=playcard=NULL;
}
@@ -2108,10 +1976,12 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna
if (playcard && stream->max_rate>0) ms_snd_card_set_preferred_sample_rate(playcard, stream->max_rate);
if (captcard && stream->max_rate>0) ms_snd_card_set_preferred_sample_rate(captcard, stream->max_rate);
audio_stream_enable_adaptive_bitrate_control(call->audiostream,use_arc);
+ media_stream_set_adaptive_bitrate_algorithm(&call->audiostream->ms,
+ ms_qos_analyzer_algorithm_from_string(linphone_core_get_adaptive_rate_algorithm(lc)));
audio_stream_enable_adaptive_jittcomp(call->audiostream, linphone_core_audio_adaptive_jittcomp_enabled(lc));
- if (!call->params.in_conference && call->params.record_file){
- audio_stream_mixed_record_open(call->audiostream,call->params.record_file);
- call->current_params.record_file=ms_strdup(call->params.record_file);
+ if (!call->params->in_conference && call->params->record_file){
+ audio_stream_mixed_record_open(call->audiostream,call->params->record_file);
+ call->current_params->record_file=ms_strdup(call->params->record_file);
}
/* valid local tags are > 0 */
if (sal_stream_description_has_srtp(stream) == TRUE) {
@@ -2142,10 +2012,7 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna
captcard,
use_ec
);
- post_configure_audio_streams(call);
- if (muted && !send_ringbacktone){
- audio_stream_set_mic_gain(call->audiostream,0);
- }
+ post_configure_audio_streams(call, muted && !send_ringbacktone);
if (stream->dir==SalStreamSendOnly && playfile!=NULL){
int pause_time=500;
ms_filter_call_method(call->audiostream->soundread,MS_FILE_PLAYER_LOOP,&pause_time);
@@ -2154,13 +2021,13 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna
setup_ring_player(lc,call);
}
- if (call->params.in_conference){
+ if (call->params->in_conference){
/*transform the graph to connect it to the conference filter */
mute=stream->dir==SalStreamRecvOnly;
linphone_call_add_to_conf(call, mute);
}
- call->current_params.in_conference=call->params.in_conference;
- call->current_params.low_bandwidth=call->params.low_bandwidth;
+ call->current_params->in_conference=call->params->in_conference;
+ call->current_params->low_bandwidth=call->params->low_bandwidth;
}else ms_warning("No audio stream accepted ?");
}
}
@@ -2171,12 +2038,17 @@ static void linphone_call_start_video_stream(LinphoneCall *call, const char *cna
int used_pt=-1;
char rtcp_tool[128]={0};
const SalStreamDescription *vstream;
+ MSFilter* source = NULL;
+ bool_t reused_preview = FALSE;
snprintf(rtcp_tool,sizeof(rtcp_tool)-1,"%s-%s",linphone_core_get_user_agent_name(),linphone_core_get_user_agent_version());
/* shutdown preview */
if (lc->previewstream!=NULL) {
- video_preview_stop(lc->previewstream);
+
+ if( lc->video_conf.reuse_preview_source == FALSE) video_preview_stop(lc->previewstream);
+ else source = video_preview_stop_reuse_source(lc->previewstream);
+
lc->previewstream=NULL;
}
@@ -2193,11 +2065,13 @@ static void linphone_call_start_video_stream(LinphoneCall *call, const char *cna
MSWebCam *cam=lc->video_conf.device;
bool_t is_inactive=FALSE;
- call->current_params.video_codec = rtp_profile_get_payload(call->video_profile, used_pt);
- call->current_params.has_video=TRUE;
+ call->current_params->video_codec = rtp_profile_get_payload(call->video_profile, used_pt);
+ call->current_params->has_video=TRUE;
video_stream_enable_adaptive_bitrate_control(call->videostream,
linphone_core_adaptive_rate_control_enabled(lc));
+ media_stream_set_adaptive_bitrate_algorithm(&call->videostream->ms,
+ ms_qos_analyzer_algorithm_from_string(linphone_core_get_adaptive_rate_algorithm(lc)));
video_stream_enable_adaptive_jittcomp(call->videostream, linphone_core_video_adaptive_jittcomp_enabled(lc));
if (lc->video_conf.preview_vsize.width!=0)
video_stream_set_preview_size(call->videostream,lc->video_conf.preview_vsize);
@@ -2249,15 +2123,30 @@ static void linphone_call_start_video_stream(LinphoneCall *call, const char *cna
video_stream_set_device_rotation(call->videostream, lc->device_rotation);
video_stream_set_rtcp_information(call->videostream, cname, rtcp_tool);
video_stream_set_freeze_on_error(call->videostream, lp_config_get_int(lc->config, "video", "freeze_on_error", 0));
- video_stream_start(call->videostream,
- call->video_profile, rtp_addr, vstream->rtp_port,
- rtcp_addr,
- linphone_core_rtcp_enabled(lc) ? (vstream->rtcp_port ? vstream->rtcp_port : vstream->rtp_port+1) : 0,
- used_pt, linphone_core_get_video_jittcomp(lc), cam);
+ if( lc->video_conf.reuse_preview_source && source ){
+ ms_message("video_stream_start_with_source kept: %p", source);
+ video_stream_start_with_source(call->videostream,
+ call->video_profile, rtp_addr, vstream->rtp_port,
+ rtcp_addr,
+ linphone_core_rtcp_enabled(lc) ? (vstream->rtcp_port ? vstream->rtcp_port : vstream->rtp_port+1) : 0,
+ used_pt, linphone_core_get_video_jittcomp(lc), cam, source);
+ reused_preview = TRUE;
+ } else {
+ video_stream_start(call->videostream,
+ call->video_profile, rtp_addr, vstream->rtp_port,
+ rtcp_addr,
+ linphone_core_rtcp_enabled(lc) ? (vstream->rtcp_port ? vstream->rtcp_port : vstream->rtp_port+1) : 0,
+ used_pt, linphone_core_get_video_jittcomp(lc), cam);
+ }
}
}else ms_warning("No video stream accepted.");
}else{
- ms_warning("No valid video stream defined.");
+ ms_message("No valid video stream defined.");
+ }
+ if( reused_preview == FALSE && source != NULL ){
+ /* destroy not-reused source filter */
+ ms_warning("Video preview (%p) not reused: destroying it.", source);
+ ms_filter_destroy(source);
}
#endif
}
@@ -2271,8 +2160,8 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut
const SalStreamDescription *vstream=sal_media_description_find_best_stream(call->resultdesc,SalVideo);
#endif
- call->current_params.audio_codec = NULL;
- call->current_params.video_codec = NULL;
+ call->current_params->audio_codec = NULL;
+ call->current_params->video_codec = NULL;
if ((call->audiostream == NULL) && (call->videostream == NULL)) {
ms_fatal("start_media_stream() called without prior init !");
@@ -2290,9 +2179,9 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut
call, linphone_core_get_upload_bandwidth(lc),linphone_core_get_download_bandwidth(lc));
if (call->audiostream!=NULL) {
- linphone_call_start_audio_stream(call,cname,all_inputs_muted,send_ringbacktone,use_arc);
+ linphone_call_start_audio_stream(call,cname,all_inputs_muted||call->audio_muted,send_ringbacktone,use_arc);
}
- call->current_params.has_video=FALSE;
+ call->current_params->has_video=FALSE;
if (call->videostream!=NULL) {
if (call->audiostream) audio_stream_link_video(call->audiostream,call->videostream);
linphone_call_start_video_stream(call,cname,all_inputs_muted);
@@ -2302,7 +2191,7 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut
call->playing_ringbacktone=send_ringbacktone;
call->up_bw=linphone_core_get_upload_bandwidth(lc);
- if (call->params.media_encryption==LinphoneMediaEncryptionZRTP) {
+ if (call->params->media_encryption==LinphoneMediaEncryptionZRTP) {
OrtpZrtpParams params;
memset(¶ms,0,sizeof(OrtpZrtpParams));
/*call->current_params.media_encryption will be set later when zrtp is activated*/
@@ -2316,7 +2205,7 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut
}
#endif
}else{
- call->current_params.media_encryption=linphone_call_all_streams_encrypted(call) ?
+ call->current_params->media_encryption=linphone_call_all_streams_encrypted(call) ?
LinphoneMediaEncryptionSRTP : LinphoneMediaEncryptionNone;
}
@@ -2342,7 +2231,7 @@ void linphone_call_stop_media_streams_for_ice_gathering(LinphoneCall *call){
static bool_t update_stream_crypto_params(LinphoneCall *call, const SalStreamDescription *local_st_desc, SalStreamDescription *old_stream, SalStreamDescription *new_stream, MediaStream *ms){
int crypto_idx = find_crypto_index_from_tag(local_st_desc->crypto, new_stream->crypto_local_tag);
if (crypto_idx >= 0) {
- if (call->localdesc_changed & SAL_MEDIA_DESCRIPTION_CRYPTO_CHANGED)
+ if (call->localdesc_changed & SAL_MEDIA_DESCRIPTION_CRYPTO_KEYS_CHANGED)
media_stream_set_srtp_send_key(ms,new_stream->crypto[0].algo,local_st_desc->crypto[crypto_idx].master_key);
if (strcmp(old_stream->crypto[0].master_key,new_stream->crypto[0].master_key)!=0){
media_stream_set_srtp_recv_key(ms,new_stream->crypto[0].algo,new_stream->crypto[0].master_key);
@@ -2429,7 +2318,7 @@ static void linphone_call_stop_audio_stream(LinphoneCall *call) {
ms_filter_call_method(call->audiostream->ec,MS_ECHO_CANCELLER_GET_STATE_STRING,&state_str);
if (state_str){
ms_message("Writing echo canceler state, %i bytes",(int)strlen(state_str));
- lp_config_set_string(call->core->config,"sound","ec_state",state_str);
+ lp_config_write_relative_file(call->core->config, EC_STATE_STORE, state_str);
}
}
audio_stream_get_local_rtp_stats(call->audiostream,&call->log->local_stats);
@@ -2439,7 +2328,7 @@ static void linphone_call_stop_audio_stream(LinphoneCall *call) {
}
audio_stream_stop(call->audiostream);
call->audiostream=NULL;
- call->current_params.audio_codec = NULL;
+ call->current_params->audio_codec = NULL;
}
}
@@ -2455,7 +2344,7 @@ static void linphone_call_stop_video_stream(LinphoneCall *call) {
linphone_call_log_fill_stats(call->log,(MediaStream*)call->videostream);
video_stream_stop(call->videostream);
call->videostream=NULL;
- call->current_params.video_codec = NULL;
+ call->current_params->video_codec = NULL;
}
#endif
}
@@ -2756,38 +2645,49 @@ uint64_t linphone_call_stats_get_late_packets_cumulative_number(const LinphoneCa
if (!stats || !call)
return 0;
memset(&rtp_stats, 0, sizeof(rtp_stats));
- if (stats->type == LINPHONE_CALL_STATS_AUDIO)
+ if (stats->type == LINPHONE_CALL_STATS_AUDIO && call->audiostream != NULL)
audio_stream_get_local_rtp_stats(call->audiostream, &rtp_stats);
#ifdef VIDEO_ENABLED
- else
+ else if (call->videostream != NULL)
video_stream_get_local_rtp_stats(call->videostream, &rtp_stats);
#endif
return rtp_stats.outoftime;
}
/**
- * Enable recording of the call (voice-only).
- * 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 cp the call parameters
- * @param path path and filename of the file where audio/video streams are written.
- * The filename must have either .mkv or .wav extention. The video stream will be written
- * only if a MKV file is given.
-**/
-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);
+ * Get the bandwidth measurement of the received stream, expressed in kbit/s, including IP/UDP/RTP headers.
+ * @param[in] stats LinphoneCallStats object
+ * @return The bandwidth measurement of the received stream in kbit/s.
+ */
+float linphone_call_stats_get_download_bandwidth(const LinphoneCallStats *stats) {
+ return stats->download_bandwidth;
}
/**
- * Retrieves the path for the audio recoding of the call.
-**/
-const char *linphone_call_params_get_record_file(const LinphoneCallParams *cp){
- return cp->record_file;
+ * Get the bandwidth measurement of the sent stream, expressed in kbit/s, including IP/UDP/RTP headers.
+ * @param[in] stats LinphoneCallStats object
+ * @return The bandwidth measurement of the sent stream in kbit/s.
+ */
+float linphone_call_stats_get_upload_bandwidth(const LinphoneCallStats *stats) {
+ return stats->upload_bandwidth;
+}
+
+/**
+ * Get the state of ICE processing.
+ * @param[in] stats LinphoneCallStats object
+ * @return The state of ICE processing.
+ */
+LinphoneIceState linphone_call_stats_get_ice_state(const LinphoneCallStats *stats) {
+ return stats->ice_state;
+}
+
+/**
+ * Get the state of uPnP processing.
+ * @param[in] stats LinphoneCallStats object
+ * @return The state of uPnP processing.
+ */
+LinphoneUpnpState linphone_call_stats_get_upnp_state(const LinphoneCallStats *stats) {
+ return stats->upnp_state;
}
/**
@@ -2795,11 +2695,11 @@ const char *linphone_call_params_get_record_file(const LinphoneCallParams *cp){
* The output file where audio is recorded must be previously specified with linphone_call_params_set_record_file().
**/
void linphone_call_start_recording(LinphoneCall *call){
- if (!call->params.record_file){
+ if (!call->params->record_file){
ms_error("linphone_call_start_recording(): no output file specified. Use linphone_call_params_set_record_file().");
return;
}
- if (call->audiostream && !call->params.in_conference){
+ if (call->audiostream && !call->params->in_conference){
audio_stream_mixed_record_start(call->audiostream);
}
call->record_active=TRUE;
@@ -2809,7 +2709,7 @@ void linphone_call_start_recording(LinphoneCall *call){
* Stop call recording.
**/
void linphone_call_stop_recording(LinphoneCall *call){
- if (call->audiostream && !call->params.in_conference){
+ if (call->audiostream && !call->params->in_conference){
audio_stream_mixed_record_stop(call->audiostream);
}
call->record_active=FALSE;
@@ -2842,8 +2742,7 @@ static void linphone_core_disconnected(LinphoneCore *lc, LinphoneCall *call){
if (from) ms_free(from);
ms_message("On call [%p]: %s",call,temp);
- if (lc->vtable.display_warning!=NULL)
- lc->vtable.display_warning(lc,temp);
+ linphone_core_notify_display_warning(lc,temp);
linphone_core_terminate_call(lc,call);
linphone_core_play_named_tone(lc,LinphoneToneCallLost);
}
@@ -2854,17 +2753,16 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){
int ping_time;
if (evt == ORTP_EVENT_ICE_SESSION_PROCESSING_FINISHED) {
- LinphoneCallParams params;
- _linphone_call_params_copy(¶ms,&call->current_params);
- if (call->params.media_encryption == LinphoneMediaEncryptionZRTP) {
+ LinphoneCallParams *params = linphone_call_params_copy(call->current_params);
+ if (call->params->media_encryption == LinphoneMediaEncryptionZRTP) {
/* preserve media encryption param because at that time ZRTP negociation may still be ongoing*/
- params.media_encryption=call->params.media_encryption;
+ params->media_encryption=call->params->media_encryption;
}
switch (ice_session_state(call->ice_session)) {
case IS_Completed:
ice_session_select_candidates(call->ice_session);
if (ice_session_role(call->ice_session) == IR_Controlling) {
- linphone_core_update_call(call->core, call, ¶ms);
+ linphone_core_update_call(call->core, call, params);
}
break;
case IS_Failed:
@@ -2872,7 +2770,7 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){
ice_session_select_candidates(call->ice_session);
if (ice_session_role(call->ice_session) == IR_Controlling) {
/* At least one ICE session has succeeded, so perform a call update. */
- linphone_core_update_call(call->core, call, ¶ms);
+ linphone_core_update_call(call->core, call, params);
}
}
break;
@@ -2880,6 +2778,7 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){
break;
}
linphone_core_update_ice_state_in_call_stats(call);
+ linphone_call_params_unref(params);
} else if (evt == ORTP_EVENT_ICE_GATHERING_FINISHED) {
if (evd->info.ice_processing_successful==TRUE) {
@@ -2899,7 +2798,7 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){
linphone_core_start_update_call(call->core, call);
break;
case LinphoneCallUpdatedByRemote:
- linphone_core_start_accept_call_update(call->core, call);
+ linphone_core_start_accept_call_update(call->core, call,call->prevstate,linphone_call_state_to_string(call->prevstate));
break;
case LinphoneCallOutgoingInit:
linphone_call_stop_media_streams_for_ice_gathering(call);
@@ -2914,13 +2813,13 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){
}
} else if (evt == ORTP_EVENT_ICE_LOSING_PAIRS_COMPLETED) {
if (call->state==LinphoneCallUpdatedByRemote){
- linphone_core_start_accept_call_update(call->core, call);
+ linphone_core_start_accept_call_update(call->core, call,call->prevstate,linphone_call_state_to_string(call->prevstate));
linphone_core_update_ice_state_in_call_stats(call);
}
} else if (evt == ORTP_EVENT_ICE_RESTART_NEEDED) {
ice_session_restart(call->ice_session);
ice_session_set_role(call->ice_session, IR_Controlling);
- linphone_core_update_call(call->core, call, &call->current_params);
+ linphone_core_update_call(call->core, call, call->current_params);
}
}
@@ -2965,8 +2864,7 @@ void linphone_call_notify_stats_updated(LinphoneCall *call, int stream_index){
LinphoneCore *lc=call->core;
if (stats->updated){
linphone_reporting_on_rtcp_update(call, stream_index);
- if (lc->vtable.call_stats_updated)
- lc->vtable.call_stats_updated(lc, call, stats);
+ linphone_core_notify_call_stats_updated(lc, call, stats);
stats->updated = 0;
}
}
@@ -3053,7 +2951,7 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse
void linphone_call_log_completed(LinphoneCall *call){
LinphoneCore *lc=call->core;
- call->log->duration=time(NULL)-call->log->start_date_time;
+ call->log->duration=linphone_call_get_duration(call); /*store duration since connected*/
if (call->log->status==LinphoneCallMissed){
char *info;
@@ -3061,11 +2959,10 @@ void linphone_call_log_completed(LinphoneCall *call){
info=ortp_strdup_printf(ngettext("You have missed %i call.",
"You have missed %i calls.", lc->missed_calls),
lc->missed_calls);
- if (lc->vtable.display_status!=NULL)
- lc->vtable.display_status(lc,info);
+ linphone_core_notify_display_status(lc,info);
ms_free(info);
}
- lc->call_logs=ms_list_prepend(lc->call_logs,(void *)call->log);
+ lc->call_logs=ms_list_prepend(lc->call_logs,linphone_call_log_ref(call->log));
if (ms_list_size(lc->call_logs)>lc->max_call_logs){
MSList *elem,*prevelem=NULL;
/*find the last element*/
@@ -3073,12 +2970,10 @@ void linphone_call_log_completed(LinphoneCall *call){
prevelem=elem;
}
elem=prevelem;
- linphone_call_log_destroy((LinphoneCallLog*)elem->data);
+ linphone_call_log_unref((LinphoneCallLog*)elem->data);
lc->call_logs=ms_list_remove_link(lc->call_logs,elem);
}
- if (lc->vtable.call_log_updated!=NULL){
- lc->vtable.call_log_updated(lc,call->log);
- }
+ linphone_core_notify_call_log_updated(lc,call->log);
call_logs_write_to_config_file(lc);
}
@@ -3097,13 +2992,12 @@ void linphone_call_set_transfer_state(LinphoneCall* call, LinphoneCallState stat
,linphone_call_state_to_string(call->transfer_state)
,linphone_call_state_to_string(state));
call->transfer_state = state;
- if (lc->vtable.transfer_state_changed)
- lc->vtable.transfer_state_changed(lc, call, state);
+ linphone_core_notify_transfer_state_changed(lc, call, state);
}
}
bool_t linphone_call_is_in_conference(const LinphoneCall *call) {
- return call->params.in_conference;
+ return call->params->in_conference;
}
/**
@@ -3137,7 +3031,7 @@ void linphone_call_zoom_video(LinphoneCall* call, float zoom_factor, float* cx,
zoom[0] = zoom_factor;
zoom[1] = *cx;
zoom[2] = *cy;
- ms_filter_call_method(vstream->output, MS_VIDEO_DISPLAY_ZOOM, &zoom);
+ ms_filter_call_method(vstream->output, MS_VIDEO_DISPLAY_ZOOM, &zoom);
}else ms_warning("Could not apply zoom: video output wasn't activated.");
}
@@ -3147,7 +3041,7 @@ static LinphoneAddress *get_fixed_contact(LinphoneCore *lc, LinphoneCall *call ,
const char *localip=call->localip;
/* first use user's supplied ip address if asked*/
- if (linphone_core_get_firewall_policy(lc)==LinphonePolicyUseNatAddress){
+ if (_linphone_core_get_firewall_policy(lc)==LinphonePolicyUseNatAddress){
ctt=linphone_core_get_primary_contact_parsed(lc);
linphone_address_set_domain(ctt,linphone_core_get_nat_address_resolved(lc));
ret=ctt;
@@ -3193,3 +3087,16 @@ void linphone_call_set_contact_op(LinphoneCall* call) {
linphone_address_destroy(contact);
}
}
+
+LinphonePlayer *linphone_call_get_player(LinphoneCall *call){
+ if (call->player==NULL)
+ call->player=linphone_call_build_player(call);
+ return call->player;
+}
+
+void linphone_call_set_new_params(LinphoneCall *call, const LinphoneCallParams *params){
+ LinphoneCallParams *cp=NULL;
+ if (params) cp=linphone_call_params_copy(params);
+ if (call->params) linphone_call_params_unref(call->params);
+ call->params=cp;
+}
diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c
index 4a5a11554..ef81ef8c1 100644
--- a/coreapi/linphonecore.c
+++ b/coreapi/linphonecore.c
@@ -17,8 +17,6 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#define _GNU_SOURCE
-
#include "linphonecore.h"
#include "sipsetup.h"
#include "lpconfig.h"
@@ -26,6 +24,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "quality_reporting.h"
#include
+#include
+#include
#include
#include
#include "mediastreamer2/mediastream.h"
@@ -42,7 +42,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifdef HAVE_CONFIG_H
#include "config.h"
-#include "liblinphone_gitversion.h"
+#ifndef ANDROID /*on Android LIBLINPHONE version is passed from root Makefile*/
+ #include "liblinphone_gitversion.h"
+#endif
#else
#ifndef LIBLINPHONE_GIT_VERSION
#define LIBLINPHONE_GIT_VERSION "unknown"
@@ -53,6 +55,24 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "TargetConditionals.h"
#endif
+#ifdef HAVE_ZLIB
+#define COMPRESSED_LOG_COLLECTION_EXTENSION "gz"
+#ifdef WIN32
+#include
+#include
+#define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
+#else
+#define SET_BINARY_MODE(file)
+#endif
+#include
+#else
+#define COMPRESSED_LOG_COLLECTION_EXTENSION "txt"
+#endif
+#define LOG_COLLECTION_DEFAULT_PATH "."
+#define LOG_COLLECTION_DEFAULT_PREFIX "linphone"
+#define LOG_COLLECTION_DEFAULT_MAX_FILE_SIZE (10 * 1024 * 1024)
+
+
/*#define UNSTANDART_GSM_11K 1*/
#define ROOT_CA_FILE PACKAGE_DATA_DIR "/linphone/rootca.pem"
@@ -64,6 +84,12 @@ static const char *liblinphone_version=
LIBLINPHONE_VERSION
#endif
;
+static OrtpLogFunc liblinphone_log_func = NULL;
+static LinphoneLogCollectionState liblinphone_log_collection_state = LinphoneLogCollectionDisabled;
+static char * liblinphone_log_collection_path = NULL;
+static char * liblinphone_log_collection_prefix = NULL;
+static int liblinphone_log_collection_max_file_size = LOG_COLLECTION_DEFAULT_MAX_FILE_SIZE;
+static ortp_mutex_t liblinphone_log_collection_mutex;
static bool_t liblinphone_serialize_logs = FALSE;
static void set_network_reachable(LinphoneCore* lc,bool_t isReachable, time_t curtime);
static void linphone_core_run_hooks(LinphoneCore *lc);
@@ -102,345 +128,486 @@ int lc_callback_obj_invoke(LCCallbackObj *obj, LinphoneCore *lc){
}
-/*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);
+/**
+ * Returns TRUE if the LinphoneCall asked to autoanswer
+ *
+**/
+bool_t linphone_call_asked_to_autoanswer(LinphoneCall *call){
+ //return TRUE if the unique(for the moment) incoming call asked to be autoanswered
+ if(call)
+ return sal_call_autoanswer_asked(call->op);
+ else
+ return FALSE;
}
-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);
+int linphone_core_get_current_call_duration(const LinphoneCore *lc){
+ LinphoneCall *call=linphone_core_get_current_call((LinphoneCore *)lc);
+ if (call) return linphone_call_get_duration(call);
+ return -1;
}
-LinphoneCallLog * linphone_call_log_new(LinphoneCall *call, LinphoneAddress *from, LinphoneAddress *to){
- LinphoneCallLog *cl=ms_new0(LinphoneCallLog,1);
- cl->dir=call->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;
+const LinphoneAddress *linphone_core_get_current_call_remote_address(struct _LinphoneCore *lc){
+ LinphoneCall *call=linphone_core_get_current_call(lc);
+ if (call==NULL) return NULL;
+ return linphone_call_get_remote_address(call);
+}
- cl->reporting.reports[LINPHONE_CALL_STATS_AUDIO]=linphone_reporting_new();
- cl->reporting.reports[LINPHONE_CALL_STATS_VIDEO]=linphone_reporting_new();
- return cl;
+void linphone_core_set_log_handler(OrtpLogFunc logfunc) {
+ ortp_set_log_handler(logfunc);
}
-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(;imax_call_logs;++i){
- snprintf(logsection,sizeof(logsection),"call_log_%i",i);
- lp_config_clean_section(cfg,logsection);
- }
-}
-
-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
+void linphone_core_set_log_file(FILE *file) {
+ if (file == NULL) file = stdout;
+ ortp_set_log_file(file);
}
-static 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=ms_new0(LinphoneCallLog,1);
- cl->dir=lp_config_get_int(cfg,logsection,"dir",0);
- cl->status=lp_config_get_int(cfg,logsection,"status",0);
- tmp=lp_config_get_string(cfg,logsection,"from",NULL);
- if (tmp) cl->from=linphone_address_new(tmp);
- tmp=lp_config_get_string(cfg,logsection,"to",NULL);
- if (tmp) cl->to=linphone_address_new(tmp);
- 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;
+void linphone_core_set_log_level(OrtpLogLevel loglevel) {
+ ortp_set_log_level_mask(loglevel);
+ if (loglevel == 0) {
+ sal_disable_logs();
+ } else {
+ sal_enable_logs();
}
}
+static void linphone_core_log_collection_handler(OrtpLogLevel level, const char *fmt, va_list args) {
+ const char *lname="undef";
+ char *msg;
+ char *log_filename1;
+ char *log_filename2;
+ FILE *log_file;
+ struct timeval tp;
+ struct tm *lt;
+ time_t tt;
+ struct stat statbuf;
+ if (liblinphone_log_func != NULL) {
+ liblinphone_log_func(level, fmt, args);
+ }
-/**
- * @addtogroup call_logs
- * @{
-**/
-
-/**
- * Returns a human readable string describing the call.
- *
- * @note: the returned char* must be freed by the application (use ms_free()).
-**/
-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");
+ ortp_gettimeofday(&tp, NULL);
+ tt = (time_t)tp.tv_sec;
+ lt = localtime((const time_t*)&tt);
+ switch(level){
+ case ORTP_DEBUG:
+ lname = "DEBUG";
break;
- case LinphoneCallSuccess:
- status=_("completed");
+ case ORTP_MESSAGE:
+ lname = "MESSAGE";
break;
- case LinphoneCallMissed:
- status=_("missed");
+ case ORTP_WARNING:
+ lname = "WARNING";
+ break;
+ case ORTP_ERROR:
+ lname = "ERROR";
+ break;
+ case ORTP_FATAL:
+ lname = "FATAL";
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;
-}
-
-/**
- * Returns RTP statistics computed locally regarding the call.
- *
-**/
-const rtp_stats_t *linphone_call_log_get_local_stats(const LinphoneCallLog *cl){
- return &cl->local_stats;
-}
+ ortp_fatal("Bad level !");
+ }
+ msg = ortp_strdup_vprintf(fmt, args);
+
+ log_filename1 = ortp_strdup_printf("%s/%s1.log",
+ liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH,
+ liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX);
+ log_filename2 = ortp_strdup_printf("%s/%s2.log",
+ liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH,
+ liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX);
+ ortp_mutex_lock(&liblinphone_log_collection_mutex);
+ log_file = fopen(log_filename1, "a");
+ fstat(fileno(log_file), &statbuf);
+ if (statbuf.st_size > liblinphone_log_collection_max_file_size) {
+ fclose(log_file);
+ log_file = fopen(log_filename2, "a");
+ fstat(fileno(log_file), &statbuf);
+ if (statbuf.st_size > liblinphone_log_collection_max_file_size) {
+ fclose(log_file);
+ unlink(log_filename1);
+ rename(log_filename2, log_filename1);
+ log_file = fopen(log_filename2, "a");
+ }
+ }
+ fprintf(log_file,"%i-%.2i-%.2i %.2i:%.2i:%.2i:%.3i %s %s\n",
+ 1900 + lt->tm_year, lt->tm_mon + 1, lt->tm_mday, lt->tm_hour, lt->tm_min, lt->tm_sec, (int)(tp.tv_usec / 1000), lname, msg);
+ fflush(log_file);
+ fclose(log_file);
+ ortp_mutex_unlock(&liblinphone_log_collection_mutex);
-/**
- * Returns RTP statistics computed by remote end and sent back via RTCP.
- *
- * @note Not implemented yet.
-**/
-const rtp_stats_t *linphone_call_log_get_remote_stats(const LinphoneCallLog *cl){
- return &cl->remote_stats;
+ ortp_free(log_filename1);
+ ortp_free(log_filename2);
+ ortp_free(msg);
}
-const char *linphone_call_log_get_call_id(const LinphoneCallLog *cl){
- return cl->call_id;
+const char * linphone_core_get_log_collection_path(void) {
+ if (liblinphone_log_collection_path != NULL) {
+ return liblinphone_log_collection_path;
+ }
+ return LOG_COLLECTION_DEFAULT_PATH;
}
-/**
- * Assign a user pointer to the call log.
-**/
-void linphone_call_log_set_user_pointer(LinphoneCallLog *cl, void *up){
- cl->user_pointer=up;
+void linphone_core_set_log_collection_path(const char *path) {
+ if (liblinphone_log_collection_path != NULL) {
+ ms_free(liblinphone_log_collection_path);
+ liblinphone_log_collection_path = NULL;
+ }
+ if (path != NULL) {
+ liblinphone_log_collection_path = ms_strdup(path);
+ }
}
-/**
- * Returns the user pointer associated with the call log.
-**/
-void *linphone_call_log_get_user_pointer(const LinphoneCallLog *cl){
- return cl->user_pointer;
+const char * linphone_core_get_log_collection_prefix(void) {
+ if (liblinphone_log_collection_prefix != NULL) {
+ return liblinphone_log_collection_prefix;
+ }
+ return LOG_COLLECTION_DEFAULT_PREFIX;
}
-
-
-/**
- * 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.
- *
-**/
-void linphone_call_log_set_ref_key(LinphoneCallLog *cl, const char *refkey){
- if (cl->refkey!=NULL){
- ms_free(cl->refkey);
- cl->refkey=NULL;
+void linphone_core_set_log_collection_prefix(const char *prefix) {
+ if (liblinphone_log_collection_prefix != NULL) {
+ ms_free(liblinphone_log_collection_prefix);
+ liblinphone_log_collection_prefix = NULL;
+ }
+ if (prefix != NULL) {
+ liblinphone_log_collection_prefix = ms_strdup(prefix);
}
- if (refkey) cl->refkey=ms_strdup(refkey);
}
-/**
- * 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.
- *
-**/
-const char *linphone_call_log_get_ref_key(const LinphoneCallLog *cl){
- return cl->refkey;
+int linphone_core_get_log_collection_max_file_size(void) {
+ return liblinphone_log_collection_max_file_size;
}
-/**
- * Returns origin (ie from) address of the call.
-**/
-LinphoneAddress *linphone_call_log_get_from(LinphoneCallLog *cl){
- return cl->from;
+void linphone_core_set_log_collection_max_file_size(int size) {
+ liblinphone_log_collection_max_file_size = size;
}
-/**
- * Returns destination address (ie to) of the call.
-**/
-LinphoneAddress *linphone_call_log_get_to(LinphoneCallLog *cl){
- return cl->to;
+const char *linphone_core_get_log_collection_upload_server_url(LinphoneCore *core) {
+ return lp_config_get_string(core->config, "misc", "log_collection_upload_server_url", NULL);
}
-/**
- * Returns remote address (that is from or to depending on call direction).
-**/
-LinphoneAddress *linphone_call_log_get_remote_address(LinphoneCallLog *cl){
- return (cl->dir == LinphoneCallIncoming) ? cl->from : cl->to;
+void linphone_core_set_log_collection_upload_server_url(LinphoneCore *core, const char *server_url) {
+ lp_config_set_string(core->config, "misc", "log_collection_upload_server_url", server_url);
}
-/**
- * Returns the direction of the call.
-**/
-LinphoneCallDir linphone_call_log_get_dir(LinphoneCallLog *cl){
- return cl->dir;
+LinphoneLogCollectionState linphone_core_log_collection_enabled(void) {
+ return liblinphone_log_collection_state;
}
-/**
- * Returns the status of the call.
-**/
-LinphoneCallStatus linphone_call_log_get_status(LinphoneCallLog *cl){
- return cl->status;
+void linphone_core_enable_log_collection(LinphoneLogCollectionState state) {
+ /* at first call of this function, set liblinphone_log_func to the current
+ * ortp log function */
+ if( liblinphone_log_func == NULL ){
+ liblinphone_log_func = ortp_logv_out;
+ }
+ liblinphone_log_collection_state = state;
+ if (state != LinphoneLogCollectionDisabled) {
+ ortp_mutex_init(&liblinphone_log_collection_mutex, NULL);
+ if (state == LinphoneLogCollectionEnabledWithoutPreviousLogHandler) {
+ liblinphone_log_func = NULL;
+ } else {
+ liblinphone_log_func = ortp_logv_out;
+ }
+ ortp_set_log_handler(linphone_core_log_collection_handler);
+ } else {
+ ortp_set_log_handler(liblinphone_log_func);
+ }
}
-/**
- * Returns the start date of the call, expressed as a POSIX time_t.
-**/
-time_t linphone_call_log_get_start_date(LinphoneCallLog *cl){
- return cl->start_date_time;
+static void delete_log_collection_upload_file(void) {
+ char *filename = ms_strdup_printf("%s/%s_log.%s",
+ liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH,
+ liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX,
+ COMPRESSED_LOG_COLLECTION_EXTENSION);
+ unlink(filename);
+ ms_free(filename);
}
-/**
- * Returns duration of the call.
-**/
-int linphone_call_log_get_duration(LinphoneCallLog *cl){
- return cl->duration;
+static void process_io_error_upload_log_collection(void *data, const belle_sip_io_error_event_t *event) {
+ LinphoneCore *core = (LinphoneCore *)data;
+ ms_error("I/O Error during log collection upload to %s", linphone_core_get_log_collection_upload_server_url(core));
+ linphone_core_notify_log_collection_upload_state_changed(core, LinphoneCoreLogCollectionUploadStateNotDelivered, "I/O Error");
+ delete_log_collection_upload_file();
}
-/**
- * Returns overall quality indication of the call.
-**/
-float linphone_call_log_get_quality(LinphoneCallLog *cl){
- return cl->quality;
+static void process_auth_requested_upload_log_collection(void *data, belle_sip_auth_event_t *event) {
+ LinphoneCore *core = (LinphoneCore *)data;
+ ms_error("Error during log collection upload: auth requested to connect %s", linphone_core_get_log_collection_upload_server_url(core));
+ linphone_core_notify_log_collection_upload_state_changed(core, LinphoneCoreLogCollectionUploadStateNotDelivered, "Auth requested");
+ delete_log_collection_upload_file();
}
+
/**
- * return true if video was enabled at the end of the call
+ * Callback called when posting a log collection file to server (following rcs5.1 recommendation)
+ *
+ * @param[in] bh The body handler
+ * @param[in] msg The belle sip message
+ * @param[in] data The user data associated with the handler, contains the LinphoneCore object
+ * @param[in] offset The current position in the input buffer
+ * @param[in] buffer The ouput buffer where to copy the data to be uploaded
+ * @param[in,out] size The size in byte of the data requested, as output it will contain the effective copied size
+ *
*/
-bool_t linphone_call_log_video_enabled(LinphoneCallLog *cl) {
- return cl->video_enabled;
-}
-/** @} */
+static int log_collection_upload_on_send_body(belle_sip_user_body_handler_t *bh, belle_sip_message_t *msg, void *data, size_t offset, uint8_t *buffer, size_t *size) {
+ LinphoneCore *core = (LinphoneCore *)data;
+
+ /* If we've not reach the end of file yet, fill the buffer with more data */
+ if (offset < core->log_collection_upload_information->size) {
+ char *log_filename = ms_strdup_printf("%s/%s_log.%s",
+ liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH,
+ liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX,
+ COMPRESSED_LOG_COLLECTION_EXTENSION);
+#ifdef HAVE_ZLIB
+ FILE *log_file = fopen(log_filename, "rb");
+#else
+ FILE *log_file = fopen(log_filename, "r");
+#endif
+ fseek(log_file, offset, SEEK_SET);
+ *size = fread(buffer, 1, *size, log_file);
+ fclose(log_file);
+ ms_free(log_filename);
+ }
-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]);
+ return BELLE_SIP_CONTINUE;
+}
- ms_free(cl);
+/**
+ * Callback called during upload of a log collection to server.
+ * It is just forwarding the call and some parameters to the vtable defined callback.
+ */
+static void log_collection_upload_on_progress(belle_sip_body_handler_t *bh, belle_sip_message_t *msg, void *data, size_t offset, size_t total) {
+ LinphoneCore *core = (LinphoneCore *)data;
+ linphone_core_notify_log_collection_upload_progress_indication(core, offset, total);
}
/**
- * Returns TRUE if the LinphoneCall asked to autoanswer
+ * Callback function called when we have a response from server during the upload of the log collection to the server (rcs5.1 recommandation)
+ * Note: The first post is empty and the server shall reply a 204 (No content) message, this will trigger a new post request to the server
+ * to upload the file. The server response to this second post is processed by this same function
*
-**/
-bool_t linphone_call_asked_to_autoanswer(LinphoneCall *call){
- //return TRUE if the unique(for the moment) incoming call asked to be autoanswered
- if(call)
- return sal_call_autoanswer_asked(call->op);
- else
- return FALSE;
+ * @param[in] data The user-defined pointer associated with the request, it contains the LinphoneCore object
+ * @param[in] event The response from server
+ */
+static void process_response_from_post_file_log_collection(void *data, const belle_http_response_event_t *event) {
+ LinphoneCore *core = (LinphoneCore *)data;
+
+ /* Check the answer code */
+ if (event->response) {
+ int code = belle_http_response_get_status_code(event->response);
+ if (code == 204) { /* This is the reply to the first post to the server - an empty file */
+ /* Start uploading the file */
+ belle_http_request_listener_callbacks_t cbs = { 0 };
+ belle_http_request_listener_t *l;
+ belle_generic_uri_t *uri;
+ belle_http_request_t *req;
+ belle_sip_multipart_body_handler_t *bh;
+ char* ua;
+ char *first_part_header;
+ belle_sip_user_body_handler_t *first_part_bh;
+
+ linphone_core_notify_log_collection_upload_state_changed(core, LinphoneCoreLogCollectionUploadStateInProgress, NULL);
+
+ /* Temporary storage for the Content-disposition header value */
+ first_part_header = belle_sip_strdup_printf("form-data; name=\"File\"; filename=\"%s\"", core->log_collection_upload_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(core->log_collection_upload_information->size, NULL, NULL, log_collection_upload_on_send_body, core);
+ 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(core->log_collection_upload_information->type, core->log_collection_upload_information->subtype));
+
+ /* Insert it in a multipart body handler which will manage the boundaries of multipart message */
+ bh = belle_sip_multipart_body_handler_new(log_collection_upload_on_progress, core, (belle_sip_body_handler_t *)first_part_bh);
+ ua = ms_strdup_printf("%s/%s", linphone_core_get_user_agent_name(), linphone_core_get_user_agent_version());
+ uri = belle_generic_uri_parse(linphone_core_get_log_collection_upload_server_url(core));
+ req = belle_http_request_create("POST", uri, belle_sip_header_create("User-Agent", ua), NULL);
+ ms_free(ua);
+ belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(req), BELLE_SIP_BODY_HANDLER(bh));
+ cbs.process_response = process_response_from_post_file_log_collection;
+ cbs.process_io_error = process_io_error_upload_log_collection;
+ cbs.process_auth_requested = process_auth_requested_upload_log_collection;
+ l = belle_http_request_listener_create_from_callbacks(&cbs, core);
+ belle_http_provider_send_request(core->http_provider, req, l);
+ }
+ if (code == 200) { /* The file has been uploaded correctly, get the server reply */
+ xmlDocPtr xmlMessageBody;
+ xmlNodePtr cur;
+ xmlChar *file_url = NULL;
+ const char *body = belle_sip_message_get_body((belle_sip_message_t *)event->response);
+ xmlMessageBody = xmlParseDoc((const xmlChar *)body);
+ cur = xmlDocGetRootElement(xmlMessageBody);
+ if (cur != NULL) {
+ cur = cur->xmlChildrenNode;
+ while (cur != NULL) {
+ if (!xmlStrcmp(cur->name, (const xmlChar *)"file-info")) { /* we found a file info node, check it has a type="file" attribute */
+ xmlChar *typeAttribute = xmlGetProp(cur, (const xmlChar *)"type");
+ if (!xmlStrcmp(typeAttribute, (const xmlChar *)"file")) { /* this is the node we are looking for */
+ cur = cur->xmlChildrenNode; /* now loop on the content of the file-info node */
+ while (cur != NULL) {
+ if (!xmlStrcmp(cur->name, (const xmlChar *)"data")) {
+ file_url = xmlGetProp(cur, (const xmlChar *)"url");
+ }
+ cur=cur->next;
+ }
+ xmlFree(typeAttribute);
+ break;
+ }
+ xmlFree(typeAttribute);
+ }
+ cur = cur->next;
+ }
+ }
+ if (file_url != NULL) {
+ linphone_core_notify_log_collection_upload_state_changed(core, LinphoneCoreLogCollectionUploadStateDelivered, (const char *)file_url);
+ }
+ delete_log_collection_upload_file();
+ }
+ }
}
-int linphone_core_get_current_call_duration(const LinphoneCore *lc){
- LinphoneCall *call=linphone_core_get_current_call((LinphoneCore *)lc);
- if (call) return linphone_call_get_duration(call);
- return -1;
-}
+#ifdef HAVE_ZLIB
+#define COMPRESS_FILE_PTR gzFile
+#define COMPRESS_OPEN gzopen
+#define COMPRESS_CLOSE gzclose
+#else
+#define COMPRESS_FILE_PTR FILE*
+#define COMPRESS_OPEN fopen
+#define COMPRESS_CLOSE fclose
+#endif
-const LinphoneAddress *linphone_core_get_current_call_remote_address(struct _LinphoneCore *lc){
- LinphoneCall *call=linphone_core_get_current_call(lc);
- if (call==NULL) return NULL;
- return linphone_call_get_remote_address(call);
+/**
+ * If zlib is not available the two log files are simply concatenated.
+ */
+static int compress_file(FILE *input_file, COMPRESS_FILE_PTR output_file) {
+ char buffer[131072]; /* 128kB */
+ int bytes;
+
+ while ((bytes = fread(buffer, 1, sizeof(buffer), input_file)) > 0) {
+ if (bytes < 0) return bytes;
+#ifdef HAVE_ZLIB
+ bytes = gzwrite(output_file, buffer, bytes);
+#else
+ bytes = fwrite(buffer, 1, bytes, output_file);
+#endif
+ if (bytes < 0) return bytes;
+ }
+ return 0;
}
-void linphone_core_set_log_handler(OrtpLogFunc logfunc) {
- ortp_set_log_handler(logfunc);
+static int prepare_log_collection_file_to_upload(const char *filename) {
+ char *input_filename = NULL;
+ char *output_filename = NULL;
+ FILE *input_file = NULL;
+ COMPRESS_FILE_PTR output_file = NULL;
+ int ret = 0;
+
+ ortp_mutex_lock(&liblinphone_log_collection_mutex);
+ output_filename = ms_strdup_printf("%s/%s",
+ liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH, filename);
+ output_file = COMPRESS_OPEN(output_filename, "w");
+ if (output_file == NULL) goto error;
+ input_filename = ms_strdup_printf("%s/%s1.log",
+ liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH,
+ liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX);
+ input_file = fopen(input_filename, "r");
+ if (input_file == NULL) goto error;
+ ret = compress_file(input_file, output_file);
+ if (ret < 0) goto error;
+ fclose(input_file);
+ ms_free(input_filename);
+ input_filename = ms_strdup_printf("%s/%s2.log",
+ liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH,
+ liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX);
+ input_file = fopen(input_filename, "r");
+ if (input_file != NULL) {
+ ret = compress_file(input_file, output_file);
+ if (ret < 0) goto error;
+ }
+
+error:
+ if (input_file != NULL) fclose(input_file);
+ if (output_file != NULL) COMPRESS_CLOSE(output_file);
+ if (input_filename != NULL) ms_free(input_filename);
+ if (output_filename != NULL) ms_free(output_filename);
+ ortp_mutex_unlock(&liblinphone_log_collection_mutex);
+ return ret;
}
-void linphone_core_set_log_file(FILE *file) {
- if (file == NULL) file = stdout;
- ortp_set_log_file(file);
+static size_t get_size_of_file_to_upload(const char *filename) {
+ struct stat statbuf;
+ char *output_filename = ms_strdup_printf("%s/%s",
+ liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH, filename);
+ FILE *output_file = fopen(output_filename, "rb");
+ fstat(fileno(output_file), &statbuf);
+ fclose(output_file);
+ ms_free(output_filename);
+ return statbuf.st_size;
+}
+
+void linphone_core_upload_log_collection(LinphoneCore *core) {
+ if ((core->log_collection_upload_information == NULL) && (linphone_core_get_log_collection_upload_server_url(core) != NULL) && (liblinphone_log_collection_state != LinphoneLogCollectionDisabled)) {
+ /* 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;
+ belle_generic_uri_t *uri;
+ belle_http_request_t *req;
+
+ core->log_collection_upload_information = (LinphoneContent *)malloc(sizeof(LinphoneContent));
+ memset(core->log_collection_upload_information, 0, sizeof(LinphoneContent));
+#ifdef HAVE_ZLIB
+ core->log_collection_upload_information->type = "application";
+ core->log_collection_upload_information->subtype = "gzip";
+#else
+ core->log_collection_upload_information->type = "text";
+ core->log_collection_upload_information->subtype = "plain";
+#endif
+ core->log_collection_upload_information->name = ms_strdup_printf("%s_log.%s",
+ liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX,
+ COMPRESSED_LOG_COLLECTION_EXTENSION);
+ if (prepare_log_collection_file_to_upload(core->log_collection_upload_information->name) < 0) return;
+ core->log_collection_upload_information->size = get_size_of_file_to_upload(core->log_collection_upload_information->name);
+ uri = belle_generic_uri_parse(linphone_core_get_log_collection_upload_server_url(core));
+ req = belle_http_request_create("POST", uri, NULL, NULL, NULL);
+ cbs.process_response = process_response_from_post_file_log_collection;
+ cbs.process_io_error = process_io_error_upload_log_collection;
+ cbs.process_auth_requested = process_auth_requested_upload_log_collection;
+ l = belle_http_request_listener_create_from_callbacks(&cbs, core);
+ belle_http_provider_send_request(core->http_provider, req, l);
+ }
+}
+
+char * linphone_core_compress_log_collection(LinphoneCore *core) {
+ char *filename = NULL;
+ if (liblinphone_log_collection_state == LinphoneLogCollectionDisabled) return NULL;
+ filename = ms_strdup_printf("%s_log.%s",
+ liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX,
+ COMPRESSED_LOG_COLLECTION_EXTENSION);
+ if (prepare_log_collection_file_to_upload(filename) < 0) {
+ ms_free(filename);
+ return NULL;
+ }
+ ms_free(filename);
+ return ms_strdup_printf("%s/%s_log.%s",
+ liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH,
+ liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX,
+ COMPRESSED_LOG_COLLECTION_EXTENSION);
}
-void linphone_core_set_log_level(OrtpLogLevel loglevel) {
- ortp_set_log_level_mask(loglevel);
- if (loglevel == 0) {
- sal_disable_logs();
- } else {
- sal_enable_logs();
- }
+void linphone_core_reset_log_collection(LinphoneCore *core) {
+ char *filename;
+ ortp_mutex_lock(&liblinphone_log_collection_mutex);
+ delete_log_collection_upload_file();
+ filename = ms_strdup_printf("%s/%s1.log",
+ liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH,
+ liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX);
+ unlink(filename);
+ ms_free(filename);
+ filename = ms_strdup_printf("%s/%s2.log",
+ liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH,
+ liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX);
+ unlink(filename);
+ ms_free(filename);
+ ortp_mutex_unlock(&liblinphone_log_collection_mutex);
}
/**
@@ -725,6 +892,7 @@ static void sip_config_read(LinphoneCore *lc)
LinphoneProxyConfig *cfg=linphone_proxy_config_new_from_config_file(lc,i);
if (cfg!=NULL){
linphone_core_add_proxy_config(lc,cfg);
+ linphone_proxy_config_unref(cfg);
}else{
break;
}
@@ -762,6 +930,7 @@ static void sip_config_read(LinphoneCore *lc)
sal_enable_sip_update_method(lc->sal,lp_config_get_int(lc->config,"sip","sip_update",1));
lc->sip_conf.vfu_with_info=lp_config_get_int(lc->config,"sip","vfu_with_info",1);
linphone_core_set_sip_transport_timeout(lc, lp_config_get_int(lc->config, "sip", "transport_timeout", 63000));
+ sal_set_supported_tags(lc->sal,lp_config_get_string(lc->config,"sip","supported","replaces, outbound"));
}
static void rtp_config_read(LinphoneCore *lc)
@@ -804,6 +973,7 @@ static void rtp_config_read(LinphoneCore *lc)
adaptive_jitt_comp_enabled = lp_config_get_int(lc->config, "rtp", "video_adaptive_jitt_comp_enabled", TRUE);
linphone_core_enable_video_adaptive_jittcomp(lc, adaptive_jitt_comp_enabled);
lc->rtp_conf.disable_upnp = lp_config_get_int(lc->config, "rtp", "disable_upnp", FALSE);
+ linphone_core_set_avpf_mode(lc,lp_config_get_int(lc->config,"rtp","avpf",0));
}
static PayloadType * find_payload(RtpProfile *prof, const char *mime_type, int clock_rate, int channels, const char *recv_fmtp){
@@ -955,6 +1125,7 @@ static void codecs_config_read(LinphoneCore *lc)
}
}
audio_codecs=add_missing_codecs(lc,SalAudio,audio_codecs);
+
for (i=0;get_codec(lc,"video_codec",i,&pt);i++){
if (pt){
if (!ms_filter_codec_supported(pt->mime_type)){
@@ -988,7 +1159,7 @@ static void build_video_devices_table(LinphoneCore *lc){
static void video_config_read(LinphoneCore *lc){
#ifdef VIDEO_ENABLED
- int capture, display, self_view;
+ int capture, display, self_view, reuse_source;
int automatic_video=1;
#endif
const char *str;
@@ -1017,12 +1188,14 @@ static void video_config_read(LinphoneCore *lc){
capture=lp_config_get_int(lc->config,"video","capture",1);
display=lp_config_get_int(lc->config,"video","display",1);
self_view=lp_config_get_int(lc->config,"video","self_view",1);
+ reuse_source=lp_config_get_int(lc->config,"video","reuse_source",0);
vpol.automatically_initiate=lp_config_get_int(lc->config,"video","automatically_initiate",automatic_video);
vpol.automatically_accept=lp_config_get_int(lc->config,"video","automatically_accept",automatic_video);
linphone_core_enable_video_capture(lc, capture);
linphone_core_enable_video_display(lc, display);
linphone_core_enable_video_preview(lc,lp_config_get_int(lc->config,"video","show_local",0));
linphone_core_enable_self_view(lc,self_view);
+ linphone_core_enable_video_source_reuse(lc, reuse_source);
linphone_core_set_video_policy(lc,&vpol);
#endif
}
@@ -1083,6 +1256,28 @@ bool_t linphone_core_adaptive_rate_control_enabled(const LinphoneCore *lc){
return lp_config_get_int(lc->config,"net","adaptive_rate_control",TRUE);
}
+/**
+ * Sets adaptive rate algorithm. It will be used for each new calls starting from
+ * now. Calls already started will not be updated.
+ *
+ * @ingroup media_parameters
+ *
+**/
+void linphone_core_set_adaptive_rate_algorithm(LinphoneCore *lc, const char* algorithm){
+ lp_config_set_string(lc->config,"net","adaptive_rate_algorithm",algorithm);
+}
+
+/**
+ * Returns which adaptive rate algorithm is currently configured for future calls.
+ *
+ * @ingroup media_parameters
+ *
+ * See linphone_core_set_adaptive_rate_algorithm().
+**/
+const char * linphone_core_get_adaptive_rate_algorithm(const LinphoneCore *lc){
+ return lp_config_get_string(lc->config, "net", "adaptive_rate_algorithm", "Simple");
+}
+
bool_t linphone_core_rtcp_enabled(const LinphoneCore *lc){
return lp_config_get_int(lc->config,"rtp","rtcp_enabled",TRUE);
}
@@ -1267,9 +1462,7 @@ static void linphone_core_free_payload_types(LinphoneCore *lc){
void linphone_core_set_state(LinphoneCore *lc, LinphoneGlobalState gstate, const char *message){
lc->state=gstate;
- if (lc->vtable.global_state_changed){
- lc->vtable.global_state_changed(lc,gstate,message);
- }
+ linphone_core_notify_global_state_changed(lc,gstate,message);
}
static void misc_config_read(LinphoneCore *lc) {
@@ -1302,18 +1495,18 @@ static void linphone_core_start(LinphoneCore * lc) {
ui_config_read(lc);
#ifdef TUNNEL_ENABLED
lc->tunnel=linphone_core_tunnel_new(lc);
- if (lc->tunnel) linphone_tunnel_configure(lc->tunnel);
+ if (lc->tunnel) {
+ linphone_tunnel_configure(lc->tunnel);
+ }
#endif
- if (lc->vtable.display_status)
- lc->vtable.display_status(lc,_("Ready"));
+ linphone_core_notify_display_status(lc,_("Ready"));
lc->auto_net_state_mon=lc->sip_conf.auto_net_state_mon;
linphone_core_set_state(lc,LinphoneGlobalOn,"Ready");
}
void linphone_configuring_terminated(LinphoneCore *lc, LinphoneConfiguringState state, const char *message) {
- if (lc->vtable.configuring_status)
- lc->vtable.configuring_status(lc, state, message);
+ linphone_core_notify_configuring_status(lc, state, message);
if (state == LinphoneConfiguringSuccessful) {
if (linphone_core_is_provisioning_transient(lc) == TRUE)
@@ -1326,13 +1519,16 @@ void linphone_configuring_terminated(LinphoneCore *lc, LinphoneConfiguringState
static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtable, LpConfig *config, void * userdata)
{
const char *remote_provisioning_uri = NULL;
+ const char *aac_fmtp162248, *aac_fmtp3244;
+ LinphoneCoreVTable* local_vtable= linphone_core_v_table_new();
ms_message("Initializing LinphoneCore %s", linphone_core_get_version());
memset (lc, 0, sizeof (LinphoneCore));
lc->config=lp_config_ref(config);
lc->data=userdata;
lc->ringstream_autorelease=TRUE;
- memcpy(&lc->vtable,vtable,sizeof(LinphoneCoreVTable));
+ memcpy(local_vtable,vtable,sizeof(LinphoneCoreVTable));
+ lc->vtables=ms_list_append(lc->vtables,local_vtable);
linphone_core_set_state(lc,LinphoneGlobalStartup,"Starting up");
ortp_init();
@@ -1370,17 +1566,29 @@ static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtab
linphone_core_assign_payload_type(lc,&payload_type_h264,102,"profile-level-id=42801F");
linphone_core_assign_payload_type(lc,&payload_type_vp8,103,NULL);
- linphone_core_assign_payload_type(lc,&payload_type_theora,97,NULL);
- linphone_core_assign_payload_type(lc,&payload_type_x_snow,-1,NULL);
+ /* linphone_core_assign_payload_type(lc,&payload_type_theora,97,NULL); commented out to free 1 slot */
+ /* linphone_core_assign_payload_type(lc,&payload_type_x_snow,-1,NULL); commented out to free 1 slot */
/* due to limited space in SDP, we have to disable this h264 line which is normally no more necessary */
/* linphone_core_assign_payload_type(&payload_type_h264,-1,"packetization-mode=1;profile-level-id=428014");*/
#endif
+ /* For AAC, we use a config value to determine if we ought to support SBR. Since it is not offically supported
+ * for the mpeg4-generic mime type, setting this flag to 1 will break compatibility with other clients. */
+ if( lp_config_get_int(lc->config, "misc", "aac_use_sbr", FALSE) ) {
+ ms_message("Using SBR for AAC");
+ aac_fmtp162248 = "config=F8EE2000; constantDuration=512; indexDeltaLength=3; indexLength=3; mode=AAC-hbr; profile-level-id=76; sizeLength=13; streamType=5; SBR-enabled=1";
+ aac_fmtp3244 = "config=F8E82000; constantDuration=512; indexDeltaLength=3; indexLength=3; mode=AAC-hbr; profile-level-id=76; sizeLength=13; streamType=5; SBR-enabled=1";
+ } else {
+ aac_fmtp162248 = "config=F8EE2000; constantDuration=512; indexDeltaLength=3; indexLength=3; mode=AAC-hbr; profile-level-id=76; sizeLength=13; streamType=5";
+ aac_fmtp3244 = "config=F8E82000; constantDuration=512; indexDeltaLength=3; indexLength=3; mode=AAC-hbr; profile-level-id=76; sizeLength=13; streamType=5";
+ }
+
+
/*add all payload type for which we don't care about the number */
linphone_core_assign_payload_type(lc,&payload_type_ilbc,-1,"mode=30");
linphone_core_assign_payload_type(lc,&payload_type_amr,-1,"octet-align=1");
linphone_core_assign_payload_type(lc,&payload_type_amrwb,-1,"octet-align=1");
- linphone_core_assign_payload_type(lc,&payload_type_lpc1015,-1,NULL);
+ /* linphone_core_assign_payload_type(lc,&payload_type_lpc1015,-1,NULL); commented out to free 1 slot */
linphone_core_assign_payload_type(lc,&payload_type_g726_16,-1,NULL);
linphone_core_assign_payload_type(lc,&payload_type_g726_24,-1,NULL);
linphone_core_assign_payload_type(lc,&payload_type_g726_32,-1,NULL);
@@ -1394,8 +1602,11 @@ static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtab
linphone_core_assign_payload_type(lc,&payload_type_silk_wb,-1,NULL);
linphone_core_assign_payload_type(lc,&payload_type_silk_swb,-1,NULL);
linphone_core_assign_payload_type(lc,&payload_type_g729,18,"annexb=no");
- linphone_core_assign_payload_type(lc,&payload_type_aaceld_22k,-1,"config=F8EE2000; constantDuration=512; indexDeltaLength=3; indexLength=3; mode=AAC-hbr; profile-level-id=76; sizeLength=13; streamType=5");
- linphone_core_assign_payload_type(lc,&payload_type_aaceld_44k,-1,"config=F8E82000; constantDuration=512; indexDeltaLength=3; indexLength=3; mode=AAC-hbr; profile-level-id=76; sizeLength=13; streamType=5");
+ linphone_core_assign_payload_type(lc,&payload_type_aaceld_16k,-1,aac_fmtp162248);
+ linphone_core_assign_payload_type(lc,&payload_type_aaceld_22k,-1,aac_fmtp162248);
+ linphone_core_assign_payload_type(lc,&payload_type_aaceld_32k,-1,aac_fmtp3244);
+ linphone_core_assign_payload_type(lc,&payload_type_aaceld_44k,-1,aac_fmtp3244);
+ linphone_core_assign_payload_type(lc,&payload_type_aaceld_48k,-1,aac_fmtp162248);
linphone_core_assign_payload_type(lc,&payload_type_opus,-1,"useinbandfec=1; stereo=0; sprop-stereo=0");
linphone_core_assign_payload_type(lc,&payload_type_isac,-1,NULL);
linphone_core_handle_static_payloads(lc);
@@ -1418,8 +1629,6 @@ static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtab
lc->http_verify_policy = belle_tls_verify_policy_new();
belle_http_provider_set_tls_verify_policy(lc->http_provider,lc->http_verify_policy);
- lc->file_transfer_server = NULL;
-
certificates_config_read(lc);
remote_provisioning_uri = linphone_core_get_provisioning_uri(lc);
@@ -1466,6 +1675,8 @@ LinphoneCore *linphone_core_new_with_config(const LinphoneCoreVTable *vtable, st
/**
* Returns the list of available audio codecs.
+ * @param[in] lc The LinphoneCore object
+ * @return \mslist{PayloadType}
*
* This list is unmodifiable. The ->data field of the MSList points a PayloadType
* structure holding the codec information.
@@ -1480,6 +1691,8 @@ const MSList *linphone_core_get_audio_codecs(const LinphoneCore *lc)
/**
* Returns the list of available video codecs.
+ * @param[in] lc The LinphoneCore object
+ * @return \mslist{PayloadType}
*
* This list is unmodifiable. The ->data field of the MSList points a PayloadType
* structure holding the codec information.
@@ -1518,44 +1731,6 @@ int linphone_core_set_primary_contact(LinphoneCore *lc, const char *contact)
}
-/*Returns the local ip that routes to the internet, or guessed by other special means (upnp)*/
-/*result must be an array of chars at least LINPHONE_IPADDR_SIZE */
-void linphone_core_get_local_ip(LinphoneCore *lc, int af, char *result){
- const char *ip;
- if (linphone_core_get_firewall_policy(lc)==LinphonePolicyUseNatAddress
- && (ip=linphone_core_get_nat_address_resolved(lc))!=NULL){
- strncpy(result,ip,LINPHONE_IPADDR_SIZE);
- return;
- }
-#ifdef BUILD_UPNP
- else if (lc->upnp != NULL && linphone_core_get_firewall_policy(lc)==LinphonePolicyUseUpnp &&
- linphone_upnp_context_get_state(lc->upnp) == LinphoneUpnpStateOk) {
- ip = linphone_upnp_context_get_external_ipaddress(lc->upnp);
- strncpy(result,ip,LINPHONE_IPADDR_SIZE);
- return;
- }
-#endif //BUILD_UPNP
- if (af==AF_UNSPEC){
- if (linphone_core_ipv6_enabled(lc)){
- bool_t has_ipv6;
- has_ipv6=linphone_core_get_local_ip_for(AF_INET6,NULL,result)==0;
- if (strcmp(result,"::1")!=0)
- return; /*this machine has real ipv6 connectivity*/
- if (linphone_core_get_local_ip_for(AF_INET,NULL,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;
- }
- if (linphone_core_get_local_ip_for(af,NULL,result)==0)
- return;
-}
-
static void update_primary_contact(LinphoneCore *lc){
char *guessed=NULL;
char tmp[LINPHONE_IPADDR_SIZE];
@@ -1570,7 +1745,7 @@ static void update_primary_contact(LinphoneCore *lc){
ms_error("Could not parse identity contact !");
url=linphone_address_new("sip:unknown@unkwownhost");
}
- linphone_core_get_local_ip(lc, AF_UNSPEC, tmp);
+ linphone_core_get_local_ip(lc, AF_UNSPEC, NULL, tmp);
if (strcmp(tmp,"127.0.0.1")==0 || strcmp(tmp,"::1")==0 ){
ms_warning("Local loopback network only !");
lc->sip_conf.loopback_only=TRUE;
@@ -1631,6 +1806,9 @@ LinphoneAddress *linphone_core_get_primary_contact_parsed(LinphoneCore *lc){
/**
* Sets the list of audio codecs.
+ * @param[in] lc The LinphoneCore object
+ * @param[in] codecs \mslist{PayloadType}
+ * @return 0
*
* @ingroup media_parameters
* The list is taken by the LinphoneCore thus the application should not free it.
@@ -1646,6 +1824,9 @@ int linphone_core_set_audio_codecs(LinphoneCore *lc, MSList *codecs)
/**
* Sets the list of video codecs.
+ * @param[in] lc The LinphoneCore object
+ * @param[in] codecs \mslist{PayloadType}
+ * @return 0
*
* @ingroup media_parameters
* The list is taken by the LinphoneCore thus the application should not free it.
@@ -1763,24 +1944,53 @@ bool_t linphone_core_get_rtp_no_xmit_on_audio_mute(const LinphoneCore *lc){
return lc->rtp_conf.rtp_no_xmit_on_audio_mute;
}
+static void apply_jitter_value(LinphoneCore *lc, int value, MSFormatType stype){
+ LinphoneCall *call;
+ MSList *it;
+ for (it=lc->calls;it!=NULL;it=it->next){
+ MediaStream *ms;
+ call=(LinphoneCall*)it->data;
+ ms = stype==MSAudio ? (MediaStream*)call->audiostream : (MediaStream*)call->videostream;
+ if (ms){
+ RtpSession *s=ms->sessions.rtp_session;
+ if (s){
+ if (value>0){
+ ms_message("Jitter buffer size set to [%i] ms on call [%p]",value,call);
+ rtp_session_set_jitter_compensation(s,value);
+ rtp_session_enable_jitter_buffer(s,TRUE);
+ }else if (value==0){
+ ms_warning("Jitter buffer is disabled per application request on call [%p]",call);
+ rtp_session_enable_jitter_buffer(s,FALSE);
+ }
+ }
+ }
+ }
+}
+
/**
* Sets the nominal audio jitter buffer size in milliseconds.
+ * The value takes effect immediately for all running and pending calls, if any.
+ * A value of 0 disables the jitter buffer.
*
* @ingroup media_parameters
**/
void linphone_core_set_audio_jittcomp(LinphoneCore *lc, int value)
{
lc->rtp_conf.audio_jitt_comp=value;
+ apply_jitter_value(lc, value, MSAudio);
}
/**
* Sets the nominal video jitter buffer size in milliseconds.
+ * The value takes effect immediately for all running and pending calls, if any.
+ * A value of 0 disables the jitter buffer.
*
* @ingroup media_parameters
**/
void linphone_core_set_video_jittcomp(LinphoneCore *lc, int value)
{
lc->rtp_conf.video_jitt_comp=value;
+ apply_jitter_value(lc, value, MSVideo);
}
void linphone_core_set_rtp_no_xmit_on_audio_mute(LinphoneCore *lc,bool_t rtp_no_xmit_on_audio_mute){
@@ -1890,35 +2100,14 @@ void linphone_core_set_use_rfc2833_for_dtmf(LinphoneCore *lc,bool_t use_rfc2833)
* Deprecated: use linphone_core_get_sip_transports() instead.
* @ingroup network_parameters
**/
-int linphone_core_get_sip_port(LinphoneCore *lc)
-{
+int linphone_core_get_sip_port(LinphoneCore *lc){
LCSipTransports tr;
linphone_core_get_sip_transports_used(lc,&tr);
return tr.udp_port>0 ? tr.udp_port : (tr.tcp_port > 0 ? tr.tcp_port : tr.tls_port);
}
-#if !USE_BELLE_SIP
static char _ua_name[64]="Linphone";
-static char _ua_version[64]=LINPHONE_VERSION;
-#endif
-
-#if HAVE_EXOSIP_GET_VERSION && !USE_BELLESIP
-extern const char *eXosip_get_version();
-#endif
-
-static void apply_user_agent(LinphoneCore *lc){
-#if !USE_BELLESIP /*default user agent is handled at sal level*/
- char ua_string[256];
- snprintf(ua_string,sizeof(ua_string)-1,"%s/%s (eXosip2/%s)",_ua_name,_ua_version,
-#if HAVE_EXOSIP_GET_VERSION
- eXosip_get_version()
-#else
- "unknown"
-#endif
- );
- if (lc->sal) sal_set_user_agent(lc->sal,ua_string);
-#endif
-}
+static char _ua_version[64]=LIBLINPHONE_VERSION;
/**
* Sets the user agent string used in SIP messages.
@@ -1926,27 +2115,15 @@ static void apply_user_agent(LinphoneCore *lc){
* @ingroup misc
**/
void linphone_core_set_user_agent(LinphoneCore *lc, const char *name, const char *ver){
-#if USE_BELLESIP
char ua_string[256];
snprintf(ua_string, sizeof(ua_string) - 1, "%s/%s", name?name:"", ver?ver:"");
if (lc->sal) {
sal_set_user_agent(lc->sal, ua_string);
sal_append_stack_string_to_user_agent(lc->sal);
}
-#else
- strncpy(_ua_name,name,sizeof(_ua_name)-1);
- strncpy(_ua_version,ver,sizeof(_ua_version));
- apply_user_agent(lc);
-#endif
}
const char *linphone_core_get_user_agent(LinphoneCore *lc){
-#if USE_BELLESIP
return sal_get_user_agent(lc->sal);
-#else
- static char ua_buffer[255] = {0};
- snprintf(ua_buffer, "%s/%s", _ua_name, _ua_version, 254);
- return ua_buffer;
-#endif
}
const char *linphone_core_get_user_agent_name(void){
@@ -1960,8 +2137,7 @@ const char *linphone_core_get_user_agent_version(void){
static void transport_error(LinphoneCore *lc, const char* transport, int port){
char *msg=ortp_strdup_printf("Could not start %s transport on port %i, maybe this port is already used.",transport,port);
ms_warning("%s",msg);
- if (lc->vtable.display_warning)
- lc->vtable.display_warning(lc,msg);
+ linphone_core_notify_display_warning(lc,msg);
ms_free(msg);
}
@@ -2004,7 +2180,6 @@ static int apply_transports(LinphoneCore *lc){
}
}
}
- apply_user_agent(lc);
return 0;
}
@@ -2131,7 +2306,7 @@ static void monitor_network_state(LinphoneCore *lc, time_t curtime){
/* only do the network up checking every five seconds */
if (lc->network_last_check==0 || (curtime-lc->network_last_check)>=5){
- linphone_core_get_local_ip(lc,AF_UNSPEC,newip);
+ linphone_core_get_local_ip(lc,AF_UNSPEC,NULL,newip);
if (strcmp(newip,"::1")!=0 && strcmp(newip,"127.0.0.1")!=0){
new_status=TRUE;
}else new_status=FALSE; /*no network*/
@@ -2161,10 +2336,11 @@ static void proxy_update(LinphoneCore *lc){
for(elem=lc->sip_conf.deleted_proxies;elem!=NULL;elem=next){
LinphoneProxyConfig* cfg = (LinphoneProxyConfig*)elem->data;
next=elem->next;
- if (ms_time(NULL) - cfg->deletion_date > 5) {
+ if (ms_time(NULL) - cfg->deletion_date > 32) {
lc->sip_conf.deleted_proxies =ms_list_remove_link(lc->sip_conf.deleted_proxies,elem);
- ms_message("clearing proxy config for [%s]",linphone_proxy_config_get_addr(cfg));
- linphone_proxy_config_destroy(cfg);
+ ms_message("Proxy config for [%s] is definitely removed from core.",linphone_proxy_config_get_addr(cfg));
+ _linphone_proxy_config_release_ops(cfg);
+ linphone_proxy_config_unref(cfg);
}
}
}
@@ -2174,8 +2350,7 @@ static void assign_buddy_info(LinphoneCore *lc, BuddyInfo *info){
if (lf!=NULL){
lf->info=info;
ms_message("%s has a BuddyInfo assigned with image %p",info->sip_uri, info->image_data);
- if (lc->vtable.buddy_info_updated)
- lc->vtable.buddy_info_updated(lc,lf);
+ linphone_core_notify_buddy_info_updated(lc,lf);
}else{
ms_warning("Could not any friend with uri %s",info->sip_uri);
}
@@ -2261,7 +2436,10 @@ void linphone_core_iterate(LinphoneCore *lc){
int elapsed;
bool_t one_second_elapsed=FALSE;
const char *remote_provisioning_uri = NULL;
-
+ if (lc->network_reachable_to_be_notified) {
+ lc->network_reachable_to_be_notified=FALSE;
+ linphone_core_notify_network_reachable(lc,lc->network_reachable);
+ }
if (linphone_core_get_global_state(lc) == LinphoneGlobalStartup) {
if (sal_get_root_ca(lc->sal)) {
belle_tls_verify_policy_t *tls_policy = belle_tls_verify_policy_new();
@@ -2269,8 +2447,7 @@ void linphone_core_iterate(LinphoneCore *lc){
belle_http_provider_set_tls_verify_policy(lc->http_provider, tls_policy);
}
- if (lc->vtable.display_status)
- lc->vtable.display_status(lc, _("Configuring"));
+ linphone_core_notify_display_status(lc, _("Configuring"));
linphone_core_set_state(lc, LinphoneGlobalConfiguring, "Configuring");
remote_provisioning_uri = linphone_core_get_provisioning_uri(lc);
@@ -2371,8 +2548,8 @@ void linphone_core_iterate(LinphoneCore *lc){
}
}
if ( (lc->sip_conf.in_call_timeout > 0)
- && (call->media_start_time != 0)
- && ((curtime - call->media_start_time) > lc->sip_conf.in_call_timeout))
+ && (call->log->connected_date_time != 0)
+ && ((curtime - call->log->connected_date_time) > lc->sip_conf.in_call_timeout))
{
ms_message("in call timeout (%i)",lc->sip_conf.in_call_timeout);
linphone_core_terminate_call(lc,call);
@@ -2435,11 +2612,9 @@ LinphoneAddress * linphone_core_interpret_url(LinphoneCore *lc, const char *url)
if (*url=='\0') return NULL;
if (is_enum(url,&enum_domain)){
- if (lc->vtable.display_status!=NULL)
- lc->vtable.display_status(lc,_("Looking for telephone number destination..."));
+ linphone_core_notify_display_status(lc,_("Looking for telephone number destination..."));
if (enum_lookup(enum_domain,&enumres)<0){
- if (lc->vtable.display_status!=NULL)
- lc->vtable.display_status(lc,_("Could not resolve this number."));
+ linphone_core_notify_display_status(lc,_("Could not resolve this number."));
ms_free(enum_domain);
return NULL;
}
@@ -2536,7 +2711,7 @@ LinphoneCall * linphone_core_start_refered_call(LinphoneCore *lc, LinphoneCall *
}
if (!params){
- cp->has_video = call->current_params.has_video; /*start the call to refer-target with video enabled if original call had video*/
+ cp->has_video = call->current_params->has_video; /*start the call to refer-target with video enabled if original call had video*/
}
cp->referer=call;
ms_message("Starting new call to refered address %s",call->refer_to);
@@ -2722,13 +2897,11 @@ int linphone_core_start_invite(LinphoneCore *lc, LinphoneCall *call, const Linph
call->log->call_id=ms_strdup(sal_op_get_call_id(call->op)); /*must be known at that time*/
barmsg=ortp_strdup_printf("%s %s", _("Contacting"), real_url);
- if (lc->vtable.display_status!=NULL)
- lc->vtable.display_status(lc,barmsg);
+ linphone_core_notify_display_status(lc,barmsg);
ms_free(barmsg);
if (err<0){
- if (lc->vtable.display_status!=NULL)
- lc->vtable.display_status(lc,_("Could not call"));
+ linphone_core_notify_display_status(lc,_("Could not call"));
linphone_call_stop_media_streams(call);
linphone_call_set_state(call,LinphoneCallError,"Call failed");
}else {
@@ -2878,8 +3051,7 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const
linphone_core_preempt_sound_resources(lc);
if(!linphone_core_can_we_add_call(lc)){
- if (lc->vtable.display_warning)
- lc->vtable.display_warning(lc,_("Sorry, we have reached the maximum number of simultaneous calls"));
+ linphone_core_notify_display_warning(lc,_("Sorry, we have reached the maximum number of simultaneous calls"));
return NULL;
}
@@ -2890,6 +3062,9 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const
from=linphone_proxy_config_get_identity(proxy);
cp->avpf_enabled = linphone_proxy_config_avpf_enabled(proxy);
cp->avpf_rr_interval = linphone_proxy_config_get_avpf_rr_interval(proxy) * 1000;
+ }else{
+ cp->avpf_enabled=linphone_core_get_avpf_mode(lc)==LinphoneAVPFEnabled;
+ if (cp->avpf_enabled) cp->avpf_rr_interval=linphone_core_get_avpf_rr_interval(lc) * 1000;
}
/* if no proxy or no identity defined for this proxy, default to primary contact*/
@@ -2910,15 +3085,15 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const
/* this call becomes now the current one*/
lc->current_call=call;
linphone_call_set_state (call,LinphoneCallOutgoingInit,"Starting outgoing call");
- call->log->start_date_time=time(NULL);
+ call->log->start_date_time=ms_time(NULL);
linphone_call_init_media_streams(call);
- if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) {
+ if (_linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) {
/* Defer the start of the call after the ICE gathering process. */
if (linphone_call_prepare_ice(call,FALSE)==1)
defer=TRUE;
}
- else if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseUpnp) {
+ else if (_linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseUpnp) {
#ifdef BUILD_UPNP
if (linphone_core_update_upnp(lc,call)<0) {
/* uPnP port mappings failed, proceed with the call anyway. */
@@ -3009,7 +3184,7 @@ int linphone_core_transfer_call_to_another(LinphoneCore *lc, LinphoneCall *call,
return result;
}
-bool_t linphone_core_inc_invite_pending(LinphoneCore*lc){
+bool_t linphone_core_is_incoming_invite_pending(LinphoneCore*lc){
LinphoneCall *call = linphone_core_get_current_call(lc);
if(call != NULL)
{
@@ -3038,8 +3213,7 @@ void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call){
if (md){
if (sal_media_description_empty(md) || linphone_core_incompatible_security(lc,md)){
sal_call_decline(call->op,SalReasonNotAcceptable,NULL);
- linphone_call_stop_media_streams(call);
- linphone_core_del_call(lc,call);
+ linphone_call_set_state_base(call, LinphoneCallError, NULL,TRUE);
linphone_call_unref(call);
return;
}
@@ -3051,9 +3225,8 @@ void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call){
linphone_address_destroy(from_parsed);
barmesg=ortp_strdup_printf("%s %s%s",tmp,_("is contacting you"),
(sal_call_autoanswer_asked(call->op)) ?_(" and asked autoanswer."):_("."));
- if (lc->vtable.show) lc->vtable.show(lc);
- if (lc->vtable.display_status)
- lc->vtable.display_status(lc,barmesg);
+ linphone_core_notify_show_interface(lc);
+ linphone_core_notify_display_status(lc,barmesg);
/* play the ring if this is the only call*/
if (ms_list_size(lc->calls)==1){
@@ -3119,7 +3292,7 @@ int linphone_core_accept_early_media_with_params(LinphoneCore* lc, LinphoneCall*
// if parameters are passed, update the media description
if ( params ) {
- _linphone_call_params_copy ( &call->params,params );
+ linphone_call_set_new_params(call,params);
linphone_call_make_local_media_description ( lc,call );
sal_call_set_local_media_description ( call->op,call->localdesc );
sal_op_set_sent_custom_header ( call->op,params->custom_headers );
@@ -3153,26 +3326,39 @@ int linphone_core_accept_early_media(LinphoneCore* lc, LinphoneCall* call){
int linphone_core_start_update_call(LinphoneCore *lc, LinphoneCall *call){
const char *subject;
+ int err;
+ bool_t no_user_consent=call->params->no_user_consent;
- linphone_call_make_local_media_description(lc,call);
+ if (!no_user_consent) linphone_call_make_local_media_description(lc,call);
#ifdef BUILD_UPNP
if(call->upnp_session != NULL) {
linphone_core_update_local_media_description_from_upnp(call->localdesc, call->upnp_session);
}
#endif //BUILD_UPNP
- if (call->params.in_conference){
+ if (call->params->in_conference){
subject="Conference";
- }else{
+ }else if (!no_user_consent){
subject="Media change";
+ }else{
+ subject="Refreshing";
+ }
+ linphone_core_notify_display_status(lc,_("Modifying call parameters..."));
+ if (!lc->sip_conf.sdp_200_ack){
+ sal_call_set_local_media_description (call->op,call->localdesc);
+ } else {
+ sal_call_set_local_media_description (call->op,NULL);
}
- if (lc->vtable.display_status)
- lc->vtable.display_status(lc,_("Modifying call parameters..."));
- sal_call_set_local_media_description (call->op,call->localdesc);
if (call->dest_proxy && call->dest_proxy->op){
/*give a chance to update the contact address if connectivity has changed*/
sal_op_set_contact_address(call->op,sal_op_get_contact_address(call->dest_proxy->op));
}else sal_op_set_contact_address(call->op,NULL);
- return sal_call_update(call->op,subject);
+ err= sal_call_update(call->op,subject,no_user_consent);
+ if (lc->sip_conf.sdp_200_ack){
+ /*we are NOT offering, set local media description after sending the call so that we are ready to
+ process the remote offer when it will arrive*/
+ sal_call_set_local_media_description(call->op,call->localdesc);
+ }
+ return err;
}
/**
@@ -3191,15 +3377,20 @@ int linphone_core_start_update_call(LinphoneCore *lc, LinphoneCall *call){
**/
int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params){
int err=0;
+ LinphoneCallState nextstate;
#if defined(VIDEO_ENABLED) && defined(BUILD_UPNP)
bool_t has_video = FALSE;
#endif
switch(call->state){
- case LinphoneCallIncomingEarlyMedia:
case LinphoneCallIncomingReceived:
+ case LinphoneCallIncomingEarlyMedia:
+ case LinphoneCallOutgoingRinging:
+ case LinphoneCallOutgoingEarlyMedia:
+ nextstate=LinphoneCallEarlyUpdating;
+ break;
case LinphoneCallStreamsRunning:
- /*these states are allowed for linphone_core_update_call()*/
+ nextstate=LinphoneCallUpdating;
break;
default:
ms_error("linphone_core_update_call() is not allowed in [%s] state",linphone_call_state_to_string(call->state));
@@ -3207,9 +3398,9 @@ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const Linpho
}
if (params!=NULL){
- linphone_call_set_state(call,LinphoneCallUpdating,"Updating call");
+ linphone_call_set_state(call,nextstate,"Updating call");
#if defined(VIDEO_ENABLED) && defined(BUILD_UPNP)
- has_video = call->params.has_video;
+ has_video = call->params->has_video;
// Video removing
if((call->videostream != NULL) && !params->has_video) {
@@ -3222,8 +3413,7 @@ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const Linpho
}
#endif /* defined(VIDEO_ENABLED) && defined(BUILD_UPNP) */
-
- _linphone_call_params_copy(&call->params,params);
+ linphone_call_set_new_params(call,params);
err=linphone_call_prepare_ice(call,FALSE);
if (err==1) {
ms_message("Defer call update to gather ICE candidates");
@@ -3232,7 +3422,7 @@ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const Linpho
#if defined(VIDEO_ENABLED) && defined(BUILD_UPNP)
// Video adding
- if (!has_video && call->params.has_video) {
+ if (!has_video && call->params->has_video) {
if(call->upnp_session != NULL) {
ms_message("Defer call update to add uPnP port mappings");
video_stream_prepare_video(call->videostream);
@@ -3250,6 +3440,7 @@ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const Linpho
#ifdef VIDEO_ENABLED
if ((call->videostream != NULL) && (call->state == LinphoneCallStreamsRunning)) {
video_stream_set_sent_video_size(call->videostream,linphone_core_get_preferred_video_size(lc));
+ video_stream_set_fps(call->videostream, linphone_core_get_preferred_framerate(lc));
if (call->camera_enabled && call->videostream->cam!=lc->video_conf.device){
video_stream_change_camera(call->videostream,lc->video_conf.device);
}else video_stream_update_video_params(call->videostream);
@@ -3283,7 +3474,7 @@ int linphone_core_defer_call_update(LinphoneCore *lc, LinphoneCall *call){
return -1;
}
-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){
SalMediaDescription *md;
if (call->ice_session != NULL) {
if (ice_session_nb_losing_pairs(call->ice_session) > 0) {
@@ -3301,8 +3492,7 @@ int linphone_core_start_accept_call_update(LinphoneCore *lc, LinphoneCall *call)
linphone_core_update_streams (lc,call,md);
linphone_call_fix_call_parameters(call);
}
- if (call->state != LinphoneCallOutgoingEarlyMedia) /*don't change the state in case of outgoing early (SIP UPDATE)*/
- linphone_call_set_state(call,LinphoneCallStreamsRunning,"Connected (streams running)");
+ linphone_call_set_state(call,next_state,state_info);
return 0;
}
@@ -3331,14 +3521,14 @@ int linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, const
linphone_call_state_to_string(call->state));
return -1;
}
- return _linphone_core_accept_call_update(lc, call, params);
+ return _linphone_core_accept_call_update(lc, call, params, call->prevstate, linphone_call_state_to_string(call->prevstate));
}
-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){
SalMediaDescription *remote_desc;
bool_t keep_sdp_version;
#if defined(VIDEO_ENABLED) && defined(BUILD_UPNP)
- bool_t old_has_video = call->params.has_video;
+ bool_t old_has_video = call->params->has_video;
#endif
remote_desc = sal_call_get_remote_media_description(call->op);
@@ -3347,23 +3537,23 @@ int _linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, cons
/* Remote has sent an INVITE with the same SDP as before, so send a 200 OK with the same SDP as before. */
ms_warning("SDP version has not changed, send same SDP as before.");
sal_call_accept(call->op);
- linphone_call_set_state(call,LinphoneCallStreamsRunning,"Connected (streams running)");
+ linphone_call_set_state(call,next_state,state_info);
return 0;
}
if (params==NULL){
- call->params.has_video=lc->video_policy.automatically_accept || call->current_params.has_video;
+ call->params->has_video=lc->video_policy.automatically_accept || call->current_params->has_video;
}else
- _linphone_call_params_copy(&call->params,params);
+ linphone_call_set_new_params(call,params);
- if (call->params.has_video && !linphone_core_video_enabled(lc)){
+ if (call->params->has_video && !linphone_core_video_enabled(lc)){
ms_warning("linphone_core_accept_call_update(): requested video but video support is globally disabled. Refusing video.");
- call->params.has_video=FALSE;
+ call->params->has_video=FALSE;
}
- if (call->current_params.in_conference) {
+ if (call->current_params->in_conference) {
ms_warning("Video isn't supported in conference");
- call->params.has_video = FALSE;
+ call->params->has_video = FALSE;
}
- call->params.has_video &= linphone_core_media_description_contains_video_stream(remote_desc);
+ call->params->has_video &= linphone_core_media_description_contains_video_stream(remote_desc);
linphone_call_init_media_streams(call); /*so that video stream is initialized if necessary*/
if (call->ice_session != NULL) {
if (linphone_call_prepare_ice(call,TRUE)==1)
@@ -3374,7 +3564,7 @@ int _linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, cons
if(call->upnp_session != NULL) {
linphone_core_update_upnp_from_remote_media_description(call, sal_call_get_remote_media_description(call->op));
#ifdef VIDEO_ENABLED
- if ((call->params.has_video) && (call->params.has_video != old_has_video)) {
+ if ((call->params->has_video) && (call->params->has_video != old_has_video)) {
video_stream_prepare_video(call->videostream);
if (linphone_core_update_upnp(lc, call)<0) {
/* uPnP update failed, proceed with the call anyway. */
@@ -3385,7 +3575,7 @@ int _linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, cons
}
#endif //BUILD_UPNP
- linphone_core_start_accept_call_update(lc, call);
+ linphone_core_start_accept_call_update(lc, call, next_state, state_info);
return 0;
}
@@ -3419,8 +3609,7 @@ int linphone_core_accept_call(LinphoneCore *lc, LinphoneCall *call){
* @param params the specific parameters for this call, for example whether video is accepted or not. Use NULL to use default parameters.
*
**/
-int linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params)
-{
+int linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params){
SalOp *replaced;
SalMediaDescription *new_md;
bool_t was_ringing=FALSE;
@@ -3433,9 +3622,15 @@ int linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call,
call = (LinphoneCall*)linphone_core_get_calls(lc)->data;
}
- if (call->state==LinphoneCallConnected){
- /*call already accepted*/
- return -1;
+ switch(call->state){
+ case LinphoneCallIncomingReceived:
+ case LinphoneCallIncomingEarlyMedia:
+ break;
+ default:
+ ms_error("linphone_core_accept_call_with_params() call [%p] is in state [%s], operation not permitted.",
+ call, linphone_call_state_to_string(call->state));
+ return -1;
+ break;
}
/* check if this call is supposed to replace an already running one*/
@@ -3468,7 +3663,7 @@ int linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call,
linphone_call_set_contact_op(call);
if (params){
const SalMediaDescription *md = sal_call_get_remote_media_description(call->op);
- _linphone_call_params_copy(&call->params,params);
+ linphone_call_set_new_params(call,params);
// There might not be a md if the INVITE was lacking an SDP
// In this case we use the parameters as is.
if (md) {
@@ -3495,8 +3690,7 @@ int linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call,
linphone_call_update_remote_session_id_and_ver(call);
sal_call_accept(call->op);
- if (lc->vtable.display_status!=NULL)
- lc->vtable.display_status(lc,_("Connected."));
+ linphone_core_notify_display_status(lc,_("Connected."));
lc->current_call=call;
linphone_call_set_state(call,LinphoneCallConnected,"Connected");
new_md=sal_call_get_final_media_description(call->op);
@@ -3521,8 +3715,7 @@ int linphone_core_abort_call(LinphoneCore *lc, LinphoneCall *call, const char *e
linphone_call_delete_upnp_session(call);
#endif //BUILD_UPNP
- if (lc->vtable.display_status!=NULL)
- lc->vtable.display_status(lc,_("Call aborted") );
+ linphone_core_notify_display_status(lc,_("Call aborted") );
linphone_call_set_state(call,LinphoneCallError,error);
return 0;
}
@@ -3541,8 +3734,7 @@ static void terminate_call(LinphoneCore *lc, LinphoneCall *call){
linphone_call_delete_upnp_session(call);
#endif //BUILD_UPNP
- if (lc->vtable.display_status!=NULL)
- lc->vtable.display_status(lc,_("Call ended") );
+ linphone_core_notify_display_status(lc,_("Call ended") );
linphone_call_set_state(call,LinphoneCallEnd,"Call terminated");
}
@@ -3642,6 +3834,8 @@ int linphone_core_terminate_all_calls(LinphoneCore *lc){
/**
* Returns the current list of calls.
+ * @param[in] lc The LinphoneCore object
+ * @return \mslist{LinphoneCall}
*
* Note that this list is read-only and might be changed by the core after a function call to linphone_core_iterate().
* Similarly the LinphoneCall objects inside it might be destroyed without prior notice.
@@ -3710,14 +3904,12 @@ int _linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *call)
return -1;
}
sal_call_set_local_media_description(call->op,call->localdesc);
- if (sal_call_update(call->op,subject) != 0){
- if (lc->vtable.display_warning)
- lc->vtable.display_warning(lc,_("Could not pause the call"));
+ if (sal_call_update(call->op,subject,FALSE) != 0){
+ linphone_core_notify_display_warning(lc,_("Could not pause the call"));
}
lc->current_call=NULL;
linphone_call_set_state(call,LinphoneCallPausing,"Pausing call");
- if (lc->vtable.display_status)
- lc->vtable.display_status(lc,_("Pausing the current call..."));
+ linphone_core_notify_display_status(lc,_("Pausing the current call..."));
if (call->audiostream || call->videostream)
linphone_call_stop_media_streams (call);
call->paused_by_app=FALSE;
@@ -3771,7 +3963,7 @@ int linphone_core_resume_call(LinphoneCore *lc, LinphoneCall *call){
ms_warning("we cannot resume a call that has not been established and paused before");
return -1;
}
- if (call->params.in_conference==FALSE){
+ if (call->params->in_conference==FALSE){
if (linphone_core_sound_resources_locked(lc)){
ms_warning("Cannot resume call %p because another call is locking the sound resources.",call);
return -1;
@@ -3794,16 +3986,15 @@ int linphone_core_resume_call(LinphoneCore *lc, LinphoneCall *call){
#endif //BUILD_UPNP
sal_call_set_local_media_description(call->op,call->localdesc);
sal_media_description_set_dir(call->localdesc,SalStreamSendRecv);
- if (call->params.in_conference && !call->current_params.in_conference) subject="Conference";
- if(sal_call_update(call->op,subject) != 0){
+ if (call->params->in_conference && !call->current_params->in_conference) subject="Conference";
+ if ( sal_call_update(call->op,subject,FALSE) != 0){
return -1;
}
linphone_call_set_state(call,LinphoneCallResuming,"Resuming");
- if (call->params.in_conference==FALSE)
+ if (call->params->in_conference==FALSE)
lc->current_call=call;
snprintf(temp,sizeof(temp)-1,"Resuming the call with %s",linphone_call_get_remote_address_as_string(call));
- if (lc->vtable.display_status)
- lc->vtable.display_status(lc,temp);
+ linphone_core_notify_display_status(lc,temp);
return 0;
}
@@ -3823,6 +4014,7 @@ static int remote_address_compare(LinphoneCall *call, const LinphoneAddress *rad
LinphoneCall *linphone_core_get_call_by_remote_address(LinphoneCore *lc, const char *remote_address){
LinphoneAddress *raddr=linphone_address_new(remote_address);
MSList *elem=ms_list_find_custom(lc->calls,(int (*)(const void*,const void *))remote_address_compare,raddr);
+ linphone_address_unref(raddr);
if (elem) return (LinphoneCall*) elem->data;
return NULL;
}
@@ -4087,9 +4279,7 @@ void linphone_core_set_mic_gain_db (LinphoneCore *lc, float gaindb){
ms_message("linphone_core_set_mic_gain_db(): no active call.");
return;
}
- if (st->volsend){
- ms_filter_call_method(st->volsend,MS_VOLUME_SET_DB_GAIN,&gain);
- }else ms_warning("Could not apply gain: gain control wasn't activated.");
+ set_mic_gain_db(st,gain);
}
/**
@@ -4120,9 +4310,7 @@ void linphone_core_set_playback_gain_db (LinphoneCore *lc, float gaindb){
ms_message("linphone_core_set_playback_gain_db(): no active call.");
return;
}
- if (st->volrecv){
- ms_filter_call_method(st->volrecv,MS_VOLUME_SET_DB_GAIN,&gain);
- }else ms_warning("Could not apply gain: gain control wasn't activated.");
+ set_playback_gain_db(st,gain);
}
/**
@@ -4477,7 +4665,7 @@ void linphone_core_set_ringback(LinphoneCore *lc, const char *path){
if (lc->sound_conf.remote_ring!=0){
ms_free(lc->sound_conf.remote_ring);
}
- lc->sound_conf.remote_ring=ms_strdup(path);
+ lc->sound_conf.remote_ring=path?ms_strdup(path):NULL;
}
/**
@@ -4490,7 +4678,10 @@ const char * linphone_core_get_ringback(const LinphoneCore *lc){
}
/**
- * Enables or disable echo cancellation. Value is saved an used for subsequent calls
+ * Enables or disable echo cancellation. Value is saved and used for subsequent calls.
+ * This actually controls software echo cancellation. If hardware echo cancellation is available, it will be always used and activated for calls, regardless
+ * of the value passed to this function.
+ * When hardware echo cancellation is available, the software one is of course not activated.
*
* @ingroup media_parameters
**/
@@ -4518,26 +4709,28 @@ bool_t linphone_core_echo_limiter_enabled(const LinphoneCore *lc){
return lc->sound_conf.ea;
}
+static void linphone_core_mute_audio_stream(LinphoneCore *lc, AudioStream *st, bool_t val) {
+ audio_stream_set_mic_gain(st,
+ (val==TRUE) ? 0 : pow(10,lc->sound_conf.soft_mic_lev/10));
+ if ( linphone_core_get_rtp_no_xmit_on_audio_mute(lc) ){
+ audio_stream_mute_rtp(st,val);
+ }
+}
+
void linphone_core_mute_mic(LinphoneCore *lc, bool_t val){
- LinphoneCall *call=linphone_core_get_current_call(lc);
- AudioStream *st=NULL;
+ LinphoneCall *call;
+ const MSList *list;
+ const MSList *elem;
+
if (linphone_core_is_in_conference(lc)){
lc->conf_ctx.local_muted=val;
- st=lc->conf_ctx.local_participant;
- }else if (call==NULL){
- ms_warning("linphone_core_mute_mic(): No current call !");
- return;
- }else{
- st=call->audiostream;
- call->audio_muted=val;
- }
- if (st!=NULL){
- audio_stream_set_mic_gain(st,
- (val==TRUE) ? 0 : pow(10,lc->sound_conf.soft_mic_lev/10));
- if ( linphone_core_get_rtp_no_xmit_on_audio_mute(lc) ){
- audio_stream_mute_rtp(st,val);
- }
-
+ linphone_core_mute_audio_stream(lc, lc->conf_ctx.local_participant, val);
+ }
+ list = linphone_core_get_calls(lc);
+ for (elem = list; elem != NULL; elem = elem->next) {
+ call = (LinphoneCall *)elem->data;
+ call->audio_muted = val;
+ linphone_core_mute_audio_stream(lc, call->audiostream, val);
}
}
@@ -4765,9 +4958,23 @@ void linphone_core_set_firewall_policy(LinphoneCore *lc, LinphoneFirewallPolicy
lp_config_set_string(lc->config,"net","firewall_policy",policy);
}
-LinphoneFirewallPolicy linphone_core_get_firewall_policy(const LinphoneCore *lc){
- const char *policy = lp_config_get_string(lc->config, "net", "firewall_policy", NULL);
+ORTP_INLINE LinphoneFirewallPolicy linphone_core_get_firewall_policy(const LinphoneCore *lc) {
+ return _linphone_core_get_firewall_policy_with_lie(lc, FALSE);
+}
+ORTP_INLINE LinphoneFirewallPolicy _linphone_core_get_firewall_policy(const LinphoneCore *lc) {
+ return _linphone_core_get_firewall_policy_with_lie(lc, TRUE);
+}
+
+LinphoneFirewallPolicy _linphone_core_get_firewall_policy_with_lie(const LinphoneCore *lc, bool_t lie){
+ const char *policy;
+ if(lie) {
+ LinphoneTunnel *tunnel = linphone_core_get_tunnel(lc);
+ if(tunnel != NULL && linphone_tunnel_get_mode(tunnel)) {
+ return LinphonePolicyNoFirewall;
+ }
+ }
+ policy = lp_config_get_string(lc->config, "net", "firewall_policy", NULL);
if ((policy == NULL) || (strcmp(policy, "0") == 0))
return LinphonePolicyNoFirewall;
else if ((strcmp(policy, "nat_address") == 0) || (strcmp(policy, "1") == 0))
@@ -4782,23 +4989,19 @@ LinphoneFirewallPolicy linphone_core_get_firewall_policy(const LinphoneCore *lc)
return LinphonePolicyNoFirewall;
}
-/**
- * Get the list of call logs (past calls).
- *
- * @ingroup call_logs
-**/
+
+
+/*******************************************************************************
+ * Call log related functions *
+ ******************************************************************************/
+
const MSList * linphone_core_get_call_logs(LinphoneCore *lc){
return lc->call_logs;
}
-/**
- * Erase the call log.
- *
- * @ingroup call_logs
-**/
void linphone_core_clear_call_logs(LinphoneCore *lc){
lc->missed_calls=0;
- ms_list_for_each(lc->call_logs,(void (*)(void*))linphone_call_log_destroy);
+ ms_list_for_each(lc->call_logs,(void (*)(void*))linphone_call_log_unref);
lc->call_logs=ms_list_free(lc->call_logs);
call_logs_write_to_config_file(lc);
}
@@ -4814,9 +5017,12 @@ void linphone_core_reset_missed_calls_count(LinphoneCore *lc) {
void linphone_core_remove_call_log(LinphoneCore *lc, LinphoneCallLog *cl){
lc->call_logs = ms_list_remove(lc->call_logs, cl);
call_logs_write_to_config_file(lc);
- linphone_call_log_destroy(cl);
+ linphone_call_log_unref(cl);
}
+
+
+
static void toggle_video_preview(LinphoneCore *lc, bool_t val){
#ifdef VIDEO_ENABLED
if (val){
@@ -4891,6 +5097,18 @@ void linphone_core_enable_video_display(LinphoneCore *lc, bool_t enable) {
reapply_network_bandwidth_settings(lc);
}
+void linphone_core_enable_video_source_reuse(LinphoneCore* lc, bool_t enable){
+#ifndef VIDEO_ENABLED
+ if (enable == TRUE) {
+ ms_warning("Cannot enable video display, this version of linphone was built without video support.");
+ }
+#endif
+ lc->video_conf.reuse_preview_source = enable;
+ if( linphone_core_ready(lc) ){
+ lp_config_set_int(lc->config, "video", "reuse_source", lc->video_conf.reuse_preview_source);
+ }
+}
+
bool_t linphone_core_video_capture_enabled(LinphoneCore *lc) {
return lc->video_conf.capture;
}
@@ -5276,15 +5494,15 @@ int linphone_core_get_camera_sensor_rotation(LinphoneCore *lc) {
}
static MSVideoSizeDef supported_resolutions[]={
-#if !ANDROID & !TARGET_OS_IPHONE
+#if !ANDROID && !TARGET_OS_IPHONE
{ { MS_VIDEO_SIZE_1080P_W, MS_VIDEO_SIZE_1080P_H } , "1080p" },
#endif
-#if !ANDROID & !TARGET_OS_MAC /*limite to most common size because mac card cannot list supported resolutions*/
+#if !ANDROID && !TARGET_OS_MAC /*limit to most common sizes because mac video API cannot list supported resolutions*/
{ { MS_VIDEO_SIZE_UXGA_W, MS_VIDEO_SIZE_UXGA_H } , "uxga" },
{ { MS_VIDEO_SIZE_SXGA_MINUS_W, MS_VIDEO_SIZE_SXGA_MINUS_H } , "sxga-" },
#endif
{ { MS_VIDEO_SIZE_720P_W, MS_VIDEO_SIZE_720P_H } , "720p" },
-#if !ANDROID & !TARGET_OS_MAC
+#if !ANDROID && !TARGET_OS_MAC
{ { MS_VIDEO_SIZE_XGA_W, MS_VIDEO_SIZE_XGA_H } , "xga" },
#endif
#if !ANDROID && !TARGET_OS_IPHONE
@@ -5316,23 +5534,33 @@ const MSVideoSizeDef *linphone_core_get_supported_video_sizes(LinphoneCore *lc){
static MSVideoSize video_size_get_by_name(const char *name){
MSVideoSizeDef *pdef=supported_resolutions;
MSVideoSize null_vsize={0,0};
+ MSVideoSize parsed;
if (!name) return null_vsize;
for(;pdef->name!=NULL;pdef++){
if (strcasecmp(name,pdef->name)==0){
return pdef->vsize;
}
}
+ if (sscanf(name,"%ix%i",&parsed.width,&parsed.height)==2){
+ return parsed;
+ }
ms_warning("Video resolution %s is not supported in linphone.",name);
return null_vsize;
}
+/* warning: function not reentrant*/
static const char *video_size_get_name(MSVideoSize vsize){
MSVideoSizeDef *pdef=supported_resolutions;
+ static char customsize[64]={0};
for(;pdef->name!=NULL;pdef++){
if (pdef->vsize.width==vsize.width && pdef->vsize.height==vsize.height){
return pdef->name;
}
}
+ if (vsize.width && vsize.height){
+ snprintf(customsize,sizeof(customsize)-1,"%ix%i",vsize.width,vsize.height);
+ return customsize;
+ }
return NULL;
}
@@ -5359,13 +5587,13 @@ static void update_preview_size(LinphoneCore *lc, MSVideoSize oldvsize, MSVideoS
void linphone_core_set_preferred_video_size(LinphoneCore *lc, MSVideoSize vsize){
if (video_size_supported(vsize)){
MSVideoSize oldvsize=lc->video_conf.preview_vsize;
-
+
if (oldvsize.width==0){
oldvsize=lc->video_conf.vsize;
}
lc->video_conf.vsize=vsize;
update_preview_size(lc,oldvsize,vsize);
-
+
if (linphone_core_ready(lc))
lp_config_set_string(lc->config,"video","size",video_size_get_name(vsize));
}
@@ -5381,6 +5609,7 @@ void linphone_core_set_preferred_video_size(LinphoneCore *lc, MSVideoSize vsize)
* @param vsize the video resolution choosed for capuring and previewing. It can be (0,0) to not request any specific preview size and let the core optimize the processing.
**/
void linphone_core_set_preview_video_size(LinphoneCore *lc, MSVideoSize vsize){
+ MSVideoSize oldvsize;
if (vsize.width==0 && vsize.height==0){
/*special case to reset the forced preview size mode*/
lc->video_conf.preview_vsize=vsize;
@@ -5388,16 +5617,25 @@ void linphone_core_set_preview_video_size(LinphoneCore *lc, MSVideoSize vsize){
lp_config_set_string(lc->config,"video","preview_size",NULL);
return;
}
- if (video_size_supported(vsize)){
- MSVideoSize oldvsize=lc->video_conf.preview_vsize;
- lc->video_conf.preview_vsize=vsize;
- if (!ms_video_size_equal(oldvsize,vsize) && lc->previewstream!=NULL){
- toggle_video_preview(lc,FALSE);
- toggle_video_preview(lc,TRUE);
- }
- if (linphone_core_ready(lc))
- lp_config_set_string(lc->config,"video","preview_size",video_size_get_name(vsize));
+ oldvsize=lc->video_conf.preview_vsize;
+ lc->video_conf.preview_vsize=vsize;
+ if (!ms_video_size_equal(oldvsize,vsize) && lc->previewstream!=NULL){
+ toggle_video_preview(lc,FALSE);
+ toggle_video_preview(lc,TRUE);
}
+ if (linphone_core_ready(lc))
+ lp_config_set_string(lc->config,"video","preview_size",video_size_get_name(vsize));
+}
+
+/**
+ * Returns video size for the captured video if it was previously set by linphone_core_set_preview_video_size(), otherwise returns a 0,0 size.
+ * @see linphone_core_set_preview_video_size()
+ * @ingroup media_parameters
+ * @param lc the core
+ * @return a MSVideoSize
+**/
+MSVideoSize linphone_core_get_preview_video_size(const LinphoneCore *lc){
+ return lc->video_conf.preview_vsize;
}
/**
@@ -5431,10 +5669,14 @@ void linphone_core_set_preferred_video_size_by_name(LinphoneCore *lc, const char
*
* @ingroup media_parameters
**/
-MSVideoSize linphone_core_get_preferred_video_size(LinphoneCore *lc){
+MSVideoSize linphone_core_get_preferred_video_size(const LinphoneCore *lc){
return lc->video_conf.vsize;
}
+char * linphone_core_get_preferred_video_size_name(const LinphoneCore *lc) {
+ return ms_strdup(video_size_get_name(lc->video_conf.vsize));
+}
+
/**
* Set the preferred frame rate for video.
* Based on the available bandwidth constraints and network conditions, the video encoder
@@ -5462,16 +5704,22 @@ float linphone_core_get_preferred_framerate(LinphoneCore *lc){
/**
* Ask the core to stream audio from and to files, instead of using the soundcard.
+ * @ingroup media_parameters
+ * @param[in] lc LinphoneCore object
+ * @param[in] yesno A boolean value asking to stream audio from and to files or not.
**/
-void linphone_core_use_files(LinphoneCore *lc, bool_t yesno){
+void linphone_core_set_use_files(LinphoneCore *lc, bool_t yesno){
lc->use_files=yesno;
}
/**
* Sets a wav file to be played when putting somebody on hold,
- * or when files are used instead of soundcards (see linphone_core_use_files()).
+ * or when files are used instead of soundcards (see linphone_core_set_use_files()).
*
* The file must be a 16 bit linear wav file.
+ * @ingroup media_parameters
+ * @param[in] lc LinphoneCore object
+ * @param[in] file The path to the file to be played when putting somebody on hold.
**/
void linphone_core_set_play_file(LinphoneCore *lc, const char *file){
LinphoneCall *call=linphone_core_get_current_call(lc);
@@ -5489,10 +5737,13 @@ void linphone_core_set_play_file(LinphoneCore *lc, const char *file){
/**
* Sets a wav file where incoming stream is to be recorded,
- * when files are used instead of soundcards (see linphone_core_use_files()).
+ * when files are used instead of soundcards (see linphone_core_set_use_files()).
*
* This feature is different from call recording (linphone_call_params_set_record_file())
* The file will be a 16 bit linear wav file.
+ * @ingroup media_parameters
+ * @param[in] lc LinphoneCore object
+ * @param[in] file The path to the file where incoming stream is to be recorded.
**/
void linphone_core_set_record_file(LinphoneCore *lc, const char *file){
LinphoneCall *call=linphone_core_get_current_call(lc);
@@ -5664,7 +5915,7 @@ void linphone_core_stop_dtmf(LinphoneCore *lc){
*
* @ingroup initializing
**/
-void *linphone_core_get_user_data(LinphoneCore *lc){
+void *linphone_core_get_user_data(const LinphoneCore *lc){
return lc->data;
}
@@ -5810,15 +6061,11 @@ void sip_config_uninit(LinphoneCore *lc)
}
if (i>=20) ms_warning("Cannot complete unregistration, giving up");
}
- ms_list_for_each(config->proxies,(void (*)(void*)) linphone_proxy_config_destroy);
- ms_list_free(config->proxies);
- config->proxies=NULL;
+ config->proxies=ms_list_free_with_data(config->proxies,(void (*)(void*)) _linphone_proxy_config_release);
/*no longuer need to write proxy config if not changedlinphone_proxy_config_write_to_config_file(lc->config,NULL,i);*/ /*mark the end */
- ms_list_for_each(lc->auth_info,(void (*)(void*))linphone_auth_info_destroy);
- ms_list_free(lc->auth_info);
- lc->auth_info=NULL;
+ lc->auth_info=ms_list_free_with_data(lc->auth_info,(void (*)(void*))linphone_auth_info_destroy);
/*now that we are unregisted, we no longer need the tunnel.*/
#ifdef TUNNEL_ENABLED
@@ -6011,28 +6258,19 @@ static void linphone_core_uninit(LinphoneCore *lc)
}
#endif //BUILD_UPNP
- if (lc->chatrooms){
- MSList *cr=ms_list_copy(lc->chatrooms);
- MSList *elem;
- for(elem=cr;elem!=NULL;elem=elem->next){
- linphone_chat_room_destroy((LinphoneChatRoom*)elem->data);
- }
- ms_list_free(cr);
- }
+ ms_list_for_each(lc->chatrooms, (MSIterateFunc)linphone_chat_room_release);
+ lc->chatrooms = ms_list_free(lc->chatrooms);
if (lp_config_needs_commit(lc->config)) lp_config_sync(lc->config);
lp_config_destroy(lc->config);
lc->config = NULL; /* Mark the config as NULL to block further calls */
- ms_list_for_each(lc->call_logs,(void (*)(void*))linphone_call_log_destroy);
+ ms_list_for_each(lc->call_logs,(void (*)(void*))linphone_call_log_unref);
lc->call_logs=ms_list_free(lc->call_logs);
ms_list_for_each(lc->last_recv_msg_ids,ms_free);
lc->last_recv_msg_ids=ms_list_free(lc->last_recv_msg_ids);
- // Free struct variable
- ms_free(lc->file_transfer_server);
-
if(lc->zrtp_secrets_cache != NULL) {
ms_free(lc->zrtp_secrets_cache);
}
@@ -6053,6 +6291,7 @@ static void linphone_core_uninit(LinphoneCore *lc)
if (liblinphone_serialize_logs == TRUE) {
ortp_set_log_thread_id(0);
}
+ ms_list_free_with_data(lc->vtables,(void (*)(void *))linphone_core_v_table_destroy);
}
static void set_network_reachable(LinphoneCore* lc,bool_t isReachable, time_t curtime){
@@ -6060,7 +6299,7 @@ static void set_network_reachable(LinphoneCore* lc,bool_t isReachable, time_t cu
const MSList *elem=linphone_core_get_proxy_config_list(lc);
if (lc->network_reachable==isReachable) return; // no change, ignore.
-
+ lc->network_reachable_to_be_notified=TRUE;
ms_message("Network state is now [%s]",isReachable?"UP":"DOWN");
for(;elem!=NULL;elem=elem->next){
LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)elem->data;
@@ -6231,8 +6470,8 @@ static PayloadType* find_payload_type_from_list(const char* type, int rate, int
}
-PayloadType* linphone_core_find_payload_type(LinphoneCore* lc, const char* type, int rate, int channels) {
- PayloadType* result = find_payload_type_from_list(type, rate, channels, linphone_core_get_audio_codecs(lc));
+LinphonePayloadType* linphone_core_find_payload_type(LinphoneCore* lc, const char* type, int rate, int channels) {
+ LinphonePayloadType* result = find_payload_type_from_list(type, rate, channels, linphone_core_get_audio_codecs(lc));
if (result) {
return result;
} else {
@@ -6270,11 +6509,25 @@ LinphoneGlobalState linphone_core_get_global_state(const LinphoneCore *lc){
}
LinphoneCallParams *linphone_core_create_default_call_parameters(LinphoneCore *lc){
- LinphoneCallParams *p=ms_new0(LinphoneCallParams,1);
+ LinphoneCallParams *p=linphone_call_params_new();
linphone_core_init_default_params(lc, p);
return p;
}
+/**
+ * Create a LinphoneCallParams suitable for linphone_core_invite_with_params(), linphone_core_accept_call_with_params(), linphone_core_accept_early_media_with_params(),
+ * linphone_core_accept_call_update().
+ * The parameters are initialized according to the current LinphoneCore configuration and the current state of the LinphoneCall.
+ * @param lc the LinphoneCore
+ * @param call the call for which the parameters are to be build, or NULL in the case where the parameters are to be used for a new outgoing call.
+ * @return a new LinphoneCallParams
+ * @ingroup call_control
+ */
+LinphoneCallParams *linphone_core_create_call_params(LinphoneCore *lc, LinphoneCall *call){
+ if (!call) return linphone_core_create_default_call_parameters(lc);
+ return linphone_call_params_copy(call->params);
+}
+
const char *linphone_reason_to_string(LinphoneReason err){
switch(err){
case LinphoneReasonNone:
@@ -6683,5 +6936,220 @@ bool_t linphone_core_sdp_200_ack_enabled(const LinphoneCore *lc) {
}
void linphone_core_set_file_transfer_server(LinphoneCore *core, const char * server_url) {
- core->file_transfer_server=ms_strdup(server_url);
+ lp_config_set_string(core->config, "misc", "file_transfer_server_url", server_url);
+}
+
+const char * linphone_core_get_file_transfer_server(LinphoneCore *core) {
+ return lp_config_get_string(core->config, "misc", "file_transfer_server_url", NULL);
+}
+
+/**
+ * This function controls signaling features supported by the core.
+ * They are typically included in a SIP Supported header.
+ * @param lc the LinphoneCore
+ * @param tag the feature tag name
+ * @ingroup initializing
+**/
+void linphone_core_add_supported_tag(LinphoneCore *lc, const char *tag){
+ sal_add_supported_tag(lc->sal,tag);
+ lp_config_set_string(lc->config,"sip","supported",sal_get_supported_tags(lc->sal));
+}
+
+/**
+ * Remove a supported tag. @see linphone_core_add_supported_tag()
+ * @param lc the LinphoneCore
+ * @param tag the tag to remove
+ * @ingroup initializing
+**/
+void linphone_core_remove_supported_tag(LinphoneCore *lc, const char *tag){
+ sal_remove_supported_tag(lc->sal,tag);
+ lp_config_set_string(lc->config,"sip","supported",sal_get_supported_tags(lc->sal));
+}
+
+/**
+ * Enable RTCP feedback (also known as RTP/AVPF profile).
+ * Setting LinphoneAVPFDefault is equivalent to LinphoneAVPFDisabled.
+ * This setting can be overriden per LinphoneProxyConfig with linphone_proxy_config_set_avpf_mode().
+ * The value set here is used for calls placed or received out of any proxy configured, or if the proxy config is configured with LinphoneAVPFDefault.
+ * @param lc the LinphoneCore
+ * @param mode the mode.
+ * @ingroup media_parameters
+**/
+void linphone_core_set_avpf_mode(LinphoneCore *lc, LinphoneAVPFMode mode){
+ if (mode==LinphoneAVPFDefault) mode=LinphoneAVPFDisabled;
+ lc->rtp_conf.avpf_mode=mode;
+ if (linphone_core_ready(lc)) lp_config_set_int(lc->config,"rtp","avpf",mode);
+}
+
+/**
+ * Return AVPF enablement. See linphone_core_set_avpf_mode() .
+ * @param lc the core
+ * @return the avpf enablement mode.
+ * @ingroup media_parameters
+**/
+LinphoneAVPFMode linphone_core_get_avpf_mode(const LinphoneCore *lc){
+ return lc->rtp_conf.avpf_mode;
+}
+
+/**
+ * Return the avpf report interval in seconds.
+ * @param lc the LinphoneCore
+ * @return the avpf report interval in seconds.
+ * @ingroup media_parameters
+**/
+int linphone_core_get_avpf_rr_interval(const LinphoneCore *lc){
+ return lp_config_get_int(lc->config,"rtp","avpf_rr_interval",5);
+}
+
+/**
+ * Set the avpf report interval in seconds.
+ * This value can be overriden by the proxy config using linphone_proxy_config_set_avpf_rr_interval().
+ * @param lc the core
+ * @param interval interval in seconds.
+ * @ingroup media_parameters
+**/
+void linphone_core_set_avpf_rr_interval(LinphoneCore *lc, int interval){
+ lp_config_set_int(lc->config,"rtp","avpf_rr_interval",interval);
+}
+
+int linphone_payload_type_get_type(const LinphonePayloadType *pt) {
+ return pt->type;
+}
+
+int linphone_payload_type_get_normal_bitrate(const LinphonePayloadType *pt) {
+ return pt->normal_bitrate;
+}
+
+char * linphone_payload_type_get_mime_type(const LinphonePayloadType *pt) {
+ return pt->mime_type;
+}
+
+int linphone_payload_type_get_channels(const LinphonePayloadType *pt) {
+ return pt->channels;
+}
+
+LinphoneCoreVTable *linphone_core_v_table_new() {
+ return ms_new0(LinphoneCoreVTable,1);
+}
+
+void linphone_core_v_table_destroy(LinphoneCoreVTable* table) {
+ ms_free(table);
+}
+#define NOTIFY_IF_EXIST(function_name) \
+ MSList* iterator; \
+ ms_message ("Linphone core [%p] notifying [%s]",lc,#function_name);\
+ for (iterator=lc->vtables; iterator!=NULL; iterator=iterator->next) \
+ if (((LinphoneCoreVTable*)(iterator->data))->function_name)\
+ ((LinphoneCoreVTable*)(iterator->data))->function_name
+
+void linphone_core_notify_global_state_changed(LinphoneCore *lc, LinphoneGlobalState gstate, const char *message) {
+ NOTIFY_IF_EXIST(global_state_changed)(lc,gstate,message);
+}
+void linphone_core_notify_call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate, const char *message){
+ NOTIFY_IF_EXIST(call_state_changed)(lc,call,cstate,message);
+}
+void linphone_core_notify_call_encryption_changed(LinphoneCore *lc, LinphoneCall *call, bool_t on, const char *authentication_token) {
+ NOTIFY_IF_EXIST(call_encryption_changed)(lc,call,on,authentication_token);
+}
+void linphone_core_notify_registration_state_changed(LinphoneCore *lc, LinphoneProxyConfig *cfg, LinphoneRegistrationState cstate, const char *message){
+ NOTIFY_IF_EXIST(registration_state_changed)(lc,cfg,cstate,message);
+}
+void linphone_core_notify_show_interface(LinphoneCore *lc){
+ NOTIFY_IF_EXIST(show)(lc);
+}
+void linphone_core_notify_display_status(LinphoneCore *lc, const char *message) {
+ NOTIFY_IF_EXIST(display_status)(lc,message);
+}
+void linphone_core_notify_display_message(LinphoneCore *lc, const char *message){
+ NOTIFY_IF_EXIST(display_message)(lc,message);
+}
+void linphone_core_notify_display_warning(LinphoneCore *lc, const char *message){
+ NOTIFY_IF_EXIST(display_warning)(lc,message);
+}
+void linphone_core_notify_display_url(LinphoneCore *lc, const char *message, const char *url){
+ NOTIFY_IF_EXIST(display_url)(lc,message,url);
+}
+void linphone_core_notify_notify_presence_received(LinphoneCore *lc, LinphoneFriend * lf){
+ NOTIFY_IF_EXIST(notify_presence_received)(lc,lf);
+}
+void linphone_core_notify_new_subscription_requested(LinphoneCore *lc, LinphoneFriend *lf, const char *url){
+ NOTIFY_IF_EXIST(new_subscription_requested)(lc,lf,url);
+}
+void linphone_core_notify_auth_info_requested(LinphoneCore *lc, const char *realm, const char *username, const char *domain){
+ NOTIFY_IF_EXIST(auth_info_requested)(lc,realm,username,domain);
+}
+void linphone_core_notify_call_log_updated(LinphoneCore *lc, LinphoneCallLog *newcl){
+ NOTIFY_IF_EXIST(call_log_updated)(lc,newcl);
+}
+void linphone_core_notify_text_message_received(LinphoneCore *lc, LinphoneChatRoom *room, const LinphoneAddress *from, const char *message){
+ NOTIFY_IF_EXIST(text_received)(lc,room,from,message);
+}
+void linphone_core_notify_message_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage *message){
+ NOTIFY_IF_EXIST(message_received)(lc,room,message);
+}
+void linphone_core_notify_file_transfer_recv(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, const char* buff, size_t size) {
+ NOTIFY_IF_EXIST(file_transfer_recv)(lc,message,content,buff,size);
+}
+void linphone_core_notify_file_transfer_send(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, char* buff, size_t* size) {
+ NOTIFY_IF_EXIST(file_transfer_send)(lc,message,content,buff,size);
+}
+void linphone_core_notify_file_transfer_progress_indication(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, size_t offset, size_t total) {
+ NOTIFY_IF_EXIST(file_transfer_progress_indication)(lc,message,content,offset,total);
+}
+void linphone_core_notify_is_composing_received(LinphoneCore *lc, LinphoneChatRoom *room) {
+ NOTIFY_IF_EXIST(is_composing_received)(lc,room);
+}
+void linphone_core_notify_dtmf_received(LinphoneCore* lc, LinphoneCall *call, int dtmf) {
+ NOTIFY_IF_EXIST(dtmf_received)(lc,call,dtmf);
+}
+bool_t linphone_core_dtmf_received_has_listener(const LinphoneCore* lc) {
+ MSList* iterator;
+ for (iterator=lc->vtables; iterator!=NULL; iterator=iterator->next)
+ if (((LinphoneCoreVTable*)(iterator->data))->dtmf_received)
+ return TRUE;
+ return FALSE;
+}
+void linphone_core_notify_refer_received(LinphoneCore *lc, const char *refer_to) {
+ NOTIFY_IF_EXIST(refer_received)(lc,refer_to);
+}
+void linphone_core_notify_buddy_info_updated(LinphoneCore *lc, LinphoneFriend *lf) {
+ NOTIFY_IF_EXIST(buddy_info_updated)(lc,lf);
+}
+void linphone_core_notify_transfer_state_changed(LinphoneCore *lc, LinphoneCall *transfered, LinphoneCallState new_call_state) {
+ NOTIFY_IF_EXIST(transfer_state_changed)(lc,transfered,new_call_state);
+}
+void linphone_core_notify_call_stats_updated(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallStats *stats) {
+ NOTIFY_IF_EXIST(call_stats_updated)(lc,call,stats);
+}
+void linphone_core_notify_info_received(LinphoneCore *lc, LinphoneCall *call, const LinphoneInfoMessage *msg) {
+ NOTIFY_IF_EXIST(info_received)(lc,call,msg);
+}
+void linphone_core_notify_configuring_status(LinphoneCore *lc, LinphoneConfiguringState status, const char *message) {
+ NOTIFY_IF_EXIST(configuring_status)(lc,status,message);
+}
+void linphone_core_notify_network_reachable(LinphoneCore *lc, bool_t reachable) {
+ NOTIFY_IF_EXIST(network_reachable)(lc,reachable);
+}
+void linphone_core_notify_notify_received(LinphoneCore *lc, LinphoneEvent *lev, const char *notified_event, const LinphoneContent *body) {
+ NOTIFY_IF_EXIST(notify_received)(lc,lev,notified_event,body);
+}
+void linphone_core_notify_subscription_state_changed(LinphoneCore *lc, LinphoneEvent *lev, LinphoneSubscriptionState state) {
+ NOTIFY_IF_EXIST(subscription_state_changed)(lc,lev,state);
+}
+void linphone_core_notify_publish_state_changed(LinphoneCore *lc, LinphoneEvent *lev, LinphonePublishState state) {
+ NOTIFY_IF_EXIST(publish_state_changed)(lc,lev,state);
+}
+void linphone_core_notify_log_collection_upload_state_changed(LinphoneCore *lc, LinphoneCoreLogCollectionUploadState state, const char *info) {
+ NOTIFY_IF_EXIST(log_collection_upload_state_changed)(lc, state, info);
+}
+void linphone_core_notify_log_collection_upload_progress_indication(LinphoneCore *lc, size_t offset, size_t total) {
+ NOTIFY_IF_EXIST(log_collection_upload_progress_indication)(lc, offset, total);
+}
+void linphone_core_add_listener(LinphoneCore *lc, LinphoneCoreVTable *vtable) {
+ ms_message("Vtable [%p] registered on core [%p]",lc,vtable);
+ lc->vtables=ms_list_append(lc->vtables,vtable);
+}
+void linphone_core_remove_listener(LinphoneCore *lc, const LinphoneCoreVTable *vtable) {
+ ms_message("Vtable [%p] unregistered on core [%p]",lc,vtable);
+ lc->vtables=ms_list_remove(lc->vtables,(void*)vtable);
}
diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h
index 9fdb864df..edb390570 100644
--- a/coreapi/linphonecore.h
+++ b/coreapi/linphonecore.h
@@ -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"
@@ -247,86 +248,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);
+/**
+ * @addtogroup media_parameters
+ * @{
+**/
/**
- * 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
+ * Object representing an RTP payload type.
*/
-LINPHONE_PUBLIC LinphoneAddress * linphone_core_create_address(LinphoneCore *lc, const char *address);
+typedef PayloadType LinphonePayloadType;
-struct _SipSetupContext;
+/**
+ * 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);
/**
- * Enum representing the direction of a call.
- * @ingroup call_logs
-**/
-enum _LinphoneCallDir {
- LinphoneCallOutgoing, /**< outgoing calls*/
- LinphoneCallIncoming /**< incoming calls*/
-};
+ * 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);
/**
- * Typedef for enum
- * @ingroup call_logs
-**/
-typedef enum _LinphoneCallDir LinphoneCallDir;
+ * 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 representing the status of a call
- * @ingroup call_logs
+ * Enum describing RTP AVPF activation modes.
**/
-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;
+enum _LinphoneAVPFMode{
+ LinphoneAVPFDefault=-1, /**