diff --git a/.gitignore b/.gitignore
index 6a94843fa..d5a842ef1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -73,3 +73,6 @@ tools/xml2lpc_test
coreapi/help/filetransfer
tester/receive_file.dump
tester/tmp.db
+.DS_Store
+Linphone.app
+*.dmg
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 e10ecc2d2..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,7 +31,7 @@ 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 \
@@ -43,22 +43,19 @@ 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
@@ -71,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.
@@ -89,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 e3ffb72d5..000000000
--- a/README.macos
+++ /dev/null
@@ -1,146 +0,0 @@
-**********************************
-* Compiling linphone on macos X *
-**********************************
-
-You need:
- - Xcode (download from apple or using appstore application)
- - Java SE
- - Macports: http://www.macports.org/
- Download and install macports using its user friendly installer.
-
-- 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 libupnp
- $ 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/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 949eed600..d8c8a1269 100755
--- a/build/android/Android.mk
+++ b/build/android/Android.mk
@@ -70,6 +70,7 @@ LOCAL_SRC_FILES := \
call_params.c \
lime.c \
player.c
+ localplayer.c
ifndef LIBLINPHONE_VERSION
LIBLINPHONE_VERSION = "Devel"
@@ -267,5 +268,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_tester.mk b/build/android/liblinphone_tester.mk
index a6a2ab5f5..b23a381bd 100644
--- a/build/android/liblinphone_tester.mk
+++ b/build/android/liblinphone_tester.mk
@@ -14,7 +14,8 @@ common_SRC_FILES := \
tester.c \
remote_provisioning_tester.c \
quality_reporting_tester.c \
- transport_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 8b0660688..876c93d2a 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\;%(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;HAVE_ZLIB;%(PreprocessorDefinitions)
Default
NotUsing
false
@@ -74,7 +74,7 @@
- _DEBUG;%(PreprocessorDefinitions)
+ _DEBUG;MSG_STORAGE_ENABLED;%(PreprocessorDefinitions)
true
@@ -82,7 +82,7 @@
- NDEBUG;%(PreprocessorDefinitions)
+ NDEBUG;MSG_STORAGE_ENABLED;%(PreprocessorDefinitions)
MaxSpeed
true
true
@@ -121,6 +121,7 @@
+
@@ -189,6 +190,9 @@
{0565952a-ea62-46a2-8261-f5b4b490da42}
+
+ {a45d63b9-60de-476c-8836-f8eedbe139d0}
+
{59500dd1-b192-4ddf-a402-8a8e3739e032}
@@ -201,6 +205,9 @@
{5dfa07b4-0be9-46a9-ba32-fdf5a55c580b}
+
+ {7afac3bb-d97b-4578-b9fe-5e1d2b94ea2f}
+
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/coreapi/Makefile.am b/coreapi/Makefile.am
index 7e47f0bcf..948d28b77 100644
--- a/coreapi/Makefile.am
+++ b/coreapi/Makefile.am
@@ -63,7 +63,7 @@ liblinphone_la_SOURCES=\
call_log.c \
call_params.c \
player.c \
- fileplayer.c \
+ localplayer.c \
$(GITVERSION_FILE)
if BUILD_UPNP
diff --git a/coreapi/TunnelManager.cc b/coreapi/TunnelManager.cc
index a0158a88a..77e26fb1b 100644
--- a/coreapi/TunnelManager.cc
+++ b/coreapi/TunnelManager.cc
@@ -97,32 +97,15 @@ RtpTransport *TunnelManager::createRtpTransport(int port){
void TunnelManager::startClient() {
ms_message("TunnelManager: Starting tunnel client");
- if (mTunnelClient == NULL) {
- 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 = 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();
- linphone_core_set_rtp_transport_factories(mCore,&mTransportFactories);
- if(mTunnelizeSipPackets) {
- sal_enable_tunnel(mCore->sal, mTunnelClient);
- }
- mConnecting = true;
-}
-
-void TunnelManager::stopClient(){
- ms_message("TunnelManager: Stopping tunnel client");
- linphone_core_set_rtp_transport_factories(mCore,NULL);
- sal_disable_tunnel(mCore->sal);
- if (mTunnelClient){
- delete mTunnelClient;
- mTunnelClient=NULL;
- }
}
bool TunnelManager::isConnected() const {
@@ -151,9 +134,7 @@ TunnelManager::TunnelManager(LinphoneCore* lc) :
mExosipTransport(NULL),
#endif
mMode(LinphoneTunnelModeDisable),
- mAutoDetecting(false),
- mConnecting(false),
- mScheduledRegistration(false),
+ mState(disabled),
mTunnelizeSipPackets(true),
mTunnelClient(NULL),
mHttpProxyPort(0),
@@ -168,7 +149,7 @@ TunnelManager::TunnelManager(LinphoneCore* lc) :
mTransportFactories.video_rtcp_func_data=this;
mTransportFactories.video_rtp_func=sCreateRtpTransport;
mTransportFactories.video_rtp_func_data=this;
- mVTable = linphone_vtable_new();
+ mVTable = linphone_core_v_table_new();
mVTable->network_reachable = networkReachableCb;
linphone_core_add_listener(mCore, mVTable);
}
@@ -177,62 +158,94 @@ TunnelManager::~TunnelManager(){
for(UdpMirrorClientList::iterator udpMirror = mUdpMirrorClients.begin(); udpMirror != mUdpMirrorClients.end(); udpMirror++) {
udpMirror->stop();
}
- stopClient();
+ if(mTunnelClient) delete mTunnelClient;
linphone_core_remove_listener(mCore, mVTable);
- linphone_vtable_destroy(mVTable);
+ linphone_core_v_table_destroy(mVTable);
}
void TunnelManager::doRegistration(){
- if(mTunnelizeSipPackets) {
- LinphoneProxyConfig* lProxy;
- linphone_core_get_default_proxy(mCore, &lProxy);
- if (lProxy) {
- ms_message("TunnelManager: need to register");
- if(linphone_proxy_config_get_state(lProxy) != LinphoneRegistrationProgress) {
- linphone_proxy_config_refresh_register(lProxy);
- mScheduledRegistration = false;
- } else {
- ms_warning("TunnelManager: register difered. There is already a registration in progress");
- mScheduledRegistration = true;
- }
- } else {
- mScheduledRegistration = false;
- }
+ LinphoneProxyConfig* lProxy;
+ linphone_core_get_default_proxy(mCore, &lProxy);
+ if (lProxy) {
+ ms_message("TunnelManager: New registration");
+ lProxy->commit = TRUE;
+ }
+}
+
+void TunnelManager::doUnregistration() {
+ LinphoneProxyConfig *lProxy;
+ linphone_core_get_default_proxy(mCore, &lProxy);
+ if(lProxy) {
+ _linphone_proxy_config_unregister(lProxy);
}
}
void TunnelManager::processTunnelEvent(const Event &ev){
if (ev.mData.mConnected){
- ms_message("Tunnel is connected");
- doRegistration();
+ 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;
+ }
} else {
- ms_error("Tunnel has been disconnected");
+ ms_error("TunnelManager: tunnel has been disconnected");
}
- mConnecting = false;
}
void TunnelManager::setMode(LinphoneTunnelMode mode) {
- if(mMode != mode) {
- ms_message("TunnelManager: Switching mode from %s to %s",
- tunnel_mode_to_string(mMode),
- tunnel_mode_to_string(mode));
- switch(mode) {
- case LinphoneTunnelModeEnable:
- mMode = 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();
- break;
- case LinphoneTunnelModeDisable:
+ mState = connecting;
mMode = mode;
- stopClient();
- doRegistration();
- break;
- case LinphoneTunnelModeAuto:
- mMode = mode;
- autoDetect();
- break;
- default:
- ms_error("TunnelManager::setMode(): invalid mode (%d)", 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);
+ }
+ 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);
}
}
@@ -244,10 +257,6 @@ void TunnelManager::tunnelCallback(bool connected, TunnelManager *zis){
}
void TunnelManager::onIterate(){
- if(mScheduledRegistration) {
- ms_message("Apply difered registration");
- doRegistration();
- }
mMutex.lock();
while(!mEvq.empty()){
Event ev=mEvq.front();
@@ -313,22 +322,31 @@ LinphoneTunnelMode TunnelManager::getMode() const {
}
void TunnelManager::processUdpMirrorEvent(const Event &ev){
+ if(mState != autodetecting) return;
if (ev.mData.mHaveUdp) {
- ms_message("TunnelManager: auto detection test succeed");
- stopClient();
- doRegistration();
- mAutoDetecting = 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: auto detection test failed");
+ ms_message("TunnelManager: UDP mirror test failed");
mCurrentUdpMirrorClient++;
if (mCurrentUdpMirrorClient !=mUdpMirrorClients.end()) {
- ms_message("TunnelManager: trying another udp mirror");
+ ms_message("TunnelManager: trying another UDP mirror");
UdpMirrorClient &lUdpMirrorClient=*mCurrentUdpMirrorClient;
lUdpMirrorClient.start(TunnelManager::sUdpMirrorClientCallback,(void*)this);
} else {
- ms_message("TunnelManager: all auto detection failed. Need ti enable tunnel");
- startClient();
- mAutoDetecting = false;
+ ms_message("TunnelManager: all UDP mirror tests failed");
+ if(mTunnelClient==NULL) {
+ startClient();
+ mState = connecting;
+ } else {
+ mState = ready;
+ }
}
}
}
@@ -349,24 +367,22 @@ void TunnelManager::sUdpMirrorClientCallback(bool isUdpAvailable, void* data) {
void TunnelManager::networkReachableCb(LinphoneCore *lc, bool_t reachable) {
TunnelManager *tunnel = bcTunnel(linphone_core_get_tunnel(lc));
- if(reachable && tunnel->getMode() == LinphoneTunnelModeAuto) {
- tunnel->autoDetect();
+ if(reachable && tunnel->getMode() == LinphoneTunnelModeAuto && tunnel->mState != connecting && tunnel->mState != autodetecting) {
+ tunnel->startAutoDetection();
+ tunnel->mState = autodetecting;
}
}
-void TunnelManager::autoDetect() {
- if(mAutoDetecting) {
- ms_error("TunnelManager: Cannot start auto detection. One auto detection is going on");
- return;
- }
+bool TunnelManager::startAutoDetection() {
if (mUdpMirrorClients.empty()) {
ms_error("TunnelManager: No UDP mirror server configured aborting auto detection");
- return;
+ return false;
}
+ ms_message("TunnelManager: Starting auto-detection");
mCurrentUdpMirrorClient = mUdpMirrorClients.begin();
UdpMirrorClient &lUdpMirrorClient=*mCurrentUdpMirrorClient;
lUdpMirrorClient.start(TunnelManager::sUdpMirrorClientCallback,(void*)this);
- mAutoDetecting = true;
+ return true;
}
void TunnelManager::setHttpProxyAuthInfo(const char* username,const char* passwd) {
diff --git a/coreapi/TunnelManager.hh b/coreapi/TunnelManager.hh
index 9b1a4c3a9..58475aab3 100644
--- a/coreapi/TunnelManager.hh
+++ b/coreapi/TunnelManager.hh
@@ -143,6 +143,13 @@ namespace belledonnecomm {
bool isConnected() const;
private:
+ enum State {
+ disabled,
+ connecting,
+ ready,
+ autodetecting
+ };
+
enum EventType{
UdpMirrorClientEvent,
TunnelEvent,
@@ -168,9 +175,9 @@ namespace belledonnecomm {
private:
void onIterate();
void doRegistration();
+ void doUnregistration();
void startClient();
- void stopClient();
- void autoDetect();
+ bool startAutoDetection();
void processTunnelEvent(const Event &ev);
void processUdpMirrorEvent(const Event &ev);
void postEvent(const Event &ev);
@@ -178,9 +185,7 @@ namespace belledonnecomm {
private:
LinphoneCore* mCore;
LinphoneTunnelMode mMode;
- bool mAutoDetecting;
- bool mConnecting;
- bool mScheduledRegistration;
+ State mState;
bool mTunnelizeSipPackets;
TunnelClient* mTunnelClient;
std::string mHttpUserName;
diff --git a/coreapi/bellesip_sal/sal_op_call.c b/coreapi/bellesip_sal/sal_op_call.c
index 9efbbb7ee..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;
@@ -639,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){
@@ -766,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))) {
diff --git a/coreapi/call_log.c b/coreapi/call_log.c
index d1e59578f..7ce488096 100644
--- a/coreapi/call_log.c
+++ b/coreapi/call_log.c
@@ -281,6 +281,7 @@ LinphoneCallLog * linphone_call_log_new(LinphoneCallDir dir, LinphoneAddress *fr
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;
}
diff --git a/coreapi/call_log.h b/coreapi/call_log.h
index d274037d2..6a3ec8dab 100644
--- a/coreapi/call_log.h
+++ b/coreapi/call_log.h
@@ -79,7 +79,7 @@ LINPHONE_PUBLIC const char * linphone_call_log_get_call_id(const LinphoneCallLog
LINPHONE_PUBLIC LinphoneCallDir linphone_call_log_get_dir(LinphoneCallLog *cl);
/**
- * Get the duration of the call.
+ * Get the duration of the call since connected.
* @param[in] cl LinphoneCallLog object
* @return The duration of the call in seconds.
**/
diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c
index f60e230f8..bb6b5b9fb 100644
--- a/coreapi/callbacks.c
+++ b/coreapi/callbacks.c
@@ -234,9 +234,9 @@ 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);
@@ -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.");
@@ -395,6 +411,7 @@ 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.");
@@ -417,12 +434,21 @@ static void call_accepted(SalOp *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);
+ 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) ||
@@ -435,7 +461,7 @@ static void call_accepted(SalOp *op){
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)){
@@ -448,7 +474,7 @@ static void call_accepted(SalOp *op){
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){
@@ -469,8 +495,7 @@ static void call_accepted(SalOp *op){
linphone_call_fix_call_parameters(call);
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*/
@@ -554,7 +579,8 @@ static void call_updated_by_remote(LinphoneCore *lc, LinphoneCall *call, bool_t
if (rmd==NULL)
call->expect_media_in_ack=TRUE;
} else if (is_update){ /*SIP UPDATE case, can occur in early states*/
- _linphone_core_accept_call_update(lc,call,NULL,call->state,linphone_call_state_to_string(call->state));
+ linphone_call_set_state(call, LinphoneCallEarlyUpdatedByRemote, "EarlyUpdatedByRemote");
+ _linphone_core_accept_call_update(lc,call,NULL,call->prevstate,linphone_call_state_to_string(call->prevstate));
}
}
@@ -611,6 +637,8 @@ static void call_updating(SalOp *op, bool_t is_update){
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;
}
diff --git a/coreapi/chat.c b/coreapi/chat.c
index 37fce3225..d48609fad 100644
--- a/coreapi/chat.c
+++ b/coreapi/chat.c
@@ -38,22 +38,20 @@
static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatMessage* msg);
-#define MULTIPART_BOUNDARY "---------------------------14737809831466499882746641449"
-const char *multipart_boundary=MULTIPART_BOUNDARY;
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);
}
#define FILE_TRANSFER_KEY_SIZE 32
}
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);
}
}
@@ -61,14 +59,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);
}
}
@@ -80,7 +78,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 */
- linphone_core_notify_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;
}
@@ -150,9 +148,8 @@ static void linphone_chat_message_process_response_from_post_file(void *data, co
belle_http_request_t *req;
belle_sip_multipart_body_handler_t *bh;
char* ua;
- char *content_type;
char *first_part_header;
- belle_sip_user_body_handler_t *first_part_bh;
+ belle_sip_body_handler_t *first_part_bh;
/* shall we encrypt the file */
if (msg->chat_room->lc->lime == 1) {
@@ -168,27 +165,26 @@ static void linphone_chat_message_process_response_from_post_file(void *data, co
}
/* create a user body handler to take care of the file and add the content disposition and content-type headers */
- first_part_bh=belle_sip_user_body_handler_new(msg->file_transfer_information->size,NULL,NULL,linphone_chat_message_file_transfer_on_send_body,msg);
- belle_sip_body_handler_add_header((belle_sip_body_handler_t *)first_part_bh, belle_sip_header_create("Content-disposition", first_part_header));
+ 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((belle_sip_body_handler_t *)first_part_bh, (belle_sip_header_t *)belle_sip_header_content_type_create(msg->file_transfer_information->type, msg->file_transfer_information->subtype));
+ belle_sip_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));
/* 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, (belle_sip_body_handler_t *)first_part_bh);
+ 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());
-
- content_type=belle_sip_strdup_printf("multipart/form-data; boundary=%s",multipart_boundary);
-
- uri=belle_generic_uri_parse(msg->chat_room->lc->file_transfer_server);
-
+ 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;
@@ -258,6 +254,9 @@ static void linphone_chat_message_process_response_from_post_file(void *data, co
}
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);
}
}
@@ -508,7 +507,7 @@ static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatM
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,
@@ -1190,16 +1189,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);
@@ -1212,6 +1216,9 @@ static void linphone_chat_process_response_from_get_file(void *data, const belle
}
/* file downloaded succesfully, call again the callback with size at zero */
linphone_core_notify_file_transfer_recv(lc, chatMsg, chatMsg->file_transfer_information, NULL, 0);
+ if (chatMsg->cb) {
+ chatMsg->cb(chatMsg, LinphoneChatMessageStateFileTransferDone, chatMsg->cb_ud);
+ }
}
}
}
@@ -1222,7 +1229,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;
@@ -1247,6 +1254,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);
}
@@ -1256,12 +1264,12 @@ 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);
}
}
@@ -1412,6 +1420,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;
}
@@ -1439,6 +1448,9 @@ 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);
}
@@ -1475,6 +1487,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
diff --git a/coreapi/fileplayer.c b/coreapi/fileplayer.c
deleted file mode 100644
index 6752dc9e1..000000000
--- a/coreapi/fileplayer.c
+++ /dev/null
@@ -1,65 +0,0 @@
-#include "private.h"
-#include
-#include
-
-static int file_player_open(LinphonePlayer *obj, const char *filename);
-static int file_player_start(LinphonePlayer *obj);
-static int file_player_pause(LinphonePlayer *obj);
-static int file_player_seek(LinphonePlayer *obj, int time_ms);
-static MSPlayerState file_player_get_state(LinphonePlayer *obj);
-static void file_player_close(LinphonePlayer *obj);
-static void file_player_eof_callback(void *user_data);
-
-LinphonePlayer *linphone_core_create_file_player(LinphoneCore *lc, MSSndCard *snd_card, const char *video_out) {
- LinphonePlayer *obj = ms_new0(LinphonePlayer, 1);
- if(snd_card == NULL) snd_card = lc->sound_conf.play_sndcard;
- if(video_out == NULL) video_out = linphone_core_get_video_display_filter(lc);
- obj->impl = ms_file_player_new(snd_card, video_out);
- obj->open = file_player_open;
- obj->start = file_player_start;
- obj->pause = file_player_pause;
- obj->seek = file_player_seek;
- obj->get_state = file_player_get_state;
- obj->close = file_player_close;
- ms_file_player_set_eof_callback((MSFilePlayer *)obj->impl, file_player_eof_callback, obj);
- return obj;
-}
-
-void linphone_file_player_destroy(LinphonePlayer *obj) {
- ms_file_player_free((MSFilePlayer *)obj->impl);
- ms_free(obj);
-}
-
-bool_t linphone_file_player_matroska_supported(void) {
- return ms_file_player_matroska_supported();
-}
-
-static int file_player_open(LinphonePlayer *obj, const char *filename) {
- return ms_file_player_open((MSFilePlayer *)obj->impl, filename) ? 0 : -1;
-}
-
-static int file_player_start(LinphonePlayer *obj) {
- return ms_file_player_start((MSFilePlayer *)obj->impl) ? 0 : -1;
-}
-
-static int file_player_pause(LinphonePlayer *obj) {
- ms_file_player_pause((MSFilePlayer *)obj->impl);
- return 0;
-}
-
-static int file_player_seek(LinphonePlayer *obj, int time_ms) {
- return ms_file_player_seek((MSFilePlayer *)obj->impl, time_ms) ? 0 : -1;
-}
-
-static MSPlayerState file_player_get_state(LinphonePlayer *obj) {
- return ms_file_player_get_state((MSFilePlayer *)obj->impl);
-}
-
-static void file_player_close(LinphonePlayer *obj) {
- ms_file_player_close((MSFilePlayer *)obj->impl);
-}
-
-static void file_player_eof_callback(void *user_data) {
- LinphonePlayer *obj = (LinphonePlayer *)user_data;
- obj->cb(obj, obj->user_data);
-}
diff --git a/coreapi/help/filetransfer.c b/coreapi/help/filetransfer.c
index 7cfc2cca9..cfa2b19c2 100644
--- a/coreapi/help/filetransfer.c
+++ b/coreapi/help/filetransfer.c
@@ -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
@@ -132,7 +132,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);
}
diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c
index 3e9066e1d..e4766a7ed 100644
--- a/coreapi/linphonecall.c
+++ b/coreapi/linphonecall.c
@@ -564,7 +564,6 @@ static void linphone_call_init_common(LinphoneCall *call, LinphoneAddress *from,
ms_message("New LinphoneCall [%p] initialized (LinphoneCore version: %s)",call,linphone_core_get_version());
call->state=LinphoneCallIdle;
call->transfer_state = LinphoneCallIdle;
- call->media_start_time=0;
call->log=linphone_call_log_new(call->dir, from, to);
call->camera_enabled=TRUE;
call->current_params = linphone_call_params_new();
@@ -793,7 +792,7 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro
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.
@@ -924,6 +923,10 @@ 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";
}
@@ -968,7 +971,7 @@ void linphone_call_set_state_base(LinphoneCall *call, LinphoneCallState cstate,
}
if (cstate == LinphoneCallConnected) {
call->log->status=LinphoneCallSuccess;
- call->media_start_time=time(NULL);
+ call->log->connected_date_time=time(NULL);
}
if (!silently)
@@ -1280,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;
}
/**
@@ -2176,7 +2179,7 @@ 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;
if (call->videostream!=NULL) {
@@ -2950,7 +2953,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;
diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c
index 6c173a342..1e20f8fb5 100644
--- a/coreapi/linphonecore.c
+++ b/coreapi/linphonecore.c
@@ -24,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"
@@ -53,6 +55,20 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "TargetConditionals.h"
#endif
+#ifdef HAVE_ZLIB
+#define COMPRESSED_LOG_COLLECTION_FILENAME "linphone_log.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_FILENAME "linphone_log.txt"
+#endif
+
/*#define UNSTANDART_GSM_11K 1*/
#define ROOT_CA_FILE PACKAGE_DATA_DIR "/linphone/rootca.pem"
@@ -64,6 +80,10 @@ static const char *liblinphone_version=
LIBLINPHONE_VERSION
#endif
;
+static OrtpLogFunc liblinphone_log_func = NULL;
+static bool_t liblinphone_log_collection_enabled = FALSE;
+static char * liblinphone_log_collection_path = NULL;
+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);
@@ -144,6 +164,380 @@ void linphone_core_set_log_level(OrtpLogLevel loglevel) {
}
}
+#define LOGFILE_MAXSIZE (10 * 1024 * 1024)
+
+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);
+ }
+
+ 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 ORTP_MESSAGE:
+ lname = "MESSAGE";
+ break;
+ case ORTP_WARNING:
+ lname = "WARNING";
+ break;
+ case ORTP_ERROR:
+ lname = "ERROR";
+ break;
+ case ORTP_FATAL:
+ lname = "FATAL";
+ break;
+ default:
+ ortp_fatal("Bad level !");
+ }
+ msg = ortp_strdup_vprintf(fmt, args);
+
+ log_filename1 = ortp_strdup_printf("%s/%s", liblinphone_log_collection_path ? liblinphone_log_collection_path : ".", "linphone1.log");
+ log_filename2 = ortp_strdup_printf("%s/%s", liblinphone_log_collection_path ? liblinphone_log_collection_path : ".", "linphone2.log");
+ ortp_mutex_lock(&liblinphone_log_collection_mutex);
+ log_file = fopen(log_filename1, "a");
+ fstat(fileno(log_file), &statbuf);
+ if (statbuf.st_size > LOGFILE_MAXSIZE) {
+ fclose(log_file);
+ log_file = fopen(log_filename2, "a");
+ fstat(fileno(log_file), &statbuf);
+ if (statbuf.st_size > LOGFILE_MAXSIZE) {
+ 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);
+
+ ortp_free(log_filename1);
+ ortp_free(log_filename2);
+ ortp_free(msg);
+}
+
+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);
+ }
+}
+
+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);
+}
+
+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);
+}
+
+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;
+ }
+ if ((state != LinphoneLogCollectionDisabled) && (liblinphone_log_collection_enabled == FALSE)) {
+ liblinphone_log_collection_enabled = TRUE;
+ 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 {
+ liblinphone_log_collection_enabled = FALSE;
+ ortp_set_log_handler(liblinphone_log_func);
+ }
+}
+
+static void delete_log_collection_upload_file(void) {
+ char *filename = ms_strdup_printf("%s/%s", liblinphone_log_collection_path ? liblinphone_log_collection_path : ".", COMPRESSED_LOG_COLLECTION_FILENAME);
+ unlink(filename);
+ ms_free(filename);
+}
+
+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();
+}
+
+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();
+}
+
+/**
+ * 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
+ *
+ */
+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", liblinphone_log_collection_path ? liblinphone_log_collection_path : ".", COMPRESSED_LOG_COLLECTION_FILENAME);
+#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);
+ }
+
+ return BELLE_SIP_CONTINUE;
+}
+
+/**
+ * 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, (size_t)(((double)offset / (double)total) * 100.0));
+}
+
+/**
+ * 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
+ *
+ * @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();
+ }
+ }
+}
+
+#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
+
+/**
+ * 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;
+}
+
+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 : ".", filename);
+ output_file = COMPRESS_OPEN(output_filename, "a");
+ if (output_file == NULL) goto error;
+ input_filename = ms_strdup_printf("%s/%s", liblinphone_log_collection_path ? liblinphone_log_collection_path : ".", "linphone1.log");
+ 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/%s", liblinphone_log_collection_path ? liblinphone_log_collection_path : ".", "linphone2.log");
+ 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;
+}
+
+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 : ".", 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_enabled == TRUE)) {
+ /* 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 = COMPRESSED_LOG_COLLECTION_FILENAME;
+ 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) {
+ if (liblinphone_log_collection_enabled == FALSE) return NULL;
+ if (prepare_log_collection_file_to_upload(COMPRESSED_LOG_COLLECTION_FILENAME) < 0) return NULL;
+ return ms_strdup_printf("%s/%s", liblinphone_log_collection_path ? liblinphone_log_collection_path : ".", COMPRESSED_LOG_COLLECTION_FILENAME);
+}
+
+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/%s", liblinphone_log_collection_path ? liblinphone_log_collection_path : ".", "linphone1.log");
+ unlink(filename);
+ ms_free(filename);
+ filename = ms_strdup_printf("%s/%s", liblinphone_log_collection_path ? liblinphone_log_collection_path : ".", "linphone2.log");
+ unlink(filename);
+ ms_free(filename);
+ ortp_mutex_unlock(&liblinphone_log_collection_mutex);
+}
+
/**
* Enable logs in supplied FILE*.
*
@@ -661,6 +1055,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)){
@@ -1054,7 +1449,8 @@ 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;
- LinphoneCoreVTable* local_vtable= linphone_vtable_new();
+ const char *aac_ftmp162248, *aac_ftmp3244;
+ 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);
@@ -1100,17 +1496,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_ftmp162248 = "config=F8EE2000; constantDuration=512; indexDeltaLength=3; indexLength=3; mode=AAC-hbr; profile-level-id=76; sizeLength=13; streamType=5 SBR-enabled=1;";
+ aac_ftmp3244 = "config=F8E82000; constantDuration=512; indexDeltaLength=3; indexLength=3; mode=AAC-hbr; profile-level-id=76; sizeLength=13; streamType=5 SBR-enabled=1;";
+ } else {
+ aac_ftmp162248 = "config=F8EE2000; constantDuration=512; indexDeltaLength=3; indexLength=3; mode=AAC-hbr; profile-level-id=76; sizeLength=13; streamType=5";
+ aac_ftmp3244 = "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);
@@ -1124,8 +1532,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_ftmp162248);
+ linphone_core_assign_payload_type(lc,&payload_type_aaceld_22k,-1,aac_ftmp162248);
+ linphone_core_assign_payload_type(lc,&payload_type_aaceld_32k,-1,aac_ftmp3244);
+ linphone_core_assign_payload_type(lc,&payload_type_aaceld_44k,-1,aac_ftmp3244);
+ linphone_core_assign_payload_type(lc,&payload_type_aaceld_48k,-1,aac_ftmp162248);
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);
@@ -1148,8 +1559,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);
@@ -2078,8 +2487,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);
@@ -2907,15 +3316,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));
@@ -2923,7 +3337,7 @@ 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;
@@ -3134,8 +3548,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;
@@ -3148,9 +3561,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*/
@@ -4226,26 +4645,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;
+ linphone_core_mute_audio_stream(lc, lc->conf_ctx.local_participant, 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);
- }
-
+ 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);
}
}
@@ -5184,10 +5605,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
@@ -5782,9 +6207,6 @@ static void linphone_core_uninit(LinphoneCore *lc)
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);
}
@@ -5805,7 +6227,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_vtable_destroy);
+ 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){
@@ -6035,6 +6457,7 @@ LinphoneCallParams *linphone_core_create_default_call_parameters(LinphoneCore *l
* @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);
@@ -6449,11 +6872,11 @@ 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 core->file_transfer_server;
+ return lp_config_get_string(core->config, "misc", "file_transfer_server_url", NULL);
}
/**
@@ -6486,6 +6909,7 @@ void linphone_core_remove_supported_tag(LinphoneCore *lc, const char *tag){
* 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;
@@ -6497,6 +6921,7 @@ void linphone_core_set_avpf_mode(LinphoneCore *lc, LinphoneAVPFMode 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;
@@ -6506,6 +6931,7 @@ LinphoneAVPFMode linphone_core_get_avpf_mode(const LinphoneCore *lc){
* 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);
@@ -6515,10 +6941,11 @@ int linphone_core_get_avpf_rr_interval(const LinphoneCore *lc){
* 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.
+ * @param interval interval in seconds.
+ * @ingroup media_parameters
**/
void linphone_core_set_avpf_rr_interval(LinphoneCore *lc, int interval){
- return lp_config_set_int(lc->config,"rtp","avpf_rr_interval",interval);
+ lp_config_set_int(lc->config,"rtp","avpf_rr_interval",interval);
}
int linphone_payload_type_get_type(const LinphonePayloadType *pt) {
@@ -6537,11 +6964,11 @@ int linphone_payload_type_get_channels(const LinphonePayloadType *pt) {
return pt->channels;
}
-LinphoneCoreVTable *linphone_vtable_new() {
+LinphoneCoreVTable *linphone_core_v_table_new() {
return ms_new0(LinphoneCoreVTable,1);
}
-void linphone_vtable_destroy(LinphoneCoreVTable* table) {
+void linphone_core_v_table_destroy(LinphoneCoreVTable* table) {
ms_free(table);
}
#define NOTIFY_IF_EXIST(function_name) \
@@ -6602,8 +7029,8 @@ void linphone_core_notify_file_transfer_recv(LinphoneCore *lc, LinphoneChatMessa
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 progress) {
- NOTIFY_IF_EXIST(file_transfer_progress_indication)(lc,message,content,progress);
+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);
@@ -6648,6 +7075,12 @@ void linphone_core_notify_subscription_state_changed(LinphoneCore *lc, LinphoneE
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 progress) {
+ NOTIFY_IF_EXIST(log_collection_upload_progress_indication)(lc, progress);
+}
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);
diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h
index 5c06f103e..8cd4ea4f8 100644
--- a/coreapi/linphonecore.h
+++ b/coreapi/linphonecore.h
@@ -594,29 +594,27 @@ int linphone_player_start(LinphonePlayer *obj);
int linphone_player_pause(LinphonePlayer *obj);
int linphone_player_seek(LinphonePlayer *obj, int time_ms);
MSPlayerState linphone_player_get_state(LinphonePlayer *obj);
+int linphone_player_get_duration(LinphonePlayer *obj);
+int linphone_player_get_current_position(LinphonePlayer *obj);
void linphone_player_close(LinphonePlayer *obj);
+void linphone_player_destroy(LinphonePlayer *obj);
/**
* @brief Create an independent media file player.
* This player support WAVE and MATROSKA formats.
- * @param lc A LinphoneCore
+ * @param lc A LinphoneCore object
* @param snd_card Playback sound card. If NULL, the sound card set in LinphoneCore will be used
* @param video_out Video display. If NULL, the video display set in LinphoneCore will be used
+ * @param window_id Pointer on the drawing window
* @return A pointer on the new instance. NULL if faild.
*/
-LINPHONE_PUBLIC LinphonePlayer *linphone_core_create_file_player(LinphoneCore *lc, MSSndCard *snd_card, const char *video_out);
-
-/**
- * @brief Destroy a file player
- * @param obj File player to destroy
- */
-LINPHONE_PUBLIC void linphone_file_player_destroy(LinphonePlayer *obj);
+LINPHONE_PUBLIC LinphonePlayer *linphone_core_create_local_player(LinphoneCore *lc, MSSndCard *snd_card, const char *video_out, void *window_id);
/**
* @brief Check whether Matroksa format is supported by the player
* @return TRUE if it is supported
*/
-LINPHONE_PUBLIC bool_t linphone_file_player_matroska_supported(void);
+LINPHONE_PUBLIC bool_t linphone_local_player_matroska_supported(void);
/**
* LinphoneCallState enum represents the different state a call can reach into.
@@ -642,7 +640,9 @@ typedef enum _LinphoneCallState{
LinphoneCallUpdatedByRemote, /** A text message has been received */
- LinphoneCoreFileTransferRecvCb file_transfer_recv; /** Callback to store file received attached to a #LinphoneChatMessage */
- LinphoneCoreFileTransferSendCb file_transfer_send; /** Callback to collect file chunk to be sent for a #LinphoneChatMessage */
- LinphoneCoreFileTransferProgressIndicationCb file_transfer_progress_indication; /**Callback to indicate file transfer progress*/
- LinphoneCoreNetworkReachableCb network_reachable; /** Call back to report IP network status (I.E up/down)*/
+ LinphoneCoreTextMessageReceivedCb text_received; /**< @deprecated, use #message_received instead
A text message has been received */
+ LinphoneCoreFileTransferRecvCb file_transfer_recv; /**< Callback to store file received attached to a #LinphoneChatMessage */
+ LinphoneCoreFileTransferSendCb file_transfer_send; /**< Callback to collect file chunk to be sent for a #LinphoneChatMessage */
+ LinphoneCoreFileTransferProgressIndicationCb file_transfer_progress_indication; /**< Callback to indicate file transfer progress */
+ LinphoneCoreNetworkReachableCb network_reachable; /**< Callback to report IP network status (I.E up/down )*/
+ LinphoneCoreLogCollectionUploadStateChangedCb log_collection_upload_state_changed; /**< Callback to upload collected logs */
+ LinphoneCoreLogCollectionUploadProgressIndicationCb log_collection_upload_progress_indication; /**< Callback to indicate log collection upload progress */
} LinphoneCoreVTable;
/**
- * Instantiate a vtable with all argument set to NULL
+ * Instantiate a vtable with all arguments set to NULL
* @returns newly allocated vtable
*/
-LINPHONE_PUBLIC LinphoneCoreVTable *linphone_vtable_new();
+LINPHONE_PUBLIC LinphoneCoreVTable *linphone_core_v_table_new();
/**
- * destroy a vtable.
+ * Destroy a vtable.
* @param vtable to be destroyed
*/
-LINPHONE_PUBLIC void linphone_vtable_destroy(LinphoneCoreVTable* table);
+LINPHONE_PUBLIC void linphone_core_v_table_destroy(LinphoneCoreVTable* table);
/**
* @}
@@ -1727,8 +1755,8 @@ LINPHONE_PUBLIC void linphone_vtable_destroy(LinphoneCoreVTable* table);
typedef struct _LCCallbackObj
{
- LinphoneCoreCbFunc _func;
- void * _user_data;
+ LinphoneCoreCbFunc _func;
+ void * _user_data;
}LCCallbackObj;
@@ -1754,6 +1782,56 @@ typedef void * (*LinphoneCoreWaitingCallback)(LinphoneCore *lc, void *context, L
/* THE main API */
+typedef enum _LinphoneLogCollectionState {
+ LinphoneLogCollectionDisabled,
+ LinphoneLogCollectionEnabled,
+ LinphoneLogCollectionEnabledWithoutPreviousLogHandler
+} LinphoneLogCollectionState;
+
+/**
+ * Enable the linphone core log collection to upload logs on a server.
+ * @ingroup misc
+ * @param[in] state LinphoneLogCollectionState value telling whether to enable log collection or not.
+ */
+LINPHONE_PUBLIC void linphone_core_enable_log_collection(LinphoneLogCollectionState state);
+
+/**
+ * Set the path where the log files will be written for log collection.
+ * @ingroup misc
+ * @param[in] path The path where the log files will be written.
+ */
+LINPHONE_PUBLIC void linphone_core_set_log_collection_path(const char *path);
+
+/**
+ * Set the url of the server where to upload the collected log files.
+ * @ingroup misc
+ * @param[in] core LinphoneCore object
+ * @param[in] server_url The url of the server where to upload the collected log files.
+ */
+LINPHONE_PUBLIC void linphone_core_set_log_collection_upload_server_url(LinphoneCore *core, const char *server_url);
+
+/**
+ * Upload the log collection to the configured server url.
+ * @ingroup misc
+ * @param[in] core LinphoneCore object
+ */
+LINPHONE_PUBLIC void linphone_core_upload_log_collection(LinphoneCore *core);
+
+/**
+ * Compress the log collection in a single file.
+ * @ingroup misc
+ * @param[in] core LinphoneCore object
+ * @return The path of the compressed log collection file (to be freed calling ms_free()).
+ */
+LINPHONE_PUBLIC char * linphone_core_compress_log_collection(LinphoneCore *core);
+
+/**
+ * Reset the log collection by removing the log files.
+ * @ingroup misc
+ * @param[in] core LinphoneCore object
+ */
+LINPHONE_PUBLIC void linphone_core_reset_log_collection(LinphoneCore *core);
+
/**
* Define a log handler.
*
@@ -2559,7 +2637,14 @@ LINPHONE_PUBLIC void linphone_core_set_preferred_video_size(LinphoneCore *lc, MS
LINPHONE_PUBLIC void linphone_core_set_preview_video_size(LinphoneCore *lc, MSVideoSize vsize);
LINPHONE_PUBLIC void linphone_core_set_preview_video_size_by_name(LinphoneCore *lc, const char *name);
LINPHONE_PUBLIC MSVideoSize linphone_core_get_preview_video_size(const LinphoneCore *lc);
-LINPHONE_PUBLIC MSVideoSize linphone_core_get_preferred_video_size(LinphoneCore *lc);
+LINPHONE_PUBLIC MSVideoSize linphone_core_get_preferred_video_size(const LinphoneCore *lc);
+
+/**
+ * Get the name of the current preferred video size for sending.
+ * @param[in] lc #LinphoneCore object.
+ * @returns A string containing the name of the current preferred video size (to be freed with ms_free()).
+ */
+LINPHONE_PUBLIC char * linphone_core_get_preferred_video_size_name(const LinphoneCore *lc);
LINPHONE_PUBLIC void linphone_core_set_preferred_video_size_by_name(LinphoneCore *lc, const char *name);
LINPHONE_PUBLIC void linphone_core_set_preferred_framerate(LinphoneCore *lc, float fps);
LINPHONE_PUBLIC float linphone_core_get_preferred_framerate(LinphoneCore *lc);
@@ -2635,7 +2720,7 @@ LINPHONE_PUBLIC void linphone_core_set_native_preview_window_id(LinphoneCore *lc
LINPHONE_PUBLIC void linphone_core_use_preview_window(LinphoneCore *lc, bool_t yesno);
int linphone_core_get_device_rotation(LinphoneCore *lc );
-void linphone_core_set_device_rotation(LinphoneCore *lc, int rotation);
+LINPHONE_PUBLIC void linphone_core_set_device_rotation(LinphoneCore *lc, int rotation);
/**
* Get the camera sensor rotation.
@@ -2974,6 +3059,8 @@ LINPHONE_PUBLIC void linphone_core_set_avpf_mode(LinphoneCore *lc, LinphoneAVPFM
LINPHONE_PUBLIC LinphoneAVPFMode linphone_core_get_avpf_mode(const LinphoneCore *lc);
+LINPHONE_PUBLIC void linphone_core_set_avpf_rr_interval(LinphoneCore *lc, int interval);
+
LINPHONE_PUBLIC int linphone_core_get_avpf_rr_interval(const LinphoneCore *lc);
#ifdef __cplusplus
diff --git a/coreapi/linphonecore_jni.cc b/coreapi/linphonecore_jni.cc
index bcdf0fdf0..241f130cc 100644
--- a/coreapi/linphonecore_jni.cc
+++ b/coreapi/linphonecore_jni.cc
@@ -27,6 +27,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
extern "C" {
#include "mediastreamer2/mediastream.h"
#include "mediastreamer2/mscommon.h"
+#include "mediastreamer2/dsptools.h"
+#include "mediastreamer2/msmediaplayer.h"
}
#include "mediastreamer2/msjava.h"
#include "private.h"
@@ -58,7 +60,8 @@ extern "C" void libmswebrtc_init();
#include
#endif /*ANDROID*/
-
+/*force linking of ms_audio_diff symbol because the tester requires it.*/
+static void *audiodiff=(void*)&ms_audio_diff;
#define RETURN_USER_DATA_OBJECT(javaclass, funcprefix, cobj) \
{ \
@@ -712,7 +715,6 @@ public:
static void infoReceived(LinphoneCore *lc, LinphoneCall*call, const LinphoneInfoMessage *info){
JNIEnv *env = 0;
jint result = jvm->AttachCurrentThread(&env,NULL);
- jobject jcall;
if (result != 0) {
ms_error("cannot attach VM");
return;
@@ -809,9 +811,10 @@ public:
env->CallVoidMethod(lcData->listener, lcData->configuringStateId, lcData->core, env->CallStaticObjectMethod(lcData->configuringStateClass,lcData->configuringStateFromIntId,(jint)status), message ? env->NewStringUTF(message) : NULL);
}
- static void fileTransferProgressIndication(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, size_t progress) {
+ static void fileTransferProgressIndication(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, size_t offset, size_t total) {
JNIEnv *env = 0;
jobject jmsg;
+ size_t progress = (offset * 100) / total;
jint result = jvm->AttachCurrentThread(&env,NULL);
if (result != 0) {
ms_error("cannot attach VM");
@@ -2442,6 +2445,10 @@ extern "C" jfloat Java_org_linphone_core_LinphoneCallImpl_getAverageQuality( JNI
return (jfloat)linphone_call_get_average_quality((LinphoneCall*)ptr);
}
+extern "C" jlong Java_org_linphone_core_LinphoneCallImpl_getPlayer(JNIEnv *env, jobject thiz, jlong callPtr) {
+ return (jlong)linphone_call_get_player((LinphoneCall *)callPtr);
+}
+
//LinphoneFriend
extern "C" jlong Java_org_linphone_core_LinphoneFriendImpl_newLinphoneFriend(JNIEnv* env
,jobject thiz
@@ -2904,7 +2911,7 @@ extern "C" void Java_org_linphone_core_LinphoneChatMessageImpl_startFileDownload
jobject listener = env->NewGlobalRef(jlistener);
LinphoneChatMessage * message = (LinphoneChatMessage *)ptr;
message->cb_ud = listener;
- linphone_chat_message_start_file_download(message, chat_room_impl_callback);
+ linphone_chat_message_start_file_download(message, chat_room_impl_callback, NULL);
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setVideoWindowId(JNIEnv* env
@@ -4047,7 +4054,7 @@ JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneInfoMessageImpl_addHeader(
* Signature: (JLjava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneInfoMessageImpl_getHeader(JNIEnv *env, jobject jobj, jlong infoptr, jstring jname){
- const char *name=name=env->GetStringUTFChars(jname,NULL);
+ const char *name=env->GetStringUTFChars(jname,NULL);
const char *ret=linphone_info_message_get_header((LinphoneInfoMessage*)infoptr,name);
env->ReleaseStringUTFChars(jname,name);
return ret ? env->NewStringUTF(ret) : NULL;
@@ -4719,6 +4726,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceActivityImpl_setDescriptio
const char *cdescription = description ? env->GetStringUTFChars(description, NULL) : NULL;
linphone_presence_activity_set_description(activity, cdescription);
if (cdescription) env->ReleaseStringUTFChars(description, cdescription);
+ return (jint)0;
}
/*
@@ -4770,6 +4778,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceServiceImpl_setId(JNIEnv *
const char *cid = id ? env->GetStringUTFChars(id, NULL) : NULL;
linphone_presence_service_set_id(service, cid);
if (cid) env->ReleaseStringUTFChars(id, cid);
+ return (jint)0;
}
/*
@@ -4815,6 +4824,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceServiceImpl_setContact(JNI
const char *ccontact = contact ? env->GetStringUTFChars(contact, NULL) : NULL;
linphone_presence_service_set_contact(service, ccontact);
if (ccontact) env->ReleaseStringUTFChars(contact, ccontact);
+ return (jint)0;
}
/*
@@ -4905,6 +4915,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_PresencePersonImpl_setId(JNIEnv *e
const char *cid = id ? env->GetStringUTFChars(id, NULL) : NULL;
linphone_presence_person_set_id(person, cid);
if (cid) env->ReleaseStringUTFChars(id, cid);
+ return (jint)0;
}
/*
@@ -5077,6 +5088,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceNoteImpl_setContent(JNIEnv
const char *ccontent = content ? env->GetStringUTFChars(content, NULL) : NULL;
linphone_presence_note_set_content(note, ccontent);
if (ccontent) env->ReleaseStringUTFChars(content, ccontent);
+ return (jint)0;
}
/*
@@ -5100,6 +5112,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceNoteImpl_setLang(JNIEnv *e
const char *clang = lang ? env->GetStringUTFChars(lang, NULL) : NULL;
linphone_presence_note_set_lang(note, clang);
if (clang) env->ReleaseStringUTFChars(lang, clang);
+ return (jint)0;
}
/*
@@ -5208,3 +5221,117 @@ JNIEXPORT jstring JNICALL Java_org_linphone_core_ErrorInfoImpl_getDetails(JNIEnv
}
#endif
+/* Linphone Player */
+struct LinphonePlayerData {
+ LinphonePlayerData(JNIEnv *env, jobject listener, jobject jLinphonePlayer) :
+ mListener(env->NewGlobalRef(listener)),
+ mJLinphonePlayer(env->NewGlobalRef(jLinphonePlayer))
+ {
+ mListenerClass = (jclass)env->NewGlobalRef(env->GetObjectClass(listener));
+ mEndOfFileMethodID = env->GetMethodID(mListenerClass, "endOfFile", "(Lorg/linphone/core/LinphonePlayer;)V");
+ if(mEndOfFileMethodID == NULL) {
+ ms_error("Could not get endOfFile method ID");
+ env->ExceptionClear();
+ }
+ }
+
+ ~LinphonePlayerData() {
+ JNIEnv *env;
+ jvm->AttachCurrentThread(&env, NULL);
+ env->DeleteGlobalRef(mListener);
+ env->DeleteGlobalRef(mListenerClass);
+ env->DeleteGlobalRef(mJLinphonePlayer);
+ }
+
+ jobject mListener;
+ jclass mListenerClass;
+ jobject mJLinphonePlayer;
+ jmethodID mEndOfFileMethodID;
+};
+
+static void _eof_callback(LinphonePlayer *player, void *user_data) {
+ JNIEnv *env;
+ LinphonePlayerData *player_data = (LinphonePlayerData *)user_data;
+ jvm->AttachCurrentThread(&env, NULL);
+ env->CallVoidMethod(player_data->mListener, player_data->mEndOfFileMethodID, player_data->mJLinphonePlayer);
+}
+
+extern "C" jint Java_org_linphone_core_LinphonePlayerImpl_open(JNIEnv *env, jobject jPlayer, jlong ptr, jstring filename, jobject listener) {
+ LinphonePlayerData *data = NULL;
+ LinphonePlayerEofCallback cb = NULL;
+ if(listener) {
+ data = new LinphonePlayerData(env, listener, jPlayer);
+ cb = _eof_callback;
+ }
+ if(linphone_player_open((LinphonePlayer *)ptr, env->GetStringUTFChars(filename, NULL), cb, data) == -1) {
+ if(data) delete data;
+ return -1;
+ }
+ return 0;
+}
+
+extern "C" jint Java_org_linphone_core_LinphonePlayerImpl_start(JNIEnv *env, jobject jobj, jlong ptr) {
+ return (jint)linphone_player_start((LinphonePlayer *)ptr);
+}
+
+extern "C" jint Java_org_linphone_core_LinphonePlayerImpl_pause(JNIEnv *env, jobject jobj, jlong ptr) {
+ return (jint)linphone_player_pause((LinphonePlayer *)ptr);
+}
+
+extern "C" jint Java_org_linphone_core_LinphonePlayerImpl_seek(JNIEnv *env, jobject jobj, jlong ptr, jint timeMs) {
+ return (jint)linphone_player_seek((LinphonePlayer *)ptr, timeMs);
+}
+
+extern "C" jint Java_org_linphone_core_LinphonePlayerImpl_getState(JNIEnv *env, jobject jobj, jlong ptr) {
+ return (jint)linphone_player_get_state((LinphonePlayer *)ptr);
+}
+
+extern "C" jint Java_org_linphone_core_LinphonePlayerImpl_getDuration(JNIEnv *env, jobject jobj, jlong ptr) {
+ return (jint)linphone_player_get_duration((LinphonePlayer *)ptr);
+}
+
+extern "C" jint Java_org_linphone_core_LinphonePlayerImpl_getCurrentPosition(JNIEnv *env, jobject jobj, jlong ptr) {
+ return (jint)linphone_player_get_current_position((LinphonePlayer *)ptr);
+}
+
+extern "C" void Java_org_linphone_core_LinphonePlayerImpl_close(JNIEnv *env, jobject playerPtr, jlong ptr) {
+ LinphonePlayer *player = (LinphonePlayer *)ptr;
+ if(player->user_data) {
+ LinphonePlayerData *data = (LinphonePlayerData *)player->user_data;
+ if(data) delete data;
+ player->user_data = NULL;
+ }
+ linphone_player_close(player);
+}
+
+extern "C" void Java_org_linphone_core_LinphonePlayerImpl_destroy(JNIEnv *env, jobject jobj, jlong playerPtr) {
+ LinphonePlayer *player = (LinphonePlayer *)playerPtr;
+ if(player == NULL) {
+ ms_error("Cannot destroy the LinphonePlayerImpl object. Native pointer is NULL");
+ return;
+ }
+ if(player->user_data) {
+ delete (LinphonePlayerData *)player->user_data;
+ }
+ jobject window_id = (jobject)ms_media_player_get_window_id((MSMediaPlayer *)player->impl);
+ if(window_id) env->DeleteGlobalRef(window_id);
+ linphone_player_destroy(player);
+}
+
+extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_createLocalPlayer(JNIEnv *env, jobject jobj, jlong ptr, jobject window) {
+ jobject window_ref = NULL;
+ MSSndCard *snd_card = ms_snd_card_manager_get_default_playback_card(ms_snd_card_manager_get());
+ if(snd_card == NULL) {
+ ms_error("No default playback sound card found");
+ return 0;
+ }
+ window_ref = env->NewGlobalRef(window);
+ LinphonePlayer *player = linphone_core_create_local_player((LinphoneCore *)ptr, snd_card, "MSAndroidDisplay", window_ref);
+ if(player == NULL) {
+ ms_error("Fails to create a player");
+ if(window_ref) env->DeleteGlobalRef(window_ref);
+ return 0;
+ } else {
+ return (jlong)player;
+ }
+}
diff --git a/coreapi/localplayer.c b/coreapi/localplayer.c
new file mode 100644
index 000000000..ad06e1751
--- /dev/null
+++ b/coreapi/localplayer.c
@@ -0,0 +1,98 @@
+/*
+linphone
+Copyright (C) 2000 - 2010 Simon MORLAT (simon.morlat@linphone.org)
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "private.h"
+#include
+#include
+
+static int _local_player_open(LinphonePlayer *obj, const char *filename);
+static int _local_player_start(LinphonePlayer *obj);
+static int _local_player_pause(LinphonePlayer *obj);
+static int _local_player_seek(LinphonePlayer *obj, int time_ms);
+static MSPlayerState _local_player_get_state(LinphonePlayer *obj);
+static int _local_player_get_duration(LinphonePlayer *obj);
+static int _local_player_get_current_position(LinphonePlayer *obj);
+static void _local_player_close(LinphonePlayer *obj);
+static void _local_player_destroy(LinphonePlayer *obj);
+static void _local_player_eof_callback(void *user_data);
+
+LinphonePlayer *linphone_core_create_local_player(LinphoneCore *lc, MSSndCard *snd_card, const char *video_out, void *window_id) {
+ LinphonePlayer *obj = ms_new0(LinphonePlayer, 1);
+ if(snd_card == NULL) snd_card = lc->sound_conf.play_sndcard;
+ if(video_out == NULL) video_out = linphone_core_get_video_display_filter(lc);
+ obj->impl = ms_media_player_new(snd_card, video_out, window_id);
+ obj->open = _local_player_open;
+ obj->start = _local_player_start;
+ obj->pause = _local_player_pause;
+ obj->seek = _local_player_seek;
+ obj->get_state = _local_player_get_state;
+ obj->get_duration = _local_player_get_duration;
+ obj->get_position = _local_player_get_current_position;
+ obj->close = _local_player_close;
+ obj->destroy = _local_player_destroy;
+ ms_media_player_set_eof_callback((MSMediaPlayer *)obj->impl, _local_player_eof_callback, obj);
+ return obj;
+}
+
+bool_t linphone_local_player_matroska_supported(void) {
+ return ms_media_player_matroska_supported();
+}
+
+static int _local_player_open(LinphonePlayer *obj, const char *filename) {
+ return ms_media_player_open((MSMediaPlayer *)obj->impl, filename) ? 0 : -1;
+}
+
+static int _local_player_start(LinphonePlayer *obj) {
+ return ms_media_player_start((MSMediaPlayer *)obj->impl) ? 0 : -1;
+}
+
+static int _local_player_pause(LinphonePlayer *obj) {
+ ms_media_player_pause((MSMediaPlayer *)obj->impl);
+ return 0;
+}
+
+static int _local_player_seek(LinphonePlayer *obj, int time_ms) {
+ return ms_media_player_seek((MSMediaPlayer *)obj->impl, time_ms) ? 0 : -1;
+}
+
+static MSPlayerState _local_player_get_state(LinphonePlayer *obj) {
+ return ms_media_player_get_state((MSMediaPlayer *)obj->impl);
+}
+
+static int _local_player_get_duration(LinphonePlayer *obj) {
+ return ms_media_player_get_duration((MSMediaPlayer *)obj->impl);
+}
+
+static int _local_player_get_current_position(LinphonePlayer *obj) {
+ return ms_media_player_get_current_position((MSMediaPlayer *)obj->impl);
+}
+
+static void _local_player_destroy(LinphonePlayer *obj) {
+ ms_media_player_free((MSMediaPlayer *)obj->impl);
+ _linphone_player_destroy(obj);
+}
+
+static void _local_player_close(LinphonePlayer *obj) {
+ ms_media_player_close((MSMediaPlayer *)obj->impl);
+}
+
+static void _local_player_eof_callback(void *user_data) {
+ LinphonePlayer *obj = (LinphonePlayer *)user_data;
+ obj->cb(obj, obj->user_data);
+}
diff --git a/coreapi/lpconfig.c b/coreapi/lpconfig.c
index c1ffea0fc..a940fb696 100644
--- a/coreapi/lpconfig.c
+++ b/coreapi/lpconfig.c
@@ -49,7 +49,9 @@
#include
#endif
-
+#ifdef WIN32
+#define RENAME_REQUIRES_NONEXISTENT_NEW_PATH 1
+#endif
#define lp_new0(type,n) (type*)calloc(sizeof(type),n)
@@ -77,6 +79,7 @@ struct _LpConfig{
int refcnt;
FILE *file;
char *filename;
+ char *tmpfilename;
MSList *sections;
int modified;
int readonly;
@@ -349,22 +352,34 @@ LpConfig *lp_config_new_with_factory(const char *config_filename, const char *fa
if (config_filename!=NULL){
ms_message("Using (r/w) config information from %s", config_filename);
lpconfig->filename=ortp_strdup(config_filename);
- lpconfig->file=fopen(config_filename,"r+");
+ lpconfig->tmpfilename=ortp_strdup_printf("%s.tmp",config_filename);
+
+#if !defined(WIN32)
+ {
+ struct stat fileStat;
+ if ((stat(config_filename,&fileStat) == 0) && (S_ISREG(fileStat.st_mode))) {
+ /* make existing configuration files non-group/world-accessible */
+ if (chmod(config_filename, S_IRUSR | S_IWUSR) == -1) {
+ ms_warning("unable to correct permissions on "
+ "configuration file: %s", strerror(errno));
+ }
+ }
+ }
+#endif /*WIN32*/
+ /*open with r+ to check if we can write on it later*/
+ lpconfig->file=fopen(lpconfig->filename,"r+");
+#ifdef RENAME_REQUIRES_NONEXISTENT_NEW_PATH
+ if (lpconfig->file==NULL){
+ lpconfig->file=fopen(lpconfig->tmpfilename,"r+");
+ if (lpconfig->file){
+ ms_warning("Could not open %s but %s works, app may have crashed during last sync.",lpconfig->filename,lpconfig->tmpfilename);
+ }
+ }
+#endif
if (lpconfig->file!=NULL){
lp_config_parse(lpconfig,lpconfig->file);
fclose(lpconfig->file);
-#if !defined(WIN32)
- {
- struct stat fileStat;
- if ((stat(config_filename,&fileStat) == 0) && (S_ISREG(fileStat.st_mode))) {
- /* make existing configuration files non-group/world-accessible */
- if (chmod(config_filename, S_IRUSR | S_IWUSR) == -1) {
- ms_warning("unable to correct permissions on "
- "configuration file: %s", strerror(errno));
- }
- }
- }
-#endif /*WIN32*/
+
lpconfig->file=NULL;
lpconfig->modified=0;
}
@@ -396,6 +411,7 @@ void lp_item_set_value(LpItem *item, const char *value){
static void _lp_config_destroy(LpConfig *lpconfig){
if (lpconfig->filename!=NULL) ortp_free(lpconfig->filename);
+ if (lpconfig->tmpfilename) ortp_free(lpconfig->tmpfilename);
ms_list_for_each(lpconfig->sections,(void (*)(void*))lp_section_destroy);
ms_list_free(lpconfig->sections);
free(lpconfig);
@@ -583,7 +599,7 @@ int lp_config_sync(LpConfig *lpconfig){
/* don't create group/world-accessible files */
(void) umask(S_IRWXG | S_IRWXO);
#endif
- file=fopen(lpconfig->filename,"w");
+ file=fopen(lpconfig->tmpfilename,"w");
if (file==NULL){
ms_warning("Could not write %s ! Maybe it is read-only. Configuration will not be saved.",lpconfig->filename);
lpconfig->readonly=1;
@@ -591,6 +607,16 @@ int lp_config_sync(LpConfig *lpconfig){
}
ms_list_for_each2(lpconfig->sections,(void (*)(void *,void*))lp_section_write,(void *)file);
fclose(file);
+#ifdef RENAME_REQUIRES_NONEXISTENT_NEW_PATH
+ /* On windows, rename() does not accept that the newpath is an existing file, while it is accepted on Unix.
+ * As a result, we are forced to first delete the linphonerc file, and then rename.*/
+ if (remove(lpconfig->filename)!=0){
+ ms_error("Cannot remove %s: %s",lpconfig->filename, strerror(errno));
+ }
+#endif
+ if (rename(lpconfig->tmpfilename,lpconfig->filename)!=0){
+ ms_error("Cannot rename %s into %s: %s",lpconfig->tmpfilename,lpconfig->filename,strerror(errno));
+ }
lpconfig->modified=0;
return 0;
}
diff --git a/coreapi/message_storage.c b/coreapi/message_storage.c
index c87891a34..8cbd088f2 100644
--- a/coreapi/message_storage.c
+++ b/coreapi/message_storage.c
@@ -21,10 +21,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "linphonecore.h"
#ifdef MSG_STORAGE_ENABLED
+#ifndef PRIu64
+#define PRIu64 "I64u"
+#endif
#include "sqlite3.h"
-static inline LinphoneChatMessage* get_transient_message(LinphoneChatRoom* cr, unsigned int storage_id){
+static ORTP_INLINE LinphoneChatMessage* get_transient_message(LinphoneChatRoom* cr, unsigned int storage_id){
MSList* transients = cr->transient_messages;
LinphoneChatMessage* chat;
while( transients ){
@@ -225,7 +228,7 @@ unsigned int linphone_chat_message_store(LinphoneChatMessage *msg){
peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(msg->chat_room));
local_contact=linphone_address_as_string_uri_only(linphone_chat_message_get_local_address(msg));
- buf=sqlite3_mprintf("INSERT INTO history VALUES(NULL,%Q,%Q,%i,%Q,%Q,%i,%i,%Q,%i,%Q,%i);",
+ buf = sqlite3_mprintf("INSERT INTO history VALUES(NULL,%Q,%Q,%i,%Q,%Q,%i,%i,%Q,%lld,%Q,%i);",
local_contact,
peer,
msg->dir,
@@ -234,7 +237,7 @@ unsigned int linphone_chat_message_store(LinphoneChatMessage *msg){
msg->is_read,
msg->state,
msg->external_body_url,
- msg->time,
+ (int64_t)msg->time,
msg->appdata,
content_id
);
@@ -250,8 +253,8 @@ unsigned int linphone_chat_message_store(LinphoneChatMessage *msg){
void linphone_chat_message_store_state(LinphoneChatMessage *msg){
LinphoneCore *lc=msg->chat_room->lc;
if (lc->db){
- char *buf=sqlite3_mprintf("UPDATE history SET status=%i WHERE (id = %i) AND utc = %i;",
- msg->state,msg->storage_id,msg->time);
+ char *buf=sqlite3_mprintf("UPDATE history SET status=%i WHERE (id = %i);",
+ msg->state,msg->storage_id);
linphone_sql_request(lc->db,buf);
sqlite3_free(buf);
}
@@ -459,7 +462,7 @@ static int migrate_messages_timestamp(void* data,int argc, char** argv, char** c
time_t new_time = parse_time_from_db(argv[1]);
if( new_time ){
/* replace 'time' by -1 and set 'utc' to the timestamp */
- char *buf = sqlite3_mprintf("UPDATE history SET utc=%i,time='-1' WHERE id=%i;", new_time, atoi(argv[0]));
+ char *buf = sqlite3_mprintf("UPDATE history SET utc=%lld,time='-1' WHERE id=%i;", new_time, atoi(argv[0]));
if( buf) {
linphone_sql_request((sqlite3*)data, buf);
sqlite3_free(buf);
@@ -486,7 +489,7 @@ static void linphone_migrate_timestamps(sqlite3* db){
uint64_t end;
linphone_sql_request(db, "COMMIT");
end=ortp_get_cur_time_ms();
- ms_message("Migrated message timestamps to UTC in %i ms",(int)(end-begin));
+ ms_message("Migrated message timestamps to UTC in %lu ms",(unsigned long)(end-begin));
}
}
diff --git a/coreapi/misc.c b/coreapi/misc.c
index 30100a304..81365f5a2 100644
--- a/coreapi/misc.c
+++ b/coreapi/misc.c
@@ -250,7 +250,19 @@ bool_t linphone_core_is_payload_type_usable_for_bandwidth(LinphoneCore *lc, cons
/* return TRUE if codec can be used with bandwidth, FALSE else*/
bool_t linphone_core_check_payload_type_usability(LinphoneCore *lc, const PayloadType *pt){
- return linphone_core_is_payload_type_usable_for_bandwidth(lc, pt, linphone_core_get_payload_type_bitrate(lc,pt));
+ bool_t ret=linphone_core_is_payload_type_usable_for_bandwidth(lc, pt, linphone_core_get_payload_type_bitrate(lc,pt));
+ if ((pt->type==PAYLOAD_AUDIO_CONTINUOUS || pt->type==PAYLOAD_AUDIO_PACKETIZED)
+ && lc->sound_conf.capt_sndcard
+ && !(ms_snd_card_get_capabilities(lc->sound_conf.capt_sndcard) & MS_SND_CARD_CAP_BUILTIN_ECHO_CANCELLER)
+ && linphone_core_echo_cancellation_enabled(lc)
+ && (pt->clock_rate!=16000 && pt->clock_rate!=8000)
+ && strcasecmp(pt->mime_type,"opus")!=0
+ && ms_filter_lookup_by_name("MSWebRTCAEC")!=NULL){
+ ms_warning("Payload type %s/%i cannot be used because software echo cancellation is required but is unable to operate at this rate.",
+ pt->mime_type,pt->clock_rate);
+ ret=FALSE;
+ }
+ return ret;
}
bool_t lp_spawn_command_line_sync(const char *command, char **result,int *command_ret){
@@ -966,6 +978,8 @@ unsigned int linphone_core_get_audio_features(LinphoneCore *lc){
else if (strcasecmp(name,"DTMF")==0) ret|=AUDIO_STREAM_FEATURE_DTMF;
else if (strcasecmp(name,"DTMF_ECHO")==0) ret|=AUDIO_STREAM_FEATURE_DTMF_ECHO;
else if (strcasecmp(name,"MIXED_RECORDING")==0) ret|=AUDIO_STREAM_FEATURE_MIXED_RECORDING;
+ else if (strcasecmp(name,"LOCAL_PLAYING")==0) ret|=AUDIO_STREAM_FEATURE_LOCAL_PLAYING;
+ else if (strcasecmp(name,"REMOTE_PLAYING")==0) ret|=AUDIO_STREAM_FEATURE_REMOTE_PLAYING;
else if (strcasecmp(name,"ALL")==0) ret|=AUDIO_STREAM_FEATURE_ALL;
else if (strcasecmp(name,"NONE")==0) ret=0;
else ms_error("Unsupported audio feature %s requested in config file.",name);
diff --git a/coreapi/player.c b/coreapi/player.c
index ed9d4095f..1b2a01022 100644
--- a/coreapi/player.c
+++ b/coreapi/player.c
@@ -71,6 +71,24 @@ MSPlayerState linphone_player_get_state(LinphonePlayer *obj){
return obj->get_state(obj);
}
+/**
+ * Get the duration of the media
+ * @param obj the player
+ * @return The duration in milliseconds
+ */
+int linphone_player_get_duration(LinphonePlayer *obj) {
+ return obj->get_duration(obj);
+}
+
+/**
+ * Get the position of the playback
+ * @param obj the player
+ * @return Position of the playback in milliseconds
+ */
+int linphone_player_get_current_position(LinphonePlayer *obj) {
+ return obj->get_position(obj);
+}
+
/**
* Close the player.
* @param obj the player.
@@ -79,6 +97,18 @@ void linphone_player_close(LinphonePlayer *obj){
return obj->close(obj);
}
+/**
+ * @brief Destroy a player
+ * @param obj The player
+ */
+void linphone_player_destroy(LinphonePlayer *obj) {
+ if(obj->destroy) obj->destroy(obj);
+}
+
+void _linphone_player_destroy(LinphonePlayer *player) {
+ ms_free(player);
+}
+
/*
* Call player implementation below.
@@ -151,7 +181,7 @@ static void call_player_close(LinphonePlayer *player){
}
static void on_call_destroy(void *obj, belle_sip_object_t *call_being_destroyed){
- ms_free(obj);
+ _linphone_player_destroy(obj);
}
LinphonePlayer *linphone_call_build_player(LinphoneCall *call){
diff --git a/coreapi/private.h b/coreapi/private.h
index caa290cb0..8b47ba07e 100644
--- a/coreapi/private.h
+++ b/coreapi/private.h
@@ -125,12 +125,13 @@ struct _LinphoneCallLog{
LinphoneAddress *from; /**
#elif defined(WIN32)
#include
@@ -95,7 +95,7 @@ static gboolean drag_drop(GtkWidget *widget, GdkDragContext *drag_context, gint
}
unsigned long get_native_handle(GdkWindow *gdkw){
-#ifdef __linux
+#ifdef GDK_WINDOWING_X11
return (unsigned long)GDK_WINDOW_XID(gdkw);
#elif defined(WIN32)
return (unsigned long)GDK_WINDOW_HWND(gdkw);
diff --git a/java/common/org/.DS_Store b/java/common/org/.DS_Store
deleted file mode 100644
index 2d8977d32..000000000
Binary files a/java/common/org/.DS_Store and /dev/null differ
diff --git a/java/common/org/linphone/.DS_Store b/java/common/org/linphone/.DS_Store
deleted file mode 100644
index f0988f202..000000000
Binary files a/java/common/org/linphone/.DS_Store and /dev/null differ
diff --git a/java/common/org/linphone/core/LinphoneCall.java b/java/common/org/linphone/core/LinphoneCall.java
index d75f1bbdb..404fdbcf0 100644
--- a/java/common/org/linphone/core/LinphoneCall.java
+++ b/java/common/org/linphone/core/LinphoneCall.java
@@ -119,6 +119,15 @@ public interface LinphoneCall {
*/
public static final State CallReleased = new State(18,"Released");
+ /**
+ * The call is updated by remote while not yet answered (SIP UPDATE in early dialog received)
+ */
+ public static final State CallEarlyUpdatedByRemote = new State(19,"EarlyUpdatedByRemote");
+
+ /**
+ * We are updating the call while not yet answered (SIP UPDATE in early dialog sent)
+ **/
+ public static final State CallEarlyUpdating = new State(20,"EarlyUpdating");
private State(int value,String stringValue) {
mValue = value;
@@ -333,4 +342,11 @@ public interface LinphoneCall {
* @return an Object.
*/
Object getUserData();
+
+ /**
+ * Get a call player
+ * Call player enable to stream a media file through a call
+ * @return A player
+ */
+ public LinphonePlayer getPlayer();
}
diff --git a/java/common/org/linphone/core/LinphoneCore.java b/java/common/org/linphone/core/LinphoneCore.java
index 3a9e1d86d..af878e24f 100644
--- a/java/common/org/linphone/core/LinphoneCore.java
+++ b/java/common/org/linphone/core/LinphoneCore.java
@@ -1781,4 +1781,10 @@ public interface LinphoneCore {
* @return the serverUrl
*/
public String getFileTransferServer();
+
+ /**
+ * Create a media player
+ * @return An object that implement LinphonePlayer
+ */
+ public LinphonePlayer createLocalPlayer(AndroidVideoWindowImpl window);
}
diff --git a/java/common/org/linphone/core/LinphonePlayer.java b/java/common/org/linphone/core/LinphonePlayer.java
new file mode 100644
index 000000000..79d05dbb4
--- /dev/null
+++ b/java/common/org/linphone/core/LinphonePlayer.java
@@ -0,0 +1,95 @@
+/**
+ * Interface to manipulate different media players of Linphone
+ */
+package org.linphone.core;
+
+/**
+ * @author François Grisez
+ *
+ */
+public interface LinphonePlayer {
+ /**
+ * States that the player can be
+ * @author François Grisez
+ *
+ */
+ public enum State {
+ closed, /*< No file is open */
+ paused, /*< A file is open and playback is not running */
+ playing; /*< A file is open and playback is running */
+
+ public static State fromValue(int value) {
+ if(value == 0) {
+ return closed;
+ } else if(value == 1) {
+ return paused;
+ } else if(value == 2) {
+ return playing;
+ } else {
+ return null;
+ }
+ }
+ };
+
+ /**
+ * Listener for Linphone players
+ * @author François Grisez
+ *
+ */
+ public interface Listener {
+ /**
+ * Method called when a player reaches the end of a file
+ * @param player The player which called the method
+ */
+ public void endOfFile(LinphonePlayer player);
+ }
+
+ /**
+ * Open a file
+ * @param filename Name of the file to open
+ * @return 0 on success, -1 on failure
+ */
+ public int open(String filename, Listener listener);
+
+ /**
+ * Start playback
+ * @return 0 on success, -1 on failure
+ */
+ public int start();
+
+ /**
+ * Get playback paused
+ * @return 0 on success, -1 on failure
+ */
+ public int pause();
+
+ /**
+ * Go to a specific position in the timeline
+ * @param timeMs Time in milliseconds
+ * @return 0 on success, -1 on failure
+ */
+ public int seek(int timeMs);
+
+ /**
+ * Get the state of the player
+ * @return See State enumeration
+ */
+ public State getState();
+
+ /**
+ * Get the duration of the media
+ * @return The duration in milliseconds
+ */
+ public int getDuration();
+
+ /**
+ * Get the position of the playback
+ * @return The position in milliseconds
+ */
+ public int getCurrentPosition();
+
+ /**
+ * Close a file
+ */
+ public void close();
+}
diff --git a/java/impl/org/linphone/core/LinphoneCallImpl.java b/java/impl/org/linphone/core/LinphoneCallImpl.java
index ee78e9d89..b2cad202c 100644
--- a/java/impl/org/linphone/core/LinphoneCallImpl.java
+++ b/java/impl/org/linphone/core/LinphoneCallImpl.java
@@ -245,4 +245,10 @@ class LinphoneCallImpl implements LinphoneCall {
public Object getUserData() {
return userData;
}
+
+ private native long getPlayer(long callPtr);
+ @Override
+ public LinphonePlayer getPlayer() {
+ return new LinphonePlayerImpl(getPlayer(nativePtr));
+ }
}
diff --git a/java/impl/org/linphone/core/LinphoneCoreImpl.java b/java/impl/org/linphone/core/LinphoneCoreImpl.java
index 0c53735fc..6e6f5a21f 100644
--- a/java/impl/org/linphone/core/LinphoneCoreImpl.java
+++ b/java/impl/org/linphone/core/LinphoneCoreImpl.java
@@ -25,6 +25,7 @@ import java.io.IOException;
import org.linphone.core.LinphoneCall.State;
import org.linphone.mediastream.Log;
+import org.linphone.mediastream.video.AndroidVideoWindowImpl;
import org.linphone.mediastream.video.capture.hwconf.Hacks;
import android.content.Context;
@@ -1279,4 +1280,14 @@ class LinphoneCoreImpl implements LinphoneCore {
return getFileTransferServer(nativePtr);
}
+ private native long createLocalPlayer(long nativePtr, AndroidVideoWindowImpl window);
+ @Override
+ public synchronized LinphonePlayer createLocalPlayer(AndroidVideoWindowImpl window) {
+ long playerPtr = createLocalPlayer(nativePtr, window);
+ if(playerPtr != 0) {
+ return new LinphonePlayerImpl(playerPtr);
+ } else {
+ return null;
+ }
+ }
}
diff --git a/java/impl/org/linphone/core/LinphonePlayerImpl.java b/java/impl/org/linphone/core/LinphonePlayerImpl.java
new file mode 100644
index 000000000..fe486321e
--- /dev/null
+++ b/java/impl/org/linphone/core/LinphonePlayerImpl.java
@@ -0,0 +1,70 @@
+/**
+ *
+ */
+package org.linphone.core;
+
+/**
+ * @author François Grisez
+ *
+ */
+public class LinphonePlayerImpl implements LinphonePlayer {
+ private long nativePtr = 0;
+
+ LinphonePlayerImpl(long nativePtr) {
+ this.nativePtr = nativePtr;
+ }
+
+ private native int open(long nativePtr, String filename, Listener listener);
+ @Override
+ public synchronized int open(String filename, Listener listener) {
+ return open(nativePtr, filename, listener);
+ }
+
+ private native int start(long nativePtr);
+ @Override
+ public synchronized int start() {
+ return start(nativePtr);
+ }
+
+ private native int pause(long nativePtr);
+ @Override
+ public synchronized int pause() {
+ return pause(nativePtr);
+ }
+
+ private native int seek(long nativePtr, int timeMs);
+ @Override
+ public synchronized int seek(int timeMs) {
+ return seek(nativePtr, timeMs);
+ }
+
+ private native int getState(long nativePtr);
+ @Override
+ public synchronized State getState() {
+ return LinphonePlayer.State.fromValue(getState(nativePtr));
+ }
+
+ private native int getDuration(long nativePtr);
+ @Override
+ public synchronized int getDuration() {
+ return getDuration(nativePtr);
+ }
+
+ private native int getCurrentPosition(long nativePtr);
+ @Override
+ public synchronized int getCurrentPosition() {
+ return getCurrentPosition(nativePtr);
+ }
+
+ private native void close(long nativePtr);
+ @Override
+ public synchronized void close() {
+ close(nativePtr);
+ }
+
+ private native void destroy(long nativePtr);
+ @Override
+ protected void finalize() {
+ destroy(nativePtr);
+ }
+}
diff --git a/mediastreamer2 b/mediastreamer2
index 91f278207..9dd1d9633 160000
--- a/mediastreamer2
+++ b/mediastreamer2
@@ -1 +1 @@
-Subproject commit 91f2782073c776b2d5ce3ab0a12561aea7610068
+Subproject commit 9dd1d9633e66ea018d346cc79a6d93ff6daeddf1
diff --git a/oRTP b/oRTP
index 540ee49bd..90a19604d 160000
--- a/oRTP
+++ b/oRTP
@@ -1 +1 @@
-Subproject commit 540ee49bd3f65139f7e5938cc6bc1f8a4353c3f7
+Subproject commit 90a19604d061d7f23189feb925847e66d366898e
diff --git a/tester/call_tester.c b/tester/call_tester.c
index a2feaab92..62b4d55b5 100644
--- a/tester/call_tester.c
+++ b/tester/call_tester.c
@@ -73,6 +73,8 @@ void call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState
case LinphoneCallIncomingEarlyMedia :counters->number_of_LinphoneCallIncomingEarlyMedia++;break;
case LinphoneCallUpdating :counters->number_of_LinphoneCallUpdating++;break;
case LinphoneCallReleased :counters->number_of_LinphoneCallReleased++;break;
+ case LinphoneCallEarlyUpdating: counters->number_of_LinphoneCallEarlyUpdating++;break;
+ case LinphoneCallEarlyUpdatedByRemote: counters->number_of_LinphoneCallEarlyUpdatedByRemote++;break;
default:
CU_FAIL("unexpected event");break;
}
@@ -215,8 +217,11 @@ bool_t call_with_params2(LinphoneCoreManager* caller_mgr
else {
LinphoneAddress* callee_from=linphone_address_clone(caller_mgr->identity);
linphone_address_set_port(callee_from,0); /*remove port because port is never present in from header*/
+
if (linphone_call_params_get_privacy(linphone_call_get_current_params(linphone_core_get_current_call(caller_mgr->lc))) == LinphonePrivacyNone) {
- CU_ASSERT_TRUE(linphone_address_weak_equal(callee_from,linphone_core_get_current_call_remote_address(callee_mgr->lc)));
+ /*don't check in case of p asserted id*/
+ if (!lp_config_get_int(callee_mgr->lc->config,"sip","call_logs_use_asserted_id_instead_of_from",0))
+ CU_ASSERT_TRUE(linphone_address_weak_equal(callee_from,linphone_core_get_current_call_remote_address(callee_mgr->lc)));
} else {
CU_ASSERT_FALSE(linphone_address_weak_equal(callee_from,linphone_core_get_current_call_remote_address(callee_mgr->lc)));
}
@@ -1903,7 +1908,9 @@ static void call_with_file_player(void) {
snprintf(hellopath,sizeof(hellopath), "%s/sounds/hello8000.wav", liblinphone_tester_file_prefix);
- /*caller uses soundcard*/
+ /*caller uses files instead of soundcard in order to avoid mixing soundcard input with file played using call's player*/
+ linphone_core_use_files(pauline->lc,TRUE);
+ linphone_core_set_play_file(pauline->lc,NULL);
/*callee is recording and plays file*/
linphone_core_use_files(pauline->lc,TRUE);
@@ -1948,7 +1955,9 @@ static void call_with_mkv_file_player(void) {
char hellowav[256];
char *recordpath;
double similar;
-
+
+ ortp_set_log_level_mask(ORTP_ERROR | ORTP_FATAL | ORTP_MESSAGE | ORTP_WARNING);
+
if (!is_format_supported(marie->lc,"mkv")){
ms_warning("Test skipped, no mkv support.");
goto end;
@@ -1960,8 +1969,9 @@ static void call_with_mkv_file_player(void) {
snprintf(hellowav,sizeof(hellowav), "%s/sounds/hello8000.wav", liblinphone_tester_file_prefix);
snprintf(hellomkv,sizeof(hellomkv), "%s/sounds/hello8000.mkv", liblinphone_tester_file_prefix);
- /*caller uses soundcard*/
-
+ /*caller uses files instead of soundcard in order to avoid mixing soundcard input with file played using call's player*/
+ linphone_core_use_files(marie->lc,TRUE);
+ linphone_core_set_play_file(marie->lc,NULL);
/*callee is recording and plays file*/
linphone_core_use_files(pauline->lc,TRUE);
linphone_core_set_play_file(pauline->lc,hellowav); /*just to send something but we are not testing what is sent by pauline*/
@@ -1974,15 +1984,16 @@ static void call_with_mkv_file_player(void) {
if (player){
CU_ASSERT_TRUE(linphone_player_open(player,hellomkv,on_eof,marie)==0);
CU_ASSERT_TRUE(linphone_player_start(player)==0);
+ CU_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&marie->stat.number_of_player_eof,1,12000));
+ linphone_player_close(player);
}
- CU_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&marie->stat.number_of_player_eof,1,12000));
/*just to sleep*/
linphone_core_terminate_all_calls(marie->lc);
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1));
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallEnd,1));
CU_ASSERT_TRUE(ms_audio_diff(hellowav,recordpath,&similar,NULL,NULL)==0);
- CU_ASSERT_TRUE(similar>0.9);
+ CU_ASSERT_TRUE(similar>0.6);
CU_ASSERT_TRUE(similar<=1.0);
ms_free(recordpath);
@@ -2121,6 +2132,10 @@ static void early_media_call_with_ringing(void){
LinphoneCoreManager* pauline = linphone_core_manager_new("pauline_rc");
MSList* lcs = NULL;
LinphoneCall* marie_call;
+ LinphoneCallLog *marie_call_log;
+ time_t connected_time=0;
+ time_t ended_time=0;
+ int dummy=0;
lcs = ms_list_append(lcs,marie->lc);
lcs = ms_list_append(lcs,pauline->lc);
@@ -2134,6 +2149,7 @@ static void early_media_call_with_ringing(void){
linphone_core_set_play_file(pauline->lc,hellopath);
marie_call = linphone_core_invite_address(marie->lc, pauline->identity);
+ marie_call_log = linphone_call_get_call_log(marie_call);
CU_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallIncomingReceived,1,3000));
CU_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallOutgoingRinging,1,1000));
@@ -2151,20 +2167,25 @@ static void early_media_call_with_ringing(void){
linphone_core_accept_call(pauline->lc, linphone_core_get_current_call(pauline->lc));
+ CU_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallConnected, 1,1000));
+ connected_time=time(NULL);
CU_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallStreamsRunning, 1,1000));
CU_ASSERT_EQUAL(marie_call, linphone_core_get_current_call(marie->lc));
liblinphone_tester_check_rtcp(marie, pauline);
+ /*just to have a call duration !=0*/
+ wait_for_list(lcs,&dummy,1,2000);
linphone_core_terminate_all_calls(pauline->lc);
CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallEnd,1,1000));
CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallEnd,1,1000));
-
-
+ ended_time=time(NULL);
+ CU_ASSERT_TRUE (abs (linphone_call_log_get_duration(marie_call_log) - (ended_time - connected_time)) <1 );
ms_list_free(lcs);
}
+
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
}
@@ -2182,7 +2203,6 @@ static void early_media_call_with_update_base(bool_t media_change){
if (media_change) {
disable_all_audio_codecs_except_one(marie->lc,"pcmu",-1);
disable_all_audio_codecs_except_one(pauline->lc,"pcmu",-1);
-
}
/*
Marie calls Pauline, and after the call has rung, transitions to an early_media session
@@ -2213,26 +2233,23 @@ static void early_media_call_with_update_base(bool_t media_change){
linphone_call_params_set_session_name(pauline_params,UPDATED_SESSION_NAME);
linphone_core_update_call(pauline->lc, pauline_call, pauline_params);
+ CU_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallEarlyUpdating,1,2000));
+ CU_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallEarlyUpdatedByRemote,1,2000));
+ CU_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallOutgoingEarlyMedia,1,2000));
+ CU_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallIncomingEarlyMedia,1,2000));
/*just to wait 2s*/
liblinphone_tester_check_rtcp(marie, pauline);
- wait_for_list(lcs, &marie->stat.number_of_LinphoneCallUpdatedByRemote,100000,2000);
CU_ASSERT_STRING_EQUAL( linphone_call_params_get_session_name(linphone_call_get_remote_params(marie_call))
, UPDATED_SESSION_NAME);
linphone_core_accept_call(pauline->lc, linphone_core_get_current_call(pauline->lc));
+ CU_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallConnected, 1,1000));
CU_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallStreamsRunning, 1,1000));
-
- CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallOutgoingEarlyMedia,1);
- CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallStreamsRunning,1);
- CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallConnected,1);
-
- CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCallIncomingEarlyMedia,1);
- CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCallStreamsRunning,1);
- CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCallConnected,1);
- CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCallUpdating,1);
+ CU_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallConnected, 1,1000));
+ CU_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallStreamsRunning, 1,1000));
liblinphone_tester_check_rtcp(marie, pauline);
@@ -3142,6 +3159,45 @@ static void call_with_custom_supported_tags(void) {
}
}
+static void call_log_from_taken_from_p_asserted_id(void) {
+ LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
+ LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
+ LinphoneCall *c1,*c2;
+ LinphoneCallParams *params;
+ const char* paulie_asserted_id ="\"Paupauche\" ";
+ LinphoneAddress *paulie_asserted_id_addr = linphone_address_new(paulie_asserted_id);
+ LpConfig *marie_lp;
+
+ params=linphone_core_create_default_call_parameters(pauline->lc);
+
+ linphone_call_params_add_custom_header(params,"P-Asserted-Identity",paulie_asserted_id);
+ /*fixme, should be able to add several time the same header linphone_call_params_add_custom_header(params,"P-Asserted-Identity","\"Paupauche\" ");*/
+
+ marie_lp = linphone_core_get_config(marie->lc);
+ lp_config_set_int(marie_lp,"sip","call_logs_use_asserted_id_instead_of_from",1);
+
+
+ CU_ASSERT_TRUE(call_with_caller_params(pauline,marie,params));
+ linphone_call_params_destroy(params);
+
+ c1=linphone_core_get_current_call(pauline->lc);
+ c2=linphone_core_get_current_call(marie->lc);
+
+ CU_ASSERT_PTR_NOT_NULL(c1);
+ CU_ASSERT_PTR_NOT_NULL(c2);
+
+ /*make sure remote identity is hidden*/
+ CU_ASSERT_TRUE(linphone_address_weak_equal(linphone_call_get_remote_address(c2),paulie_asserted_id_addr));
+
+
+ /*just to sleep*/
+ linphone_core_terminate_all_calls(pauline->lc);
+ CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1));
+ CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallEnd,1));
+
+ linphone_core_manager_destroy(marie);
+ linphone_core_manager_destroy(pauline);
+}
test_t call_tests[] = {
{ "Early declined call", early_declined_call },
{ "Call declined", call_declined },
@@ -3241,7 +3297,8 @@ test_t call_tests[] = {
{ "Call with in-dialog UPDATE request", call_with_in_dialog_update },
{ "Call with in-dialog codec change", call_with_in_dialog_codec_change },
{ "Call with in-dialog codec change no sdp", call_with_in_dialog_codec_change_no_sdp },
- { "Call with custom supported tags", call_with_custom_supported_tags }
+ { "Call with custom supported tags", call_with_custom_supported_tags },
+ { "Call log from taken from asserted id",call_log_from_taken_from_p_asserted_id}
};
test_suite_t call_test_suite = {
diff --git a/tester/liblinphone_tester.h b/tester/liblinphone_tester.h
index 9178bac8f..18990f313 100644
--- a/tester/liblinphone_tester.h
+++ b/tester/liblinphone_tester.h
@@ -116,6 +116,8 @@ typedef struct _stats {
int number_of_LinphoneCallIncomingEarlyMedia;
int number_of_LinphoneCallUpdating;
int number_of_LinphoneCallReleased;
+ int number_of_LinphoneCallEarlyUpdatedByRemote;
+ int number_of_LinphoneCallEarlyUpdating;
int number_of_LinphoneTransferCallOutgoingInit;
int number_of_LinphoneTransferCallOutgoingProgress;
@@ -224,7 +226,7 @@ void text_message_received(LinphoneCore *lc, LinphoneChatRoom *room, const Linph
void message_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage* message);
void file_transfer_received(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, const char* buff, size_t size);
void file_transfer_send(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, char* buff, size_t* size);
-void file_transfer_progress_indication(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, size_t progress);
+void file_transfer_progress_indication(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, size_t offset, size_t total);
void is_composing_received(LinphoneCore *lc, LinphoneChatRoom *room);
void info_message_received(LinphoneCore *lc, LinphoneCall *call, const LinphoneInfoMessage *msg);
void new_subscription_requested(LinphoneCore *lc, LinphoneFriend *lf, const char *url);
diff --git a/tester/message_tester.c b/tester/message_tester.c
index fcbcf3919..62a365233 100644
--- a/tester/message_tester.c
+++ b/tester/message_tester.c
@@ -117,12 +117,13 @@ void file_transfer_send(LinphoneCore *lc, LinphoneChatMessage *message, const L
/**
* function invoked to report file transfer progress.
* */
-void file_transfer_progress_indication(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, size_t progress) {
+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);
stats* counters = get_stats(lc);
- ms_message(" File transfer [%d%%] %s of type [%s/%s] %s [%s] \n", (int)progress
+ int progress = (int)((offset * 100)/total);
+ ms_message(" File transfer [%d%%] %s of type [%s/%s] %s [%s] \n", progress
,(linphone_chat_message_is_outgoing(message)?"sent":"received")
, content->type
, content->subtype
@@ -237,7 +238,7 @@ static void text_message_with_credential_from_auth_cb_auth_info_requested(Linpho
static void text_message_with_credential_from_auth_cb(void) {
char* to;
LinphoneChatRoom* chat_room;
- LinphoneCoreVTable* vtable = linphone_vtable_new();
+ LinphoneCoreVTable* vtable = linphone_core_v_table_new();
LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
text_message_with_credential_from_auth_cb_auth_info=linphone_auth_info_clone((LinphoneAuthInfo*)(linphone_core_get_auth_info_list(marie->lc)->data));
@@ -479,7 +480,7 @@ static void file_transfer_message(void) {
linphone_chat_room_send_message2(chat_room,message,liblinphone_tester_chat_message_state_change,pauline->lc);
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceivedWithFile,1));
if (marie->stat.last_received_chat_message ) {
- linphone_chat_message_start_file_download(marie->stat.last_received_chat_message, liblinphone_tester_chat_message_state_change);
+ linphone_chat_message_start_file_download(marie->stat.last_received_chat_message, liblinphone_tester_chat_message_state_change, marie->lc);
}
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageExtBodyReceived,1));
@@ -541,7 +542,7 @@ static void lime_file_transfer_message(void) {
linphone_chat_room_send_message2(chat_room,message,liblinphone_tester_chat_message_state_change,pauline->lc);
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceivedWithFile,1));
if (marie->stat.last_received_chat_message ) {
- linphone_chat_message_start_file_download(marie->stat.last_received_chat_message, liblinphone_tester_chat_message_state_change);
+ linphone_chat_message_start_file_download(marie->stat.last_received_chat_message, liblinphone_tester_chat_message_state_change, marie->lc);
}
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageExtBodyReceived,1));
@@ -668,7 +669,7 @@ static void file_transfer_message_io_error_download(void) {
if (marie->stat.last_received_chat_message ) { /* get last message and use it to download file */
- linphone_chat_message_start_file_download(marie->stat.last_received_chat_message, liblinphone_tester_chat_message_state_change);
+ linphone_chat_message_start_file_download(marie->stat.last_received_chat_message, liblinphone_tester_chat_message_state_change, marie->lc);
/* wait for file to be 50% downloaded */
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.progress_of_LinphoneFileTransfer, 50));
/* and simulate network error */
@@ -795,7 +796,7 @@ static void file_transfer_message_download_cancelled(void) {
if (marie->stat.last_received_chat_message ) { /* get last message and use it to download file */
- linphone_chat_message_start_file_download(marie->stat.last_received_chat_message, liblinphone_tester_chat_message_state_change);
+ linphone_chat_message_start_file_download(marie->stat.last_received_chat_message, liblinphone_tester_chat_message_state_change, marie->lc);
/* wait for file to be 50% downloaded */
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.progress_of_LinphoneFileTransfer, 50));
/* and cancel the transfer */
diff --git a/tester/player_tester.c b/tester/player_tester.c
index 59e648340..17e692d23 100644
--- a/tester/player_tester.c
+++ b/tester/player_tester.c
@@ -1,8 +1,44 @@
+/*
+ liblinphone_tester - liblinphone test suite
+ Copyright (C) 2013 Belledonne Communications SARL
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License 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, see .
+*/
+
#include "liblinphone_tester.h"
+static const char *_get_default_video_renderer(void){
+#ifdef WIN32
+ return "MSDrawDibDisplay";
+#elif defined(ANDROID)
+ return "MSAndroidDisplay";
+#elif __APPLE__ && !defined(__ios)
+ return "MSOSXGLDisplay";
+#elif defined (HAVE_XV)
+ return "MSX11Video";
+#elif defined(HAVE_GL)
+ return "MSGLXVideo";
+#elif defined(__ios)
+ return "IOSDisplay";
+#else
+ return "MSVideoOut";
+#endif
+}
+
static bool_t wait_for_eof(bool_t *eof, int *time,int time_refresh, int timeout) {
while(*time < timeout && !*eof) {
- usleep(time_refresh * 1000U);
+ ms_usleep(time_refresh * 1000U);
*time += time_refresh;
}
return *time < timeout;
@@ -23,7 +59,7 @@ static void play_file(const char *filename, bool_t unsupported_format) {
CU_ASSERT_PTR_NOT_NULL(lc_manager);
if(lc_manager == NULL) return;
- player = linphone_core_create_file_player(lc_manager->lc, ms_snd_card_manager_get_default_card(ms_snd_card_manager_get()), video_stream_get_default_video_renderer());
+ player = linphone_core_create_local_player(lc_manager->lc, ms_snd_card_manager_get_default_card(ms_snd_card_manager_get()), _get_default_video_renderer(), NULL);
CU_ASSERT_PTR_NOT_NULL(player);
if(player == NULL) goto fail;
@@ -43,12 +79,12 @@ static void play_file(const char *filename, bool_t unsupported_format) {
linphone_player_close(player);
fail:
- if(player) linphone_file_player_destroy(player);
+ if(player) linphone_player_destroy(player);
if(lc_manager) linphone_core_manager_destroy(lc_manager);
}
static void playing_test(void) {
- play_file("sounds/hello_opus_h264.mkv", !linphone_file_player_matroska_supported());
+ play_file("sounds/hello_opus_h264.mkv", !linphone_local_player_matroska_supported());
}
test_t player_tests[] = {
diff --git a/tester/presence_tester.c b/tester/presence_tester.c
index a1a1b6b63..ca3c8c18e 100644
--- a/tester/presence_tester.c
+++ b/tester/presence_tester.c
@@ -347,6 +347,62 @@ static void presence_information(void) {
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
}
+#define USE_PRESENCE_SERVER 0
+
+#if USE_PRESENCE_SERVER
+static void test_subscribe_notify_publish(void) {
+
+ LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
+ LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
+ LinphoneProxyConfig* proxy;
+ LinphonePresenceModel* presence;
+
+ LpConfig *pauline_lp = linphone_core_get_config(pauline->lc);
+ char* lf_identity=linphone_address_as_string_uri_only(marie->identity);
+ LinphoneFriend *lf = linphone_core_create_friend_with_address(pauline->lc,lf_identity);
+
+ lp_config_set_int(pauline_lp,"sip","subscribe_expires",5);
+
+ linphone_core_add_friend(pauline->lc,lf);
+
+ /*wait for subscribe acknowledgment*/
+ wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_NotifyReceived,1,2000);
+ CU_ASSERT_EQUAL(LinphoneStatusOffline,linphone_friend_get_status(lf));
+
+ /*enable publish*/
+
+ linphone_core_get_default_proxy(marie->lc,&proxy);
+ linphone_proxy_config_edit(proxy);
+
+ linphone_proxy_config_enable_publish(proxy,TRUE);
+ linphone_proxy_config_set_publish_expires(proxy,3);
+ linphone_proxy_config_done(proxy);
+
+ /*wait for marie status*/
+ wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_NotifyReceived,2,2000);
+ CU_ASSERT_EQUAL(LinphoneStatusOnline,linphone_friend_get_status(lf));
+
+ presence =linphone_presence_model_new_with_activity(LinphonePresenceActivityOffline,NULL);
+ linphone_core_set_presence_model(marie->lc,presence);
+
+ /*wait for new status*/
+ wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_NotifyReceived,3,2000);
+ CU_ASSERT_EQUAL(LinphonePresenceActivityOffline,linphone_friend_get_status(lf));
+
+ /*wait for refresh*/
+ wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_NotifyReceived,4,5000);
+ CU_ASSERT_EQUAL(LinphonePresenceActivityOffline,linphone_friend_get_status(lf));
+
+ //linphone_core_remove_friend(pauline->lc,lf);
+ /*wait for final notify*/
+ //wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_NotifyReceived,4,5000);
+ //CU_ASSERT_EQUAL(LinphonePresenceActivityOffline,linphone_friend_get_status(lf));
+
+ linphone_core_manager_destroy(marie);
+ linphone_core_manager_destroy(pauline);
+}
+
+#endif
test_t presence_tests[] = {
{ "Simple Subscribe", simple_subscribe },
@@ -356,6 +412,9 @@ test_t presence_tests[] = {
{ "Unsubscribe while subscribing", unsubscribe_while_subscribing },
{ "Presence information", presence_information },
{ "App managed presence failure", subscribe_failure_handle_by_app },
+#if USE_PRESENCE_SERVER
+ { "Subscribe with late publish", test_subscribe_notify_publish },
+#endif
};
test_suite_t presence_test_suite = {
diff --git a/tester/rcfiles/laure_rc b/tester/rcfiles/laure_rc
index 54a682401..7f4d099f5 100644
--- a/tester/rcfiles/laure_rc
+++ b/tester/rcfiles/laure_rc
@@ -38,4 +38,7 @@ automatically_accept=0
device=StaticImage: Static picture
[sound]
-echocancellation=0 #to not overload cpu in case of VG
\ No newline at end of file
+echocancellation=0 #to not overload cpu in case of VG
+
+[net]
+dns_srv_enabled=0 #no srv needed in general
\ No newline at end of file
diff --git a/tester/rcfiles/marie_rc b/tester/rcfiles/marie_rc
index f4f9aa793..a1721c22a 100644
--- a/tester/rcfiles/marie_rc
+++ b/tester/rcfiles/marie_rc
@@ -48,3 +48,6 @@ device=StaticImage: Static picture
[sound]
echocancellation=0 #to not overload cpu in case of VG
+
+[net]
+dns_srv_enabled=0 #no srv needed in general
diff --git a/tester/rcfiles/pauline_rc b/tester/rcfiles/pauline_rc
index 09669b72c..7322fd99a 100644
--- a/tester/rcfiles/pauline_rc
+++ b/tester/rcfiles/pauline_rc
@@ -45,3 +45,6 @@ device=StaticImage: Static picture
[sound]
echocancellation=0 #to not overload cpu in case of VG
+
+[net]
+dns_srv_enabled=0 #no srv needed in general
\ No newline at end of file
diff --git a/tester/register_tester.c b/tester/register_tester.c
index d47ffa2df..907a10db7 100644
--- a/tester/register_tester.c
+++ b/tester/register_tester.c
@@ -36,7 +36,7 @@ static LinphoneCoreManager* create_lcm_with_auth(unsigned int with_auth) {
LinphoneCoreManager* mgr=linphone_core_manager_new(NULL);
if (with_auth) {
- LinphoneCoreVTable* vtable = linphone_vtable_new();
+ LinphoneCoreVTable* vtable = linphone_core_v_table_new();
vtable->auth_info_requested=auth_info_requested;
linphone_core_add_listener(mgr->lc,vtable);
}
@@ -314,7 +314,7 @@ static void ha1_authenticated_register(){
static void authenticated_register_with_no_initial_credentials(){
LinphoneCoreManager *mgr;
- LinphoneCoreVTable* vtable = linphone_vtable_new();
+ LinphoneCoreVTable* vtable = linphone_core_v_table_new();
stats* counters;
char route[256];
diff --git a/tester/sounds/hello8000.mkv b/tester/sounds/hello8000.mkv
index 42fa387e5..812d62563 100644
Binary files a/tester/sounds/hello8000.mkv and b/tester/sounds/hello8000.mkv differ
diff --git a/tools/generator.cc b/tools/generator.cc
index 82f50c660..2b8ab0a39 100644
--- a/tools/generator.cc
+++ b/tools/generator.cc
@@ -52,7 +52,7 @@ void CplusplusGenerator::generate(Project *proj){
void CplusplusGenerator::writeEnumMember(ConstField *cf, bool isLast){
writeTabs(1);
- mOutfile<getName();
+ mOutfile<getName()<<"="<getValue();
if (!isLast) mOutfile<<",";
if (!cf->getHelp().empty()) mOutfile<<"\t/**< "<getHelp()<<" */";
mOutfile< members=klass->getConstFields();
list::iterator it;
string enum_name=getEnumName(klass);
- int value=0;
filename<getName())<<"/"<getHelp().empty()){
writeTabs(1);
@@ -254,7 +253,7 @@ void JavascriptGenerator::writeEnum(Class *klass){
mOutfile<<"*/"<getName().substr(prefix_size,string::npos)<<" : "<getName().substr(prefix_size,string::npos)<<" : "<getValue();
if (++it!=members.end()) mOutfile<<",";
mOutfile<setHelp(node.getChild("detaileddescription").getChild("para").getText());
list enumValues=node.getChildren("enumvalue");
list::iterator it;
+ int value = 0;
for (it=enumValues.begin();it!=enumValues.end();++it){
- ConstField *cf=new ConstField(Type::getType("int"),(*it).getChild("name").getText());
+ string initializer = (*it).getChild("initializer").getText();
+ if ((initializer.length() > 1) && (initializer.at(0) == '=')) {
+ std::stringstream ss;
+ if ((initializer.length() > 2) && (initializer.at(1) == '0')) {
+ if ((initializer.length() > 3) && (initializer.at(2) == 'x')) {
+ ss << std::hex << initializer.substr(3);
+ } else {
+ ss << std::oct << initializer.substr(2);
+ }
+ } else {
+ ss << std::dec << initializer.substr(1);
+ }
+ ss >> value;
+ }
+ ConstField *cf=new ConstField(Type::getType("int"),(*it).getChild("name").getText(),value);
cf->setHelp((*it).getChild("detaileddescription").getChild("para").getText());
klass->addConstField(cf);
-
+ value++;
}
}
diff --git a/tools/python/apixml2python.py b/tools/python/apixml2python.py
index b8f1bff2f..357816a5a 100755
--- a/tools/python/apixml2python.py
+++ b/tools/python/apixml2python.py
@@ -48,6 +48,7 @@ blacklisted_functions = [
'linphone_chat_room_create_file_transfer_message', # missing LinphoneContent
'linphone_core_add_listener',
'linphone_core_can_we_add_call', # private function
+ 'linphone_core_enable_log_collection', # need to handle class properties
'linphone_core_get_audio_port_range', # to be handwritten because of result via arguments
'linphone_core_get_sip_transports', # missing LCSipTransports
'linphone_core_get_sip_transports_used', # missing LCSipTransports
@@ -57,6 +58,7 @@ blacklisted_functions = [
'linphone_core_publish', # missing LinphoneContent
'linphone_core_remove_listener',
'linphone_core_serialize_logs', # There is no use to wrap this function
+ 'linphone_core_set_log_collection_path', # need to handle class properties
'linphone_core_set_log_file', # There is no use to wrap this function
'linphone_core_set_log_handler', # Hand-written but put directly in the linphone module
'linphone_core_set_log_level', # There is no use to wrap this function
diff --git a/tools/software-desc.hh b/tools/software-desc.hh
index 2d454e502..575f52fb0 100644
--- a/tools/software-desc.hh
+++ b/tools/software-desc.hh
@@ -294,7 +294,7 @@ private:
class ConstField{
public:
- ConstField(Type *type, const string &name, const string &value="") : mType(type), mName(name), mValue(value){
+ ConstField(Type *type, const string &name, int value) : mType(type), mName(name), mValue(value){
}
void setHelp(const string & help){
mHelp=help;
@@ -308,7 +308,7 @@ public:
Type *getType()const{
return mType;
}
- const string &getValue()const{
+ int getValue()const{
return mValue;
}
static string getCommonPrefix(list fields){
@@ -338,7 +338,7 @@ public:
private:
Type *mType;
string mName;
- string mValue;
+ int mValue;
string mHelp;
};